Difference between revisions of "How to Submit Multisig Tx"
VeriBlockTim (talk | contribs) |
VeriBlockTim (talk | contribs) |
||
(5 intermediate revisions by the same user not shown) | |||
Line 24: | Line 24: | ||
Run this command: | Run this command: | ||
<pre> | <pre> | ||
+ | #Format | ||
+ | generatemultisigaddress <csvaddresses> <signatureThreshold> | ||
+ | |||
+ | #Example | ||
generatemultisigaddress V7aigFb3yA56ZBroNMpdcV66hFqdCV,V9Z4MrtkTSoFmaUWFb39wrh597SduJ,VEhP8gKnPsFa7i8HUqsVDLWvH2Spke 2 | generatemultisigaddress V7aigFb3yA56ZBroNMpdcV66hFqdCV,V9Z4MrtkTSoFmaUWFb39wrh597SduJ,VEhP8gKnPsFa7i8HUqsVDLWvH2Spke 2 | ||
+ | |||
+ | #Example - same as above, but output to a file (use the -o parameter, it will write a file next to where the NC_CLI is running) | ||
+ | # You'll want to keep track of the original addresses and their order for future reference | ||
+ | generatemultisigaddress V7aigFb3yA56ZBroNMpdcV66hFqdCV,V9Z4MrtkTSoFmaUWFb39wrh597SduJ,VEhP8gKnPsFa7i8HUqsVDLWvH2Spke 2 -o multisig.json | ||
+ | |||
</pre> | </pre> | ||
− | This will provide the new address "V239PhRtWxDovahFpg47kq7WgCCJw0". NOTE: Make sure to save the source addresses | + | This will provide the new address "V239PhRtWxDovahFpg47kq7WgCCJw0". |
+ | |||
+ | '''NOTE: Make sure to save the source addresses and the order somewhere, so it can be used later:''' | ||
+ | |||
<pre> | <pre> | ||
{ | { | ||
Line 47: | Line 59: | ||
<pre> | <pre> | ||
− | # | + | #Format |
makeunsignedmultisigtx <sourceAddress> <amount> <destinationAddress> [transactionFee] [signatureIndex] | makeunsignedmultisigtx <sourceAddress> <amount> <destinationAddress> [transactionFee] [signatureIndex] | ||
− | # | + | #Example to send 75 VBK from the multisig address to another address |
makeunsignedmultisigtx V239PhRtWxDovahFpg47kq7WgCCJw0 75 V7ycoS1TArJEXE8ivfYugpaRH61eqg | makeunsignedmultisigtx V239PhRtWxDovahFpg47kq7WgCCJw0 75 V7ycoS1TArJEXE8ivfYugpaRH61eqg | ||
</pre> | </pre> | ||
Line 101: | Line 113: | ||
For example, say people with access to the first and third addresses' private keys decide to sign the transaction: | For example, say people with access to the first and third addresses' private keys decide to sign the transaction: | ||
− | Holder #1 --> signs | + | '''Holder #1 --> signs''' |
<pre> | <pre> | ||
Line 113: | Line 125: | ||
</pre> | </pre> | ||
− | Holder #2 --> does not sign | + | '''Holder #2 --> does not sign''' |
− | Holder #3 --> signs | + | '''Holder #3 --> signs''' |
<pre> | <pre> | ||
Line 219: | Line 231: | ||
=== How can I view the balance of a multisig address? === | === How can I view the balance of a multisig address? === | ||
− | + | A multisig address will not show up with just getbalance, rather one must explicitly specify the address: | |
<pre> | <pre> | ||
getbalance V239PhRtWxDovahFpg47kq7WgCCJw0 | getbalance V239PhRtWxDovahFpg47kq7WgCCJw0 | ||
</pre> | </pre> | ||
+ | |||
+ | |||
+ | === What is signature index? === | ||
+ | |||
+ | While the blocktime is only 30 seconds, it could take people days to coordinate getting all the signatures for a multisig address. | ||
+ | |||
+ | signatureindex allows the same multisig address to have multiple uncompleted transactions being signed at the same time | ||
+ | |||
+ | More Detail: | ||
+ | |||
+ | Transactions included in the VeriBlock blockchain must be in-order based on their index (the first transaction from a particular address must be at signature index 0, the second must be at signature index 1, etc.). By default, NodeCore generates new transactions based on the current signature index of the address according to the last transaction sent from an address which is in the VeriBlock blockchain/mempool. However, multisig transactions are not immediately submitted to the blockchain; they have to be signed by multiple parties, and those signatures have to be compiled together in order to be able to submit a valid multisig transaction to the network. As a result, if you generate a new multisig transaction before submitting a previous one, they will both be generated with the same signature index, because the state of the mempool and blockchain hasn't changed with respect to the multisig address's signature index. When both transactions are submitted back to the network, one of them will be rejected, because only one transaction at a particular signature index can exist in the blockchain for a particular address. | ||
+ | |||
+ | In this case, you could specify a signature index manually (which should be 1 above the signature index of the first multisig transaction you just generated), and then both transactions would be valid on the network. However be aware that the first multisig transaction you generated (or another transaction with the same signature index as the first multisig transaction) must be submitted to the network before the second one can be submitted to the network. |
Latest revision as of 14:09, 28 November 2018
See: NodeCore_CommandLine
Contents
Overview
The NC_CLI allows creating multisig addresses and submitting multisig transactions.
Multisig means "multiple signatures", such as it takes at least 2 out of 3 signatures to submit the transaction. Such an address would look like V23...0 (only multisig ends in 0).
This will require 4 NC_CLI commands:
- generatemultisigaddress --> initially create the multisig address. This could be done once.
- makeunsignedmultisigtx --> create a Tx
- signhexmessage --> sufficient owners must provide their signatures
- submitmultisigtx --> given sufficient signatures (such as 3 of 5), submit the transaction
Steps
Say for this example we want to make a 2-of-3 multisig address from the following three addresses: V7aigFb3yA56ZBroNMpdcV66hFqdCV, V9Z4MrtkTSoFmaUWFb39wrh597SduJ, and VEhP8gKnPsFa7i8HUqsVDLWvH2Spke.
Generate the multisig address
Run this command:
#Format generatemultisigaddress <csvaddresses> <signatureThreshold> #Example generatemultisigaddress V7aigFb3yA56ZBroNMpdcV66hFqdCV,V9Z4MrtkTSoFmaUWFb39wrh597SduJ,VEhP8gKnPsFa7i8HUqsVDLWvH2Spke 2 #Example - same as above, but output to a file (use the -o parameter, it will write a file next to where the NC_CLI is running) # You'll want to keep track of the original addresses and their order for future reference generatemultisigaddress V7aigFb3yA56ZBroNMpdcV66hFqdCV,V9Z4MrtkTSoFmaUWFb39wrh597SduJ,VEhP8gKnPsFa7i8HUqsVDLWvH2Spke 2 -o multisig.json
This will provide the new address "V239PhRtWxDovahFpg47kq7WgCCJw0".
NOTE: Make sure to save the source addresses and the order somewhere, so it can be used later:
{ "sourceAddresses": [ "V7aigFb3yA56ZBroNMpdcV66hFqdCV", "V9Z4MrtkTSoFmaUWFb39wrh597SduJ", "VEhP8gKnPsFa7i8HUqsVDLWvH2Spke" ], "signatureThresholdM": 2, "resultantMultisigAddress": "V239PhRtWxDovahFpg47kq7WgCCJw0" }
Note: multisig addresses are a deterministic result of the source addresses (in order) and 'm' (of n) value. Changing the order of the same three addresses will yield a separate multisig address. Also note the 1st and 2nd character immediately after the starting 'V'; this shows that it is a 2-of-3 multisig (a 5-of-7 would be V57..., etc.) (multisig addresses can go up to 58-of-58).
Make an unsigned transaction
To generate the unsigned transaction (note the fee and signature index will be calculated for us if left out; the signatureIndex should only be specified when simultaneously coordinating multiple multisig signings for the same address, and they must be submitted in the signatureIndex order):
#Format makeunsignedmultisigtx <sourceAddress> <amount> <destinationAddress> [transactionFee] [signatureIndex] #Example to send 75 VBK from the multisig address to another address makeunsignedmultisigtx V239PhRtWxDovahFpg47kq7WgCCJw0 75 V7ycoS1TArJEXE8ivfYugpaRH61eqg
Output:
{ "signatureThresholdM": 2, "addressCompositionCountN": 3, "unsignedTransaction": { "size": 246, "txid": "3A0FA4FF27CEDE7853320B44A81FCC4BFB4DCE7EA9D637D0FB21C73C3967ADA0", "data": "", "type": "multisig", "fee": "0.00246000", "timestamp": 1542759712, "source_amount": "75.00246000", "merkle_path": "", "source_address": "V239PhRtWxDovahFpg47kq7WgCCJw0", "bitcoin_transaction": "N/A", "bitcoin_block_header_of_proof": "N/A", "endorsed_block_header": "N/A", "outputs": [ { "address": "V7ycoS1TArJEXE8ivfYugpaRH61eqg", "amount": "75.00000000" } ] }, "unsignedTransactionHex": "0A7108031216A978FB269E9D2A741593C9CF9CD6495E6AC007669A3F18F0D7B2F81B221E0A16679B943B5F9696EF21C4DDEF8DF7D775021640DCCA0B1080D6A3F81B28F0810F78A0CAD2DF058001F6018A01203A0FA4FF27CEDE7853320B44A81FCC4BFB4DCE7EA9D637D0FB21C73C3967ADA0", "txid": "3A0FA4FF27CEDE7853320B44A81FCC4BFB4DCE7EA9D637D0FB21C73C3967ADA0", "sigIndex": 0, "instructions": "Have at least 2 of the component addresses sign the TxID listed above (see: signhexmessage command) to validly sign this transaction, then submit the raw transaction hex listed above (see: submitmultisigtx command)!" }
Keep the unsignedTransactionHex and txid for later.
- unsignedTransactionHex --> will be needed to submit the final transaction
- txid --> will be sent to sufficient number of address owners (In this example, if you send to 3, will need at least 2 of them to sign)
Sufficient multisig holders sign
Each multisig holder who is signing (minimum of 2) is going to sign the TxID like so, where standardAddressToSignWith is the standard address which is part of the multisig group (so V7aigFb3yA56ZBroNMpdcV66hFqdCV, V9Z4MrtkTSoFmaUWFb39wrh597SduJ, or VEhP8gKnPsFa7i8HUqsVDLWvH2Spke):
signhexmessage <standardAddressToSignWith> <TxID>
For example, say people with access to the first and third addresses' private keys decide to sign the transaction:
Holder #1 --> signs
signhexmessage V7aigFb3yA56ZBroNMpdcV66hFqdCV 3A0FA4FF27CEDE7853320B44A81FCC4BFB4DCE7EA9D637D0FB21C73C3967ADA0 { "address": "V7aigFb3yA56ZBroNMpdcV66hFqdCV", "signedMessage": "3A0FA4FF27CEDE7853320B44A81FCC4BFB4DCE7EA9D637D0FB21C73C3967ADA0", "signature": "30450220471B2A09898A2E55EF0426BB1E75A7670BB38EB871AF604FE04784512ADCA7770221008433254C42BC8DA156E989E62EB0A8BA455F20D818D0F118C60C2589B3A1D921", "publicKey": "3056301006072A8648CE3D020106052B8104000A034200048487843CBD7A032DFA532A01376D0681791785BB069E22C47B660ABECC2405AC267E29F6FE1391137678CCB979176AAEC154264984605C683BBE768575A4F946" }
Holder #2 --> does not sign
Holder #3 --> signs
signhexmessage VEhP8gKnPsFa7i8HUqsVDLWvH2Spke 3A0FA4FF27CEDE7853320B44A81FCC4BFB4DCE7EA9D637D0FB21C73C3967ADA0 { "address": "VEhP8gKnPsFa7i8HUqsVDLWvH2Spke", "signedMessage": "3A0FA4FF27CEDE7853320B44A81FCC4BFB4DCE7EA9D637D0FB21C73C3967ADA0", "signature": "304502204373A68FF09411866BEE658DCAD382C8CABC022891D06AE389CD8304AA6C2C8B022100FE4A7A2E8B980211AC7F630BA98CE4E9D1DD77B479321F40A110F49D53B039C0", "publicKey": "3056301006072A8648CE3D020106052B8104000A0342000419C14BCA422EE1536A2774AB0F288ADCD20224838BEFD72CBED52FCD37833698E69282C461C09A2D70AAEABE220B26B12290900FB52A78BFE25F1A24C9894D48" }
Now we have signatures from two addresses (V7aigFb3yA56ZBroNMpdcV66hFqdCV and VEhP8gKnPsFa7i8HUqsVDLWvH2Spke) as well as their public keys. Since the address is a 2-of-3 multisig, we have enough signatures to send a valid transaction to the network!
Submit the multisig transaction with enough signatures
This is a little tricky. We will need to assemble two CSV lists, and keep the order for both in sync.
Now we'll serialize our public keys/addresses (public keys for addresses signing this transaction, addresses which aren't signing) into a CSV list:
#Format csvpublickeysoraddresses = <holder_1_public_key>,<holder_2_address>,<holder_3_public_key> #Example csvpublickeysoraddresses = 3056301006072A8648CE3D020106052B8104000A034200048487843CBD7A032DFA532A01376D0681791785BB069E22C47B660ABECC2405AC267E29F6FE1391137678CCB979176AAEC154264984605C683BBE768575A4F946,V9Z4MrtkTSoFmaUWFb39wrh597SduJ,3056301006072A8648CE3D020106052B8104000A0342000419C14BCA422EE1536A2774AB0F288ADCD20224838BEFD72CBED52FCD37833698E69282C461C09A2D70AAEABE220B26B12290900FB52A78BFE25F1A24C9894D48
And we'll do similar with the signatures (leaving a blank spot in the CSV list for the address that didn't sign, note the double-comma):
#Format csvsignatureshex = <holder_1_signature>,,<holder_2_signature> #Example csvsignatureshex = 30450220471B2A09898A2E55EF0426BB1E75A7670BB38EB871AF604FE04784512ADCA7770221008433254C42BC8DA156E989E62EB0A8BA455F20D818D0F118C60C2589B3A1D921,,304502204373A68FF09411866BEE658DCAD382C8CABC022891D06AE389CD8304AA6C2C8B022100FE4A7A2E8B980211AC7F630BA98CE4E9D1DD77B479321F40A110F49D53B039C0
And finally we're ready to submit the multisig transaction to the network:
- unsignedtransactionhex --> from above when we created the unsigned tx
- csvpublickeysoraddresses
- csvsignatureshex
#Format submitmultisigtx <unsignedtransactionhex> <csvpublickeysoraddresses> <csvsignatureshex> #Example submitmultisigtx 0A7108031216A978FB269E9D2A741593C9CF9CD6495E6AC007669A3F18F0D7B2F81B221E0A16679B943B5F9696EF21C4DDEF8DF7D775021640DCCA0B1080D6A3F81B28F0810F78A0CAD2DF058001F6018A01203A0FA4FF27CEDE7853320B44A81FCC4BFB4DCE7EA9D637D0FB21C73C3967ADA0 3056301006072A8648CE3D020106052B8104000A034200048487843CBD7A032DFA532A01376D0681791785BB069E22C47B660ABECC2405AC267E29F6FE1391137678CCB979176AAEC154264984605C683BBE768575A4F946,V9Z4MrtkTSoFmaUWFb39wrh597SduJ,3056301006072A8648CE3D020106052B8104000A0342000419C14BCA422EE1536A2774AB0F288ADCD20224838BEFD72CBED52FCD37833698E69282C461C09A2D70AAEABE220B26B12290900FB52A78BFE25F1A24C9894D48 30450220471B2A09898A2E55EF0426BB1E75A7670BB38EB871AF604FE04784512ADCA7770221008433254C42BC8DA156E989E62EB0A8BA455F20D818D0F118C60C2589B3A1D921,,304502204373A68FF09411866BEE658DCAD382C8CABC022891D06AE389CD8304AA6C2C8B022100FE4A7A2E8B980211AC7F630BA98CE4E9D1DD77B479321F40A110F49D53B039C0
Output will create a new transaction: 3A0FA4FF27CEDE7853320B44A81FCC4BFB4DCE7EA9D637D0FB21C73C3967ADA0
{ "transaction": { "size": 246, "txid": "3A0FA4FF27CEDE7853320B44A81FCC4BFB4DCE7EA9D637D0FB21C73C3967ADA0", "data": "", "type": "multisig", "fee": "0.00246000", "timestamp": 1542759712, "source_amount": "75.00246000", "merkle_path": "", "source_address": "V239PhRtWxDovahFpg47kq7WgCCJw0", "bitcoin_transaction": "N/A", "bitcoin_block_header_of_proof": "N/A", "endorsed_block_header": "N/A", "outputs": [ { "address": "V7ycoS1TArJEXE8ivfYugpaRH61eqg", "amount": "75.00000000" } ] }, "txid": "", "multisigSlotBundle": { "multisigSlots": [ { "publicKey": "3056301006072A8648CE3D020106052B8104000A034200048487843CBD7A032DFA532A01376D0681791785BB069E22C47B660ABECC2405AC267E29F6FE1391137678CCB979176AAEC154264984605C683BBE768575A4F946", "signature": "30450220471B2A09898A2E55EF0426BB1E75A7670BB38EB871AF604FE04784512ADCA7770221008433254C42BC8DA156E989E62EB0A8BA455F20D818D0F118C60C2589B3A1D921", "ownerAddress": "V7aigFb3yA56ZBroNMpdcV66hFqdCV", "populated": true }, { "publicKey": "", "signature": "", "ownerAddress": "VGKot5hBsd81kMupNCXHaqbhvCzncR", "populated": false }, { "publicKey": "3056301006072A8648CE3D020106052B8104000A0342000419C14BCA422EE1536A2774AB0F288ADCD20224838BEFD72CBED52FCD37833698E69282C461C09A2D70AAEABE220B26B12290900FB52A78BFE25F1A24C9894D48", "signature": "304502204373A68FF09411866BEE658DCAD382C8CABC022891D06AE389CD8304AA6C2C8B022100FE4A7A2E8B980211AC7F630BA98CE4E9D1DD77B479321F40A110F49D53B039C0", "ownerAddress": "VEhP8gKnPsFa7i8HUqsVDLWvH2Spke", "populated": true } ] }, "sigIndex": 0 }
FAQ
How can I view the balance of a multisig address?
A multisig address will not show up with just getbalance, rather one must explicitly specify the address:
getbalance V239PhRtWxDovahFpg47kq7WgCCJw0
What is signature index?
While the blocktime is only 30 seconds, it could take people days to coordinate getting all the signatures for a multisig address.
signatureindex allows the same multisig address to have multiple uncompleted transactions being signed at the same time
More Detail:
Transactions included in the VeriBlock blockchain must be in-order based on their index (the first transaction from a particular address must be at signature index 0, the second must be at signature index 1, etc.). By default, NodeCore generates new transactions based on the current signature index of the address according to the last transaction sent from an address which is in the VeriBlock blockchain/mempool. However, multisig transactions are not immediately submitted to the blockchain; they have to be signed by multiple parties, and those signatures have to be compiled together in order to be able to submit a valid multisig transaction to the network. As a result, if you generate a new multisig transaction before submitting a previous one, they will both be generated with the same signature index, because the state of the mempool and blockchain hasn't changed with respect to the multisig address's signature index. When both transactions are submitted back to the network, one of them will be rejected, because only one transaction at a particular signature index can exist in the blockchain for a particular address.
In this case, you could specify a signature index manually (which should be 1 above the signature index of the first multisig transaction you just generated), and then both transactions would be valid on the network. However be aware that the first multisig transaction you generated (or another transaction with the same signature index as the first multisig transaction) must be submitted to the network before the second one can be submitted to the network.