|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: Pettycoin Revisited Part IV: Simplified Transactions |
| 4 | +commentIssueId: 42 |
| 5 | +--- |
| 6 | +> This is the fourth in a series analyzing the pettycoin implementation |
| 7 | +> against Gregory Maxwell's |
| 8 | +> [writeup on scaling](https://en.bitcoin.it/wiki/User:Gmaxwell/features#Proofs). |
| 9 | +> The first talked about |
| 10 | +> [UTXO commitments vs backrefs](http://rustyrussell.github.io/pettycoin/2014/11/29/Pettycoin-Revisted-Part-I:-UTXO-Commitments.html), |
| 11 | +> the second talked about [Propogation servers vs prev_txhashes](http://rustyrussell.github.io/pettycoin/2014/12/04/Pettycoin-Revisited-Part-II:-Proof-of-Propogation.html), |
| 12 | +> and the third talked about [Hashed Fees vs Random Extrapolation](http://rustyrussell.github.io/pettycoin/2014/12/04/Pettycoin-Revisited-Part-III:-Miner-Rewards.html). |
| 13 | +
|
| 14 | +Each transaction has inputs and outputs. An input is fully consumed |
| 15 | +when used, so you need at least two outputs (one for change). |
| 16 | +Obviously, you need more than one input if you want to combine funds to pay |
| 17 | +someone. |
| 18 | + |
| 19 | +## Pettycoin Solution ## |
| 20 | + |
| 21 | +Pettycoin allows up to 4 inputs from a single address, which also |
| 22 | +implies where the change output goes. This is makes for a compact |
| 23 | +representation: |
| 24 | + |
| 25 | + /* Which input are we spending? */ |
| 26 | + struct protocol_input { |
| 27 | + /* This identifies the transaction. */ |
| 28 | + struct protocol_tx_id input; |
| 29 | + /* This identifies the output. |
| 30 | + * For normal transactions, 0 == send_amount, 1 = change */ |
| 31 | + u16 output; |
| 32 | + u16 unused; |
| 33 | + }; |
| 34 | + |
| 35 | + struct protocol_tx_normal { |
| 36 | + u8 version; |
| 37 | + u8 type; /* == TX_NORMAL */ |
| 38 | + u8 features; |
| 39 | + /* change_amount goes back to this key. */ |
| 40 | + struct protocol_pubkey input_key; |
| 41 | + /* send_amount goes to this address. */ |
| 42 | + struct protocol_address output_addr; |
| 43 | + /* Amount to output_addr. */ |
| 44 | + u32 send_amount; |
| 45 | + /* Amount to return to input_key. */ |
| 46 | + u32 change_amount; |
| 47 | + /* Number of inputs to spend (<= PROTOCOL_TX_MAX_INPUTS) */ |
| 48 | + u32 num_inputs; |
| 49 | + /* ECDSA of double SHA256 of above, and input[num_inputs] below. */ |
| 50 | + struct protocol_signature signature; |
| 51 | + |
| 52 | + /* The inputs. */ |
| 53 | + struct protocol_input input /* [s->num_inputs] */; |
| 54 | + }; |
| 55 | + |
| 56 | +The size of a 2-input transaction is 3 + 33 + 32 + 4 + 4 + 4 + 64 + |
| 57 | +36*2 = 216 bytes. |
| 58 | + |
| 59 | +This makes it easy to determine fees (since pettycoin uses a 0.3% fee) |
| 60 | +as you can tell how much was change and how much was transferred. It |
| 61 | +also (with a canonical signature check) makes transactions non-malleable. |
| 62 | + |
| 63 | +However, it has real disadvantages: |
| 64 | + |
| 65 | +1. Privacy. By forcing address use in this way, transactions are not |
| 66 | + private. And you can't use a scheme like CoinJoin because there |
| 67 | + are no multiple different inputs. Just because amounts are small |
| 68 | + doesn't *necessarily* imply they're non-sensitive. |
| 69 | +2. The [sidechains](http://blockstream.com/sidechains.pdf) proposal |
| 70 | + will require sidechain transactions to be of some canonical |
| 71 | + (bitcoin-like!) form, so we'd have to change anyway. |
| 72 | +3. The atomic-swap proposal which makes sidechains effective requires |
| 73 | + locktime, which is not present in this simplified transaction format. |
| 74 | +4. If you want to be a sidechain, you have to understand bitcoin transactions |
| 75 | + (or, at least a subset) so you can spot transfers coming into the network. |
| 76 | + |
| 77 | +## Bitcoin's Solution ## |
| 78 | + |
| 79 | +Bitcoin's transactions are fully scriptable, though there are standard |
| 80 | +forms for the scripts which are generally used. |
| 81 | + |
| 82 | + struct bitcoin_transaction { |
| 83 | + u32 version; |
| 84 | + varint_t input_count; |
| 85 | + struct bitcoin_transaction_input *input; |
| 86 | + varint_t output_count; |
| 87 | + struct bitcoin_transaction_output *output; |
| 88 | + u32 lock_time; |
| 89 | + }; |
| 90 | + |
| 91 | + struct bitcoin_transaction_output { |
| 92 | + u64 amount; |
| 93 | + varint_t script_length; |
| 94 | + u8 *script; |
| 95 | + }; |
| 96 | + |
| 97 | + struct bitcoin_transaction_input { |
| 98 | + u8 hash[32]; |
| 99 | + u32 index; /* output number referred to by above */ |
| 100 | + varint_t script_length; |
| 101 | + u8 *script; |
| 102 | + u32 sequence_number; |
| 103 | + }; |
| 104 | + |
| 105 | +A [typical output script](https://en.bitcoin.it/wiki/Script) is |
| 106 | +`OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG` (25 |
| 107 | +bytes), and a |
| 108 | +[typical output scriptsig](https://en.bitcoin.it/wiki/Script) is |
| 109 | +`<sig> <pubkey>` (106 bytes), and a `varint` is 1-9 bytes (typically 1 |
| 110 | +byte here). So a typical input would be 32 + 4 + 1 + 106 + 4 = 147 |
| 111 | +bytes, and the typical output 8 + 1 + 106 = 115 bytes. With 10 bytes |
| 112 | +for the transaction parts, that's 534 bytes. |
| 113 | + |
| 114 | +There are several bad things about the bitcoin approach: |
| 115 | + |
| 116 | +1. The scripting has enough non-uniformity, corner cases and |
| 117 | + weirdness that best practice is to use the reference |
| 118 | + implementation to interpret scripts. |
| 119 | +2. [Transaction malleability](https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki) is a real problem, with different encodings possible for |
| 120 | + signatures, scripts and elsewhere. |
| 121 | +3. As opcodes and patterns are |
| 122 | + "[reinterpreted](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki)" |
| 123 | + for soft-forking upgrades, this problem gets worse. |
| 124 | +4. Signatures are DER encoded (70/71 instead of 64 bytes) for no good |
| 125 | + reason, and keys can be either uncompressed (64) or compressed (33) |
| 126 | + bytes. Pettycoin uses binary encoding for signatures and only |
| 127 | + compressed keys. |
| 128 | + |
| 129 | +## Summary ## |
| 130 | + |
| 131 | +The benefits of bitcoin transactions become very apparent if you have |
| 132 | +to handle them anyway for sidechains. And there's a middle ground |
| 133 | +possible: use a strict subset of bitcoin scripting, with some limits |
| 134 | +on transactions. It would have required pettycoin to use a different |
| 135 | +approach for fees (0.1% of total transferred might make sense, with |
| 136 | +limits on numbers of inputs and outputs). |
| 137 | + |
| 138 | +The factor-of-two reduction in size isn't worthwhile, given the |
| 139 | +privacy implications. And cleaning up the protocol slightly is nice, |
| 140 | +but again, not worth the gratuitous incompatibility since we'd have to |
| 141 | +handle both. |
0 commit comments