Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion 08_1_Sending_a_Transaction_with_a_Locktime.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Once you've figured out the current height, you can decide how far in the future

Once you have figured out your locktime, all you need to do is write up a typical raw transaction, with a third variable for `locktime`:
```
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.001, "'$changeaddress'": 0.00095 }''' locktime=1774650)
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''[{ "'$recipient'": 0.001, "'$changeaddress'": 0.00095 }]''' locktime=1774650)
```
Note that this usage of `locktime` is under 500 million, which means that it defines a block height. In this case, it's just a few blocks past the current block height at the time of this writing, meant to exemplify how locktime works without sitting around for a long time to wait and see what happens.

Expand Down
14 changes: 8 additions & 6 deletions 11_3_Using_CSV_in_Scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ A relative timelock is a lock that's placed on a specific input of a transaction

Easy!

> :information_source: **NOTE — SEQUENCE:** This is the third use of the `nSequence` value in Bitcoin. Any `nSequence` value without the 32nd bit set (1<<31), so 0x00000001 to 0x7ffffffff, will be interpreted as a relative timelock if `nVersion ≥ 2` (which is the default starting in Bitcoin Core 0.14.0). You should be careful to ensure that relative timelocks don't conflict with the other two uses of `nSequence`, for signalling `nTimeLock` and RBF. `nTimeLock` usually sets a value of 0xffffffff-1, where a relative timelock is disallowed; and RBF usually sets a value of "1", where a relative timelock is irrelevent, because it defines a timelock of 1 block.
> :information_source: **NOTE — SEQUENCE:** This is the third use of the `nSequence` value in Bitcoin. Any `nSequence` value without the 32nd bit set (1<<31), so 0x00 00 00 01 to 0x7f ff ff ff, will be interpreted as a relative timelock if `nVersion ≥ 2` (which is the default starting in Bitcoin Core 0.14.0). You should be careful to ensure that relative timelocks don't conflict with the other two uses of `nSequence`, for signalling `nLockTime` and RBF. `nLockTime` usually sets a value of 0xff ff ff ff-1, where a relative timelock is disallowed; and RBF usually sets a value of "1", where a relative timelock is irrelevent, because it defines a timelock of 1 block.

> In general, remember: with a `nVersion` value of 2, a `nSequence` value of 0x00000001 to 0x7fffffff allows relative timelock, RBF, and `nTimeLock`; a `nSequence` value of 0x7fffffff to 0xffffffff-2 allows RBF and `nTimeLock`; a `nSequence` value of 0xffffffff-1 allows only `nTimeLock`; a `nSequence` value of 0xffffffff allows none; and `nVersion` can be set to 1 to disallow relative timelocks for any value of `nSequence`. Whew!
> In general, remember: with a `nVersion` value of 2, a `nSequence` value of 0x00 00 00 01 to 0x7f ff ff ff allows relative timelock, RBF, and `nLockTime`; a `nSequence` value of 0x7f ff ff ff to 0xff ff ff ff-2 allows RBF and `nLockTime`; a `nSequence` value of 0xff ff ff ff-1 allows only `nLockTime`; a `nSequence` value of 0xff ff ff ff allows none; and `nVersion` can be set to 1 to disallow relative timelocks for any value of `nSequence`. Whew!

### Create a CSV Relative Block Time

The format for using `nSequence` to represent relative time locks is defined in [BIP 68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki) and is slightly more complex than just inputting a number, like you did for `nTimeLock`. Instead, the BIP specifications breaks up the four byte number into three parts:
The format for using `nSequence` to represent relative time locks is defined in [BIP 68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki) and is slightly more complex than just inputting a number, like you did for `nLockTime`. Instead, the BIP specifications breaks up the four byte number into three parts:

* The first two bytes are used to specify a relative locktime.
* The 23rd bit is used to positively signal if the lock refers to a time rather than a blockheight.
* The 32nd bit is used to positively signal if relative timelocks are deactivated.

With that said, the construction of a block-based relative timelock is still quite easy, because the two flagged bits are set to `0`, so you just set `nSequence` to a value between 1 and 0xffff (65535). The new transaction can be mined that number of blocks after the associated UTXO was mined.
With that said, the construction of a block-based relative timelock is still quite easy, because the two flagged bits are set to `0`, so you just set `nSequence` to a value between 1 and 0xff ff (65535). The new transaction can be mined that number of blocks after the associated UTXO was mined.

### Create a CSV Relative Time

Expand All @@ -51,6 +51,8 @@ Finally, bitwise-or the 23rd bit into the hex value you created:
```
$ relativevalue=$(printf '%x\n' $((0x$hexvalue | 0x400000)))
$ echo $relativevalue
4076a7
$ printf "%d\n" "0x$relativevalue"
4224679
```
If you convert that back you'll see that 4224679 = 10000000111011010100111. The 23rd digit is set to a "1"; meanwhile the first 2 bytes, 0111011010100111, convert to 76A7 in hex or 30375 in decimal. Multiply that by 512 and you get 15.55 million seconds, which indeed is 180 days.
Expand All @@ -65,7 +67,7 @@ Except pretty much no one does this. The [BIP 68](https://github.com/bitcoin/bip

| | Absolute Timelock | Relative Timelock |
|:--------------------:|-------------------|-------------------|
| **Lock Transaction** | nTimeLock | nSequence |
| **Lock Transaction** | nLockTime | nSequence |
| **Lock Output** | OP_CHECKLOCKTIMEVERIFY| OP_CHECKSEQUENCEVERIFY |

## Understand the CSV Opcode
Expand Down Expand Up @@ -93,7 +95,7 @@ CSV has many of the same subtleties in usage as CLTV:

* The `nVersion` field must be set to 2 or more.
* The `nSequence` field must be set to less than 0x80000000.
* When CSV is run, there must be an operand on the stack that's between 0 and 0xf0000000-1.
* When CSV is run, there must be an operand on the stack that's between 0 and 0xf0 00 00 00-1.
* Both the stack operand and `nSequence` must have the same value on the 23rd bit.
* The `nSequence` must be greater than or equal to the stack operand.

Expand Down
4 changes: 2 additions & 2 deletions 12_1_Using_Script_Conditionals.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ ELSE
ENDIF

```
Remember your reverse Polish notation! That `IF` statement if referring to the `OP_EQUAL` before it, not the `OP_CHECKSIG` after it!
Remember your reverse Polish notation! That `IF` statement is referring to the `OP_EQUAL` before it, not the `OP_CHECKSIG` after it!

#### Run the True Branch

Expand Down Expand Up @@ -136,7 +136,7 @@ Stack: [ True ]
```
#### Run the False Branch

Here's how it actally runs if unlocked with `<signatureB> <pubKeyB>`:
Here's how it actually runs if unlocked with `<signatureB> <pubKeyB>`:
```
Script: <signatureB> <pubKeyB> OP_DUP OP_HASH160 <pubKeyHashA> OP_EQUAL IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Stack: [ ]
Expand Down
2 changes: 1 addition & 1 deletion 12_2_Using_Other_Script_Commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Also see: `OP_CODESEPARATOR` (0xab), `OP_CHECKSIGVERIFY` (0xad), and `OP_CHECKMU

## Summary: Using Other Script Commands

Bitcoin Script includes a wide array of arithemetic, stack, and cryptographic opcodes. Most of these additional opcodes are probably not as common as the ones discussed in previous sections, but nonetheless they're available if they're just what you need to write your Script!
Bitcoin Script includes a wide array of arithmetic, stack, and cryptographic opcodes. Most of these additional opcodes are probably not as common as the ones discussed in previous sections, but nonetheless they're available if they're just what you need to write your Script!

## What's Next?

Expand Down
2 changes: 1 addition & 1 deletion 13_0_Designing_Real_Bitcoin_Scripts.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Chapter 13: Designing Real Bitcoin Scripts

Our Bitcoin Scripts to date have been largely theoretical examples, because we've still been putting together the puzzle pieces. Now, with the full Bitcoin Script repetoire in hand, we're ready to dig into several real-world Bitcoin Scripts and see how they work.
Our Bitcoin Scripts to date have been largely theoretical examples, because we've still been putting together the puzzle pieces. Now, with the full Bitcoin Script repertoire in hand, we're ready to dig into several real-world Bitcoin Scripts and see how they work.

## Objectives for This Chapter

Expand Down
2 changes: 1 addition & 1 deletion 14_2_Changing_Your_Bitcoin_Hidden_Services.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ See [Bitcoin Onion Nodes](https://github.com/emmanuelrosa/bitcoin-onion-nodes) f

Afterward, restart `tor` and `bitcoind`.

You should now be communicating exlusively on Tor. But, unless you are in a hostile state, this level of anonymity is probably not required. It also is not particularly recommended: you might greatly decrease your number of potential peers, inviting problems of censorship or even correlation. You may also see lag. And, this setup may give you a false sense of anonymity that really doesn't exist on the Bitcoin network.
You should now be communicating exclusively on Tor. But, unless you are in a hostile state, this level of anonymity is probably not required. It also is not particularly recommended: you might greatly decrease your number of potential peers, inviting problems of censorship or even correlation. You may also see lag. And, this setup may give you a false sense of anonymity that really doesn't exist on the Bitcoin network.

> :warning: **WARNING:** This setup is untested! Use at your own risk!

Expand Down
2 changes: 1 addition & 1 deletion 17_4_Using_PSBTs_in_Libwally.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ The creator role is tasked with creating a PSBT with at least one input.
A PSBT is created with a simple use of `wally_psbt_init_alloc`, telling it how many inputs and outputs you will eventually add:
```
struct wally_psbt *psbt;
lw_response = wally_psbt_init_alloc(0,1,1,0,&psbt);
lw_response = wally_psbt_init_alloc(0,1,1,0,0,&psbt);
```
But what you have is not yet a legal PSBT, because of the lack of inputs. You can create those by creating a transaction and setting it as the global transaction in the PSBT, which updates all the inputs and outputs:
```
Expand Down
2 changes: 1 addition & 1 deletion 17_5_Using_Scripts_in_Libwally.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ a9 / 14 / 3f58b4f7b14847a9083694b9b3b52a4cea2569ed / 87
```
That's our old friend `OP_HASH160 3f58b4f7b14847a9083694b9b3b52a4cea2569ed OP_EQUAL`.

Basically, Libwally took your serialized redeem script, hashed it for you with SHA-256 and RIPEMD-160, and the applied the standard framing to turn it into a proper P2SH; You did similar work in [§10.2](10_2_Building_the_Structure_of_P2SH.md), but with an excess of shell commands.
Basically, Libwally took your serialized redeem script, hashed it for you with SHA-256 and RIPEMD-160, and then applied the standard framing to turn it into a proper P2SH; You did similar work in [§10.2](10_2_Building_the_Structure_of_P2SH.md), but with an excess of shell commands.

In fact, you can double-check your work using the same commands from §10.2:
```
Expand Down
1 change: 0 additions & 1 deletion 17_7_Integrating_Libwally_and_Bitcoin-CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,6 @@ $ bitcoin-cli getaddressesbylabel "LibwallyWO"
"purpose": "receive"
}
}
}
```

## Summary: Integrating Libwally and Bitcoin-CLI
Expand Down
2 changes: 1 addition & 1 deletion 18_1_Accessing_Bitcoind_with_Go.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ tb1qutkcj34pw0aq7n9wgp3ktmz780szlycwddfmza

### Decode an Address

Creating an address took a look extra work, in specifying the appropiate chain. Using an address also will because you'll have to decode it prior to use.
Creating an address took a little extra work, in specifying the appropriate chain. Using an address also will because you'll have to decode it prior to use.

The means that you'll have to import both the ```"github.com/btcsuite/btcutil"``` and ```"github.com/btcsuite/btcd/chaincfg"``` libraries.
* ```btcutil``` allows for a Bitcoin address to be decoded in a way that the`rpcclient` can understand. This is necessary when working with addresses in `rpcclient`.
Expand Down
2 changes: 1 addition & 1 deletion 18_3_Accessing_Bitcoind_with_NodeJS.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Obviously, your `user` and `pass` should again match what's in your `~/.bitcoin/

Using BCRPC, you can use the same RPC commands you would usually use via ```bitcoin-cli``` with your `RpcAgent`, except they need to be in camelCase. For example, ```getblockhash``` would be ```getBlockHash``` instead.

To print the newest block number, you just call `getBlockCount` thourgh your `RpcAgent`:
To print the newest block number, you just call `getBlockCount` through your `RpcAgent`:

```
agent.getBlockCount(function (err, blockCount) {
Expand Down
4 changes: 2 additions & 2 deletions 18_4_Accessing_Bitcoind_with_Python.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import logging
```
`pprint` will pretty print the `json` response from `bitcoind`.

`logging` will print out the call you make to `bitcoind` and `bitcoind`'s respose, which is useful when you make a bunch of calls together. If you don't want the excessive output in the terminal just comment out the `logging` block.
`logging` will print out the call you make to `bitcoind` and `bitcoind`'s response, which is useful when you make a bunch of calls together. If you don't want the excessive output in the terminal just comment out the `logging` block.

## Build Your Connection

Expand Down Expand Up @@ -357,7 +357,7 @@ There are five steps:

### 1. Select UTXO & Set Transaction Details

In the folowing code snippet you first select the UTXO which we want to spend. Then you get its address, transaction id, and the vector index of the output.
In the following code snippet you first select the UTXO which we want to spend. Then you get its address, transaction id, and the vector index of the output.

```py
utxos = rpc_client.listunspent()
Expand Down
2 changes: 1 addition & 1 deletion 18_6_Accessing_Bitcoind_with_Swift.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ rpcpassword=ebVCeSyyM0LurvgQyi0exWTqm4oU0rZU
```
## Build Your Connection by Hand

At the time of this writing, there isn't an up-to-date, simple-to-use Bitcoin RPC Library that's specific for Swift, something that you can drop in and immediately start using. Thus, you're're going to do something you're never done before: build an RPC connection by hand.
At the time of this writing, there isn't an up-to-date, simple-to-use Bitcoin RPC Library that's specific for Swift, something that you can drop in and immediately start using. Thus, you're going to do something you're never done before: build an RPC connection by hand.

### Write the RPC Transmitter

Expand Down
Binary file added Bitcoin_Command_line.epub
Binary file not shown.
12 changes: 6 additions & 6 deletions src/04_2_i_txfee-calc.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#!/bin/bash

if [ -z $1 ];
if [ -z "$1" ];
then
echo "You must include the raw transaction hex as an argument.";
exit;
fi

usedtxid=($(bitcoin-cli decoderawtransaction $1 | jq -r '.vin | .[] | .txid'))
usedvout=($(bitcoin-cli decoderawtransaction $1 | jq -r '.vin | .[] | .vout'))
btcin=$(for ((i=0; i<${#usedtxid[*]}; i++)); do txid=${usedtxid[i]}; vout=${usedvout[i]}; bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${txid}'")) | select(.vout | contains('$vout')) | .amount'; done | awk '{s+=$1} END {print s}')
btcout=$(bitcoin-cli decoderawtransaction $1 | jq -r '.vout [] | .value' | awk '{s+=$1} END {print s}')
btcout_f=$(awk -v btcout="$btcout" 'BEGIN { printf("%f\n", btcout) }' </dev/null)
mapfile -t usedtxid < <(bitcoin-cli decoderawtransaction "$1" | jq -r '.vin | .[] | .txid')
mapfile -t usedvout < <(bitcoin-cli decoderawtransaction "$1" | jq -r '.vin | .[] | .vout')
btcin=$(for ((i=0; i<${#usedtxid[*]}; i++)); do txid=${usedtxid[i]}; vout=${usedvout[i]}; bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'"${txid}"'")) | select(.vout | contains('"$vout"')) | .amount'; done | awk '{s+=$1} END {printf "%.8f\n, s}')
btcout=$(bitcoin-cli decoderawtransaction "$1" | jq -r '.vout [] | .value' | awk '{s+=$1} END {printf "%.8f\n, s}')
btcout_f=$(awk -v btcout="$btcout" 'BEGIN { printf("%.8f\n", btcout) }' </dev/null)
echo "$btcin-$btcout_f"| /usr/bin/bc
2 changes: 1 addition & 1 deletion src/17_4_createemptypsbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ int main(void) {

char *psbt_64;

lw_response = wally_psbt_init_alloc(0,1,1,0,&psbt);
lw_response = wally_psbt_init_alloc(0,1,1,0,0,&psbt);

if (lw_response) {

Expand Down
2 changes: 1 addition & 1 deletion src/17_4_examinepsbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ int main(int argc, char *argv[]) {

struct wally_psbt *psbt;

lw_response = wally_psbt_from_base64(psbt_64,&psbt);
lw_response = wally_psbt_from_base64(psbt_64,WALLY_PSBT_PARSE_FLAG_STRICT,&psbt);

if (lw_response) {

Expand Down