summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoretotheipi <etotheipi@gmail.com>2011-12-30 18:22:57 -0500
committeretotheipi <etotheipi@gmail.com>2011-12-30 18:22:57 -0500
commit0a1cd78d080cb479323b4c28e6f27a7eef6a7414 (patch)
tree6eee2468059b5c8890f16dbcf1328ffcf1566a16
parentecd6fdeb0975aadbf1637d8e8ee4f627f3843b77 (diff)
downloadbips-0a1cd78d080cb479323b4c28e6f27a7eef6a7414.tar.xz
Updated header to be consistent with other BIPs
-rw-r--r--bip-0010.md157
1 files changed, 29 insertions, 128 deletions
diff --git a/bip-0010.md b/bip-0010.md
index 8947012..97e64aa 100644
--- a/bip-0010.md
+++ b/bip-0010.md
@@ -2,11 +2,11 @@
<pre>
BIP: 10
+ Title: Distribution Proposals for Multi-Sig Transactions
Author: Alan Reiner
- Status: Draft Proposal
- Orig Date: 28 Oct, 2011
- Contact: etotheipi@gmail.com
- Updated: 20 Dec, 2011
+ Status: Draft
+ Type: Standards Track
+ Created: 2011-10-28
</pre>
===Abstract===
@@ -25,13 +25,13 @@ The enabling of multi-signature transactions in Bitcoin will introduce a great d
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
+# One party will initiate this process by creating a "Distribution Proposal", which could be abbreviated DP, or TxDP
+# 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.'''
+# 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.
+# The TxDP will have an "DP ID" which is the hash of the TxDP in Base58 -- the reason for the specific naming convention 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.
+# 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.
+# Identical TxDP objects with different signatures can be easily combined
+# 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):
@@ -80,125 +80,26 @@ A multi-signature proposal that has 3 signatures on it could be stored in a file
'''------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.
+The style of communication is taken directly from PGP/GPG, which 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 manually, instead of requiring a program/parser to simply determine the core elements of the TxDP.
+
+A party receiving this TxDP can simply add their signature to the appropriate _TXINPUT_ 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.
+
+=== Reference Implementation ===
+
+This proposal has been implemented and tested in the ''Armory'' Bitcoin software for use in offline-wallet transaction signing, and is prepared to be used for supporting multi-signature transactions in a future release. As such, the ''Armory'' source code contains a working implementation of BIP 0010 for single-party transactions (for offline wallets), and the logic is implemented (but untested) for multi-signature transactions.
+
+The source code can be found at: https://github.com/etotheipi/BitcoinArmory/blob/qtdev/armoryengine.py with the PyTxDistProposal class starting at line 4520. A few direct links:
+
+'''TxDP from list of unspent TxOuts:''' https://github.com/etotheipi/BitcoinArmory/blob/qtdev/armoryengine.py#L4616
+
+'''Serialization of TxDP:''' https://github.com/etotheipi/BitcoinArmory/blob/qtdev/armoryengine.py#L4840
+
+'''Unserialize a TxDP:''' https://github.com/etotheipi/BitcoinArmory/blob/qtdev/armoryengine.py#L4879
+
+'''Finished TxDP to broadcast-Tx:''' https://github.com/etotheipi/BitcoinArmory/blob/qtdev/armoryengine.py#L4795
-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. 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
+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.