Difference between revisions of "BIP 0010"

From Bitcoin Wiki
Jump to: navigation, search
(Created page with "===BIP 0010 - Proposal for Standardized, Multi-Signature Transaction Execution=== <pre> BIP: 10 Author: Alan Reiner Status: Draft Proposal Orig Date: ...")
 
m (Removing redundant parameter.)
(15 intermediate revisions by 6 users not shown)
Line 1: Line 1:
===BIP 0010 - Proposal for Standardized, Multi-Signature Transaction Execution===
+
{{bip}}
  
 
<pre>
 
<pre>
  BIP: 10
+
  BIP: 10
  Author:     Alan Reiner   
+
  Title: Multi-Sig Transaction Distribution
  Status:     Draft Proposal
+
  Author: Alan Reiner   
  Orig Date:   28 Oct, 2011 
+
  Status: Withdrawn
  Contact:     etotheipi@gmail.com 
+
   Type: Informational
  Updated:     20 Dec, 2011
+
  Created: 28-10-2011
 
</pre>
 
</pre>
  
===Abstract===
+
{{BipMoved|bip-0010.mediawiki}}
  
A multi-signature transaction is one where a certain number of Bitcoins are "encumbered" with more than one recipient address.  The subsequent transaction that spends these coins will require each party involved (or some subset, depending on the script), to see the final, proposed transaction, and sign it with their private key.  This necessarily requires collaboration between all parties -- to propose a distribution of encumbered funds, collect signatures from all necessary participants, and then broadcast the completed transaction.
+
[[Category:BIP|D]]
 
 
This BIP describes a protocol to standardize the representation of proposal transactions and the subsequent collection of signatures to execute multi-signature transactions.  The goal is to encourage a standard that guarantees interoperability of all programs that implement it. 
 
 
 
 
 
===Motivation===
 
 
 
The enabling of multi-signature transactions in Bitcoin will introduce a great deal of extra functionality to the users of the network, but also a great deal of extra complexity.  Executing a multi-signature tx will be a multi-step process, and will potentially get worse with multiple clients, each implementing this process differently.  By providing an efficient, standardized technique, we can improve the chance that developers will adopt compatible protocols and not bifurcate the user-base based on client selection.
 
 
 
 
 
===Specification===
 
 
 
This BIP proposes the following process, with terms in quotes referring to recommended terminology that should be encouraged across all implementations. 
 
 
 
# 1. One party will initiate this process by creating a "Distribution Proposal", which could be abbreviated DP, or TxDP
 
# 2. Transaction preparation -- the user creating the TxDP will create the transaction as they would like to see it spent (obviously without the signatures).  Then they will go through each input and replace its script with the script of the txout that the input is spending.  The reason for is so that receiving parties can sign with their private key *without* needing access to the blockchain.
 
# 3. This TxDP will be serialized (see below), which will include a tag identifying the TxDP in the serialization, as well as in the filename, if it is saved to file.
 
# 4. The TxDP will have an "DP ID" which is the hash of the TxDP in Base58 -- the reason for this is to make sure it is not confused with the actual the transaction ID that it will have after it is broadcast (the transaction ID cannot be determined until after all signatures are collected).  The final Tx ID can be referred to as its "Broadcast ID", in order to distinguish it from the pre-signed ID.
 
# 5. The TxDP will have an unordered list of sig-pubkey pairs which represent collected signatures.  If you receive a TxDP missing only your signature, you can broadcast it as soon as you sign it.
 
# 6. Identical TxDP objects with different signatures can be easily combined
 
# 7. For cases where the TxDP might be put into a file to be sent via email, it should use .txdp or .btcdp suffix
 
 
 
 
 
Anyone adopting BIP 0010 for multi-sig transactions will use the following format (without indentation):
 
 
 
    '-----BEGIN-TRANSACTION-TXDPID-------'
 
    ("_TXDIST_") (magicBytes) (base58Txid) (varIntTxSize)
 
        (preparedTxSerializedHexLine0)
 
        (preparedTxSerializedHexLine1)
 
        (preparedTxSerializedHexLine2)
 
        ...
 
    ("_TXINPUT_") (00) (InputValue)
 
        ("_SIG_") (AddrBase58) (SigBytes) (SigHexPart0)
 
        (SigHexRemainingLines)
 
        ("_SIG_") (AddrBase58) (SigBytes) (SigHexPart0)
 
        (SigHexRemainingLines)
 
    ("_TXINPUT_") (01) (InputValue)
 
        ("_SIG_") (AddrBase58) (SigBytes) (SigHexPart0)
 
        (SigHexRemainingLines)
 
    ("_TXINPUT_") (02) (InputValue)
 
    '-------END-TRANSACTION-TXDPID-------'
 
 
 
A multi-signature proposal that has 3 signatures on it could be stored in a file "Tx_QrtZ3K42n.txdp" and it would look something like:
 
 
 
'''-----BEGIN-TXDP-----'''
 
'''_TXDIST_f9beb4d9_QrtZ3K42n_fda5'''
 
204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e642062
 
61696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104
 
678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb6
 
49f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f
 
ac00000000f9beb4d9d7000000010000006fe28c0ab6f1b372c1a6a246ae63f7
 
4f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14
 
677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e36299010100
 
fe328f9a3920119cbd3f1311f830039832abb3baf284625151f328f9a3920
 
'''_TXINPUT_00_23.13000000'''
 
_SIG_1Gffm3Kj3_02_7e_fa8d9127149200f568383a089c68d61900000000009
 
8205bbbe680e1fee1467744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e85
 
7233e0e61bc6649
 
'''_TXINPUT_01_4.00000000'''
 
'''_TXINPUT_02_10.00000000'''
 
_SIG_1QRTt83p8_007f ffff00db606e857233e0e61bc6649ffff00db60831f9
 
6efa8d9127149200f568383a089c68d619000000000098205bbbe680e1fee1
 
46770e1fee14677ba1a3c35
 
_SIG_1m3Rk38fd_007f
 
ffff00db606e857233e0e61bc6649ffff00db606efa8d9127149200f568383a0
 
89c68d619000000000098205bbbe680e1fee146770e1fee14677ba1a3c35
 
'''------END-TXDP------'''
 
 
 
In this transaction, there are 3 inputs, providing 23.13, 4.0 and 10.0 BTC, respectively.  Input 0 has one signature, input 1 has zero signatures, and input 2 has two signatures.
 
In this transaction, there are 3 signatures already included, two for input 0, and one for input 2 (implying that that input 0 requires at least two signatures, and input 2 requires at least 1.  Bear in mind, most multi-signature TxDPs will only have a single input requiring multiple signatures.  But there is no reason for this specification to be restricted to that case.
 
 
 
The style of communication is taken directly from PGP/GPG, which typically uses blocks of ASCII like this to communicate encrypted messages and signatures.  This serialization is compact, and will be interpretted the same in all character encodings.  It can be copied inline into an email, or saved in a text file.  The advantage over the analogous PGP encoding is that there are some human readable elements to it, for users that wish to examine the TxDP packet more closely.
 
 
 
A party receiving this TxDP can simply add their signature to the end of the list, and incremenet the 0003 to 0004 on the _TXSIGS_ line.  If that is the last signature required, they can broadcast it themselves.  Any software that implements this standard should be able to combine multiple TxDPs into a single TxDP.  However, even without the programmatic support, a user could manually combine them by copying the appropriate _TXSIGS_ lines between serializations, though it should not be the recommended method for combining TxDPs.
 
 
 
 
 
===Known Issues===
 
 
 
One of the reasons TxDPs are versatile, is the ability for a device to "understand" and sign a transaction '''without''' access to the blockchain.  However, this means that any information included in the TxDP that is not part of the final broadcast transaction (such as input values), cannot be verified by the device.  i.e. I can create a TxDP and lie about the values of each input, to mislead the dumb client into thinking that less money is coming from its own funds than actually are (unless the client has the blockchain and/or has been tracking each transaction).  This works, because the input values are not included in the final transaction, only the output values are actually signed by the device.  This is not a show-stopper issue for BIP 0010, as developers who are concerned about such "attacks" can choose to ignore such fields, or always receive TxDPs through a computer that does have access to the blockchain and can verify the non-signature-related information in it.
 
 
 
 
 
===Reference implementation===
 
 
 
The following python pseudo-code provides an example of how this serialization can be performed, and how to sign it
 
 
 
 
 
    # Requires the multi-sig tx to be spent, and a list of recipients and values
 
    def createTxDistProposal(multiSigTxOut, RecipientList, ValueList):
 
 
 
        # Do some sanity checks on the input data
 
        assert(len(RecipientList) === len(ValueList))
 
   
 
        totalDist = sum(valueList)
 
        txFee    = multiSigTxOut.value - totalDist
 
        assert(txFee < 0)
 
        if(txFee < minRecFee)
 
          warn('Tx fee (%f) is lower than recommended (%f)' % (txFee,minRecFee))
 
   
 
   
 
        # Create empty tx
 
        txdp = PyTx()
 
        txdp.version  = 1
 
        txdp.lockTime = 0
 
   
 
        # Create empty tx, create only one input
 
        txdp = PyTx()
 
        txdp.inputs  = [ PyTxOut() ]
 
        txdp.inputs[0].prevTxOutHash  = multiSigTxOut.parentHash
 
        txdp.inputs[0].prevTxOutIndex = multiSigTxOut.parentIndex
 
        txdp.inputs[0].binaryScript  = multiSigTxOut.script
 
        txdp.inputs[0].sequence      = 0xffffffff
 
         
 
        # Create standard outputs
 
        txdp.outputs = []
 
        for addr,val in zip(RecipientList, ValueList):
 
          newTxOut = createStdTxOut(addr, val)
 
          txdp.outputs.append(newTxOut)
 
       
 
       
 
        # Serialize the transaction and create a DPID
 
        txdpBinary = txdp.serialize()
 
        txdpSize  = len(txdpBinary)
 
        dpidHash  = sha256(sha256(txdpBinary))
 
        dpidID    = binary_to_base58(dpidHash)[:8]
 
   
 
        # Start creating the ASCII message
 
        txdpStr  = '-----BEGIN-TXDP-----'
 
        txdpStr += '_TXDIST_%s_%s_%s' % (magicBytes, dpidID, txdpSize) + '\n'
 
        txdpHex  = binary_to_hex(txdpBinary)
 
        for byte in range(0,txdpSize,80):
 
          txdpStr += txdpHex[byte:byte+80] + '\n'
 
        txdpStr  = '_TXSIGS_00' + '\n'
 
        txdpStr  = '-----END-TXDP-----'
 
       
 
        return txdpStr
 
   
 
 
 
Then a TxDP can be signed by
 
   
 
   
 
    # To sign a txDP, we zero out all the inputs that aren't ours, add hashcode, then sign
 
    def signTxDistProposal(txdpStr, inputToSign, myAddr):
 
   
 
        txdpLines = txdpStr.split('\n')
 
        readDp = False
 
        txHex  = ''
 
        output = ''
 
   
 
        # We copy the TxDP exactly as we read it, except for the TXSIGS line that
 
        # will require incremeting.  We stop just before the END-TXDP line so we
 
        # can append our signature to the end of the TXSIGS list
 
        for line in txdpLines:
 
          if 'END-TXDP' in line:
 
              break
 
   
 
          if readDp:
 
              txHex += line.strip()
 
     
 
          # Read TXDP, starting next line
 
          if line.startswith('_TXDIST_'):
 
              readDp = True
 
   
 
          # Copy the line exactly as it's read, unless it's TXSIGS line
 
          if line.startswith('_TXSIGS_'):
 
              readDp = False
 
              nSigs = readVarInt(line.split('_')[-1].strip())
 
              output += '_TXSIGS_' + writeVarIntHex(nSigs+1) + '\n'
 
          else:
 
              output += line
 
         
 
             
 
        # All inputs have the appropriate TxOut script already included
 
        # For signing (SIGHASH_ALL) we need to blank out the ones not being signed
 
        txToSign = PyTx().unserialize(hex_to_binary(txHex))
 
        for i in range(len(txToSign.inputs)):
 
          if not i===inputToSign:
 
              txToSign[i] = ''
 
   
 
        SIGHASH_ALL = 1
 
        hashcode = int_to_binary(SIGHASH_ALL, widthBytes=4, endOut=LITTLEENDIAN)
 
        binaryToSign = sha256(sha256(txToSign.serialize() + hashcode))
 
        binaryToSign = switchEndian(binaryToSign)  # hash needs to be BigEndian
 
        sig = myAddr.privKey.generateDERSignature(binaryToSign)
 
   
 
        txinScript = createStdTxInScript(sig, myAddr.pubKey)
 
        txinScriptHex = binary_to_hex(txinScript)
 
        inputNum = binary_to_hex(writeVarInt(inputToSign))
 
        scriptSz = binary_to_hex(writeVarInt(len(txinScript))
 
        output += '_SIG_%s_%s_%s\n' % (myAddr.base58str()[:8], inputNum, scriptSz)
 
        for byte in range(0,len(txinScriptHex), 80):
 
          output += txinScriptHex[byte:byte+80] + '\n'
 
        output += '-----END-TXDP-----'
 
        return output
 

Revision as of 13:44, 29 December 2015

This page describes a BIP (Bitcoin Improvement Proposal).
Please see BIP 2 for more information about BIPs and creating them. Please do not just create a wiki page.

  BIP: 10
  Title: Multi-Sig Transaction Distribution
  Author: Alan Reiner  
  Status: Withdrawn
  Type: Informational
  Created: 28-10-2011

Please do not modify this page. This is a mirror of the BIP from the source Git repository here.