|
|
@ -7,39 +7,42 @@ Nodar Chkuaselidze |
|
|
|
## How It Works |
|
|
|
#### General |
|
|
|
In bitcoin there are several transaction types and one of them is Multisig. Multisig addresses and transactions are created |
|
|
|
from multiple private keys and can be used in multiple situations. For example, you can secure your fund using multiple |
|
|
|
from multiple private keys and can be used in multiple situations. For example, you can secure your funds using multiple |
|
|
|
keys on multiple devices. If you want to spend transactions received on multisig address, you'll need to sign transactions |
|
|
|
on both devices. Also in large companies, where several people are in charge of funds, they can create multisig addresses for |
|
|
|
company, where several people will have to sign the transaction in order to spend. This will improve security of the funds |
|
|
|
for outside threat as well as inside threat (No one will be able to spend tx on its own). You can check other multisig |
|
|
|
applications on [wiki][multisig-apps]. |
|
|
|
on both devices. As another example, in large companies where several people are in charge of funds, |
|
|
|
they can create multisig addresses for company funds where you have multiple signatories. |
|
|
|
This will improve the security of the funds from both internal and external threats since no one can |
|
|
|
send a tx without the approval of other signatories. More examples of multisig applications can be |
|
|
|
found on the [wiki][multisig-apps]. |
|
|
|
|
|
|
|
|
|
|
|
#### Definition |
|
|
|
Multisig transactions have `m-of-n` form, where `m` stands for number of signatures required to spend funds and `n` stands |
|
|
|
Multisig transactions have an `m-of-n` form, where `m` stands for number of signatures required to spend funds and `n` stands |
|
|
|
for maximum number of pubkeys that are permitted to sign (`m <= n`). You can check the motivation |
|
|
|
and specification in [BIP11][]. We'll also be using [Pay to Script Hash(P2SH)][BIP16] format for script |
|
|
|
and [Its address format][BIP13] for our addresses and for receiving the transactions. |
|
|
|
and specification in [BIP11][]. We'll also be using the [Pay-to-Script-Hash(P2SH)][BIP16] format for the script |
|
|
|
and [its address format][BIP13] for our addresses and for receiving the transactions. |
|
|
|
|
|
|
|
|
|
|
|
#### Address Creation |
|
|
|
When you want to create multisig address, first you need to aggree on numbers in `m-of-n`. If someone chooses |
|
|
|
different `m` or different `n`, they'll end up with different address. You also need to know pubkey for all cosigners. |
|
|
|
You can share these pubkeys however you want. Wallets support various ways for sharing pubkeys, using QR Code |
|
|
|
When you want to create a multisig address, first you need to aggree on the numbers in `m-of-n`. If one of the |
|
|
|
signatories chooses a different `m` or a different `n`, they'll end up with different addresses. |
|
|
|
You also need to know the pubkey for all cosigners. |
|
|
|
You can share these pubkeys however you want. Wallets support various ways for sharing pubkeys, using QR Codes |
|
|
|
or sending base58check encoded strings. After you have collected all pubkeys and agreed on `m` and `n`, |
|
|
|
you construct the multisig script and generate P2SH address from that. |
|
|
|
|
|
|
|
|
|
|
|
#### Spending Received Transaction |
|
|
|
After you've received transaction on your multisig address, you can spend it if all signatures are provided |
|
|
|
After you've received a transaction on your multisig address, you can spend it if the minimum number of signatures are provided |
|
|
|
in a signature script. |
|
|
|
Signing process: You need all public keys, same that were used in address generation. From that |
|
|
|
you can construct the redeem script, that is the original script you constructed for address. Once |
|
|
|
you have redeem script, you can start creating signature script which will be constructed according |
|
|
|
to BIP11 and BIP16. When you prepend your signature, you take this transaction (not yet fully valid) and send it |
|
|
|
to another pubkey owner, who'll be signing next. Next person will do the same, until you have `m` signatures |
|
|
|
in the sigscript. After this process is done, your transaction is fully signed and you can broadcast your |
|
|
|
transaction with outputs you provided. |
|
|
|
1. You need all public keys, the same as were used in address generation. |
|
|
|
2. From that you can construct the redeem script, that is the original script you constructed for address. |
|
|
|
3. Once you have the redeem script, you can start creating the signature script which will be constructed according |
|
|
|
to BIP11 and BIP16. |
|
|
|
4. When you prepend your signature, you take this transaction (not yet fully valid) and send it to another pubkey owner, |
|
|
|
who'll be signing next. The next person will do the same, until you have `m` signatures in the sigscript. |
|
|
|
|
|
|
|
After this process is done, your transaction is fully signed and you can broadcast your transaction. |
|
|
|
|
|
|
|
|
|
|
|
[BIP11]: https://github.com/bitcoin/bips/blob/master/bip-0011.mediawiki |
|
|
@ -51,14 +54,15 @@ transaction with outputs you provided. |
|
|
|
|
|
|
|
### Manual construction |
|
|
|
|
|
|
|
In this setup, we won't be running node, looking into blockchain or wallet functionality. This is slightly more abstract |
|
|
|
then constructing scripts by ourselves. |
|
|
|
We'll split code in multiple files and share keys using current directory (So you can use fresh dir). |
|
|
|
In this setup, we won't be running a node or running any of the blockchain or wallet functionality of bcoin. |
|
|
|
This is a slightly more abstract than constructing bare scripts ourselves. |
|
|
|
We'll split code in multiple files and share keys using the current directory (So you can use fresh dir). |
|
|
|
|
|
|
|
|
|
|
|
### Step 1: Address Creation |
|
|
|
|
|
|
|
In following code, we'll import all necessary libraries, generate private and public keys, and create |
|
|
|
multisig address. |
|
|
|
In the following code, we'll import all necessary libraries, generate private and public keys, and create |
|
|
|
a multisig address. |
|
|
|
|
|
|
|
```js |
|
|
|
'use strict'; |
|
|
@ -109,16 +113,16 @@ console.log(`Address: ${base58addr}`); |
|
|
|
```js |
|
|
|
const ring1 = KeyRing.generate(compressed, network); |
|
|
|
``` |
|
|
|
Here we generate private key, public key is generated too. We need to provide |
|
|
|
information about network and public key format. There are two [Public key formats][bitcoin-pubkeyformat] |
|
|
|
one compressed and uncompressed. You can check details on [Bitcoin Developer Guide][bitcoin-pubkeyformat] |
|
|
|
Here we generate a private key and public key pair. We need to provide |
|
|
|
information about the network and public key format. There are two [Public key formats][bitcoin-pubkeyformat] |
|
|
|
one compressed and one uncompressed. More details can be found at the [Bitcoin Developer Guide][bitcoin-pubkeyformat] |
|
|
|
|
|
|
|
[bitcoin-pubkeyformat]: https://bitcoin.org/en/developer-guide#public-key-formats |
|
|
|
|
|
|
|
|
|
|
|
### Step 2: Generate Transaction |
|
|
|
|
|
|
|
In this part, we assume that we received transaction on the network with following information: |
|
|
|
In this part, we assume that we received a transaction on the network with the following information: |
|
|
|
> Transaction ID: 3b1dd17cc82e2ac43ba62bf8f1c6a0fe805df43911653d22c902571eb3a212ce |
|
|
|
> Output index: 0 |
|
|
|
> Amount: 100 BTC |
|
|
@ -175,9 +179,9 @@ const txInfo = { |
|
|
|
index: 0 |
|
|
|
}; |
|
|
|
|
|
|
|
// Coin provides information to the transaction |
|
|
|
// which are aggregated in CoinView within mtx |
|
|
|
// It's contains information about previous output |
|
|
|
// Coin provides information for the transaction |
|
|
|
// that is aggregated in CoinView within the mtx |
|
|
|
// and contains information about the previous output |
|
|
|
const coin = Coin.fromJSON({ |
|
|
|
version: 1, |
|
|
|
height: -1, |
|
|
@ -203,8 +207,8 @@ spend1.addOutput({ |
|
|
|
value: Amount.fromBTC('50').toValue() |
|
|
|
}); |
|
|
|
|
|
|
|
// Check the guide |
|
|
|
// send change to ourselves |
|
|
|
// Check notes below |
|
|
|
// send change to ourselves |
|
|
|
spend1.addOutput({ |
|
|
|
address: changeAddr, |
|
|
|
value: Amount.fromBTC('49.99').toValue() |
|
|
@ -253,7 +257,8 @@ assert(spend2.verify(), 'Transaction isnt valid.'); |
|
|
|
console.log(spend2.toRaw().toString('hex')); |
|
|
|
``` |
|
|
|
|
|
|
|
This will return raw transaction and also make sure |
|
|
|
Since there's a lot of code here, I wanted to review a couple of sections. |
|
|
|
This snippet below will return a raw transaction and also makes sure the |
|
|
|
transaction has all the signatures. |
|
|
|
|
|
|
|
|
|
|
@ -271,11 +276,12 @@ spend1.addOutput({ |
|
|
|
spend1.addCoin(coin); |
|
|
|
``` |
|
|
|
|
|
|
|
Here we send change to ourselves and specify it manually. |
|
|
|
Instead we could use `MTX.prototype.fund` which will automatically |
|
|
|
allocate coins to outputs, based on amounts they need and |
|
|
|
also calculate change and append output for it. |
|
|
|
Instead of code above, we could have simpler and more automated |
|
|
|
In this next snippet we send change to ourselves and specify it manually. |
|
|
|
Alternatively, we could also use `MTX.prototype.fund` which automatically |
|
|
|
allocates coins to outputs, based on the amounts they need and |
|
|
|
also calculate change and append a new output for it. |
|
|
|
Instead of the code above, we could have simpler and more automated |
|
|
|
|
|
|
|
calculations: |
|
|
|
|
|
|
|
```js |
|
|
@ -291,6 +297,7 @@ await spend1.fund([coin], { |
|
|
|
|
|
|
|
|
|
|
|
## Using Wallet API |
|
|
|
|
|
|
|
While it's possible to use `bcoin` for manually constructing transaction with just private keys, it's not |
|
|
|
convenient to handle all logic manually, we even skipped HD wallet parts. So if you have node running |
|
|
|
and you have access to it via HTTP, you can use `bcoin.http.Client` and `bcoin.http.Wallet`. These classes |
|
|
|