bitcoin-sidechain-multisig-bitcoin-wallet-and-bitcoin-addresses-pw
Bitcoin sidechain Multisig Bitcoin Wallet and Bitcoin addresses (PW)
This doc describes the design of the multisignature Bitcoin wallet - (Primary Wallet - hereinafter - PW) mechanism as related to SON implementation, and the operations and objects concerning it.
PW is used to store all the BTC that has been deposited by users. The signatures included in it are the signatures of the accounts that are active SONs (PeerPlays blockchain nodes with SON enabled and having enough vote weight to be included in Sidechain operations) - therefore all the BTC in PW is under the control of active SONs. No SON can control the BTC stored there by himself, therefore a degree of decentralization is required.
Multisignature (multisig) refers to requiring more than one key to authorize a Bitcoin transaction. It is generally used to divide up responsibility for possession of Bitcoin.
Standard transactions on the Bitcoin network could be called “single-signature transactions,” because transfers require only one signature — from the owner of the private key associated with the Bitcoin address. However, the Bitcoin network supports much more complicated transactions that require the signatures of multiple people before the funds can be transferred. These are often referred to as M-of-N transactions (where M is the number of signatures required for sending a transaction, and N is the number of signatures available in a wallet). The idea is that Bitcoin becomes “encumbered” by providing addresses of multiple parties, thus requiring cooperation of those parties in order to do anything with them. These parties can be people, institutions or programmed scripts.
In our case, it is not enough to require M-of-N signatures to approve a transaction, as each signature comes with its own weight. This weight is determined by the number of votes received when voting for SONs. This requirement further complicates the bitcoin script, we cannot use the built-in OP_CHECKMULTISIG operation, but have to check every signature separately and add up the corresponding weights.
The address of the PW is stored in btc_address_object.
btc_pw_prevout_object
This object is created when sending a transaction in Biotcoin network, and stores the information about PW vout. It is structured as follows:
Type
Name
Description
prev_out
vout
Information about the previous vout
sha256
hash_id
vout identificator
bool
confirmed
Flag that shows if the vout is confirmed
bool
used
Flag that shows if the vout has been used
It stores the information on a PW vout with all the funds in it.
This object is created on each transaction from PW sent on Bitcoin blockchain.
Since all the funds on a PW are stored in one vout, it is required to be able to spend the money from an unconfirmed vout. Due to this fact, it is required to store the chain of PW vouts, from the last confirmed vout to the current vout. Due to the limitations of Bitcoin protocol the chain of vouts can not exceed 25. The chain of vouts is stored in btc_pw_prevout_index. The index is represented as a chain of vouts from PW. After a Bitcoin transaction from PW gets N confirmations on Bitcoin blockchain, it is considered confirmed, therefore its vout becomes confirmed. The index is then updated, with the latest confirmed vout replacing the previous latest confirmed vout.
The standard value for the required number of confirmations is N=6, but many exchanges use N=3 for deposits. It is a trade-off between speed (how long the conversion takes) and safety. We would start with N=6, but as SONs are basically exchanges, we could change the requirement to only N=3 confirmations if desired.
SideChain Bitcoin address
Bitcoin addresses are used to allow users to deposit Bitcoin to PeerPlays sidechain.
There are two types of Bitcoin addresses in PeerPlays network:
PW-address - the storage of all BTC deposited by users (described above).
Deposit-address - address generated for each user and used for depositing BTC to PeerPlays, after which the deposited BTC is sent to PW.
Operation to create Bitcoin address
The operation is called btc_address_create_operation. Its evaluator class creates an object called btc_address_object, containing a Bitcoin address. An address is a custom mutisig script consisting of keys and weights (sum of votes for a SON) SON.
btc_address_create_operation
This operation creates an object that stores the deposit address for an account (btc_address_object).
It includes the following fields:
Type
Name
Description
asset
fee
The fee for executing the operation on PeerPlays blockchain
account_id_type
payer
Account that pays the fee for the operation
account_id_type
owner
Account to own the created address
btc_address_object
This object is created on execution of btc_address_create_operationand stores the information about the address on Bitcoin blockchain.
It contains the following fields:
Type
Name
Description
account_id_type
owner
Account that the Bitcioin deposit address belongs to
btc_multisig_segwit_address
address
Information on the Bitcoin address
uint64_t
count_invalid_pub_key
The number of invalid co-sginatory keys in the address
Active SONs are co-signatories for the funds stored on PW. Each SON has a public key on Bitcoin (secp256k1) and the weight of its signature.
This is executed on Bitcoin blockchain with the following script:
<pubkey1> OP_CHECKSIG
OP_IF
<voting_weight1>
OP_ELSE
0
OP_ENDIF
OP_SWAP
<pubkey2> OP_CHECKSIG
OP_IF
<voting_weight2>
OP_ADD
OP_ENDIF
...
OP_SWAP
<pubkeyN-1> OP_CHECKSIG
OP_IF
<voting_weightN-1>
OP_ADD
OP_ENDIF
OP_SWAP
<pubkeyN> OP_CHECKSIG
OP_IF
<voting_weightN>
OP_ADD
OP_ENDIF
<two_thirds_of_total_voting_weight>
OP_GREATERTHAN
The point of the script is that each SON has a weight (sum of votes for SON that is set at maintenance). The script goes through each SON and checks their signature. If the signature is present, their weight is added to the variable at the top of the stack. At the end, the the sum is compared to 2/3 of the total weight of all SONs. Depending on the cumulative weight of votes a decision is made on whether the transfer is to be executed. For the transfer to happen the sum of weights in the script must be >= 2/3 + 1 from the number of current active SON weights. All the variables in `<>` brackets change only when the set of SONs change, which is the same time as when the script is re-generated. Thus in the actual bitcoin script they will be literal constants.
Since the addresses depend on weights, and weights in turn depend on balances, on most occasions the deposit addresses will be re-generated after maintenance. There are two ways to handle this situation:
All pre-maintenance are to be considered invalid after maintenance.
Consider the pre-maintenance composition of SONs and their weights trusted post-maintenance. If the composition of SONs doesn't change, but their weights do, SON members are to be allowed to process the transaction in accordance with their pre-maintenance weights.
The maximum size of a Bitcoin script is 10kB, so with our limit of 15 SONs we will not approach this limit.
SON downtime and communication problems, handling of invalid transactions
Potential issues could arise on both the side of Bitcoin and PeerPlays. In case a transaction is sent on Bitcoin and is not added to mempool, and, by extension, Bitcoin blockchain, it is vital to avoid the depositors losing their BTC.
Potential issues include:
Invalid serialization of a Bitcoin transaction.
Bitcoin transaction uses invalid signatures.
Bitcoin transaction uses invalid vin.
Detection of an invalid transaction
Before a transaction is sent to Bitcoin blockchain, SON memberplaces bitcoin_transaction_confirmations object with tx_id to an index in btc_sidechain_net_manager.
After receiving a block from Bitcoin, block counter bitcoin_transaction_confirmations::count_block increments in these objects. As soon as the counter reaches confirmations_num (specified in chain_parameters) transaction confirmation validation takes place.
Request to receive the number of confirmations (method bitcoin_rpc_client::receive_confirmations_tx). They are stored in bitcoin_transaction_confirmations::count_block , re-recording the previous data.
If the received number of confirmations >= confirmations_num, a transaction is considered confirmed.
If the number of confirmations = 0, it means that the transaction has not been added to the blockchain, and it is required to check if it is in Bitcoin mempool.
A request is made to check if a transaction is ino mempool (bitcoin_rpc_client::receive_mempool_entry_tx).
If it is in mempool, it is left as is, continuing to await confirmation.
If it is not in mempool, it is considered invalid, or a fork has occurred on Bitcoin.
Handling of an invalid transactions
vins are checked for validity via bitcoin_rpc_client::receive_confirmations_tx.
All invalid vins are dropped.
All valid vins and vouts are added to btc_revert_operation and sent to the blockchain.
Transaction object is removed from sidechain_net_manager::bitcoin_confirmations.
Handling btc_revert_operation
All valid objects btc_input_data_object and btc_withdrawal_data_object in the Evaluator class for this operation are marked as unused (unspent). Invalid btc_input_data_object and btc_transaction_object are deleted.
Therefore only valid input and withdrawals will be used in transactions on Bitcoin.
btc_revert_operation
This operation is used to restore information about transfers and removal of invalid information.
It contains the following fields:
Type
Name
Description
asset
fee
The fee for executing the operation on PeerPlays blockchain
account_id_type
payer
SON acount that pays for the operation
vector<revert_trx_info>
transactions_info
Information on transactions, stored as a vector
In the case of PeerPlays, potential issues arise when an active SON is disconnected and/or does not sign transactions due to the downtime, other SONs will need to sign transactions for him.
Borderline cases include:
Active SONs with the cumulative weights > 1/3 total active SONs weight do not sign transactions with deposit information or transactions outgoing from PW.
A SON wishes to stop performing their functions due to the required maintenance on his end
In the first case the operations of Sidechain will not be performed and Bitcoin transactions will be reverted as described above.
In the second case the SON is required to utilize remove_son_operation`. If they wish to return to the list of SONs and take part in SideChain operation, they will need to utilize create_son_operation`.
Primary wallet transfer during maintenance
When a new set of SONs is voted in, the primary wallet ownership has to be transferred to them. This involves multiple steps:
Creating a new Bitcoin script using the new SON keys and weights
Transferring any funds in the primary wallet to the new address