Too much idea. I'd consolidate everything in one post. I hope this will become a BIP.
BIP: xxxx
Title: Mnemonic code for referencing transaction output in the blockchain
Authors: Nicolas Dorier, jl2012
Status: Draft
Type: Standards Track
Created: 2015
==Abstract==
This BIP describes the implementation of a mnemonic code for referencing any transaction output in the blockchain.
==Motivation==
==Generating the mnemonic address==
Definitions:
blockHeight: the height of the referenced block. Genesis block is 0
blockHash: the hash of the referenced block
txIndex: index of the referenced transaction in the block. Index of the first transaction in a block is 0
outputIndex: index of the referenced output in the transaction. Index of the first output in a transaction is 0
scriptPubKey: the scriptPubKey of the referenced output
c: a fixed integer, the minimal number of bits for checksum (to be defined later)
y
min = ceiling(log(txIndex + 1, 2))
z
min = ceiling(log(outputIndex + 1, 2))
Step1: Determine the number of bits and encoding of blockHeight
blockHeight takes x bits and is encoded as follow:
- For height =< 1,048,575 (0-1111-1111-1111-1111-1111), blockHeight is the height as 21bit interger
- For 1,048,575 < height =< 8,388,607, blockHeight is Concat(1, height as 23 bit integer), which totally takes 24bit. For example, block 1234567 is 1001-0010-1101-0110-1000-0111
- For height > 8,388,607, it is undefined and returns error
Step2: Determine the lower bound of words required for the mnemonic address
- w = ceiling((x + ymin + zmin + c + 1)/11)
Step3: Determine the number of bits for txIndex
txIndex takes y bits:
- y1 = ceiling(log(total number of transactions in the block, 2))
- y2 = 11w-1-x-c
- y = min(y1, y2))
If (ymin > y), increase w by 1 and go back to Step 3 (This condition is not possible as the initial value of w must provide enough space for ymin)
Step4: Determine the number of bits for outputIndex
outputIndex takes z bits:
- z1 = ceiling(log(total number of output in the transaction, 2))
- z2 = 11w-1-x-y-c
- z = min(z1, z2)
- If (zmin > z), increase w by 1 and go back to Step 3
Step5: Calculate the checksum
- rawChecksum = SHA256(SHA256(Concat(blockHash-txIndex-outputIndex-scriptPubKey))) (I don't know why but Satoshi never used single SHA256)
(for simplicity, the length of txIndex and outputIndex here is same as those determined in Step 3 and 4 respectively)- checksum = rawChecksum(11w-1-x-y-z) (the most significant 11w-1-x-y-z bits of rawChecksum)
Step6: Get the rawAddress = Concat(blockHeight-txIndex-outputIndex-checksum)
Step7: Get the encryptionKey = least significant c bits of rawAddress
Step8: Get the finalEncryptionKey
- If 11w-1-c =< c, finalEncryptionKey = encryptionKey(11w-1-c)
- If 2c >= 11w-1-c > c, finalEncryptionKey = Concat(EncryptionKey, EncryptionKey(11w-1-2c))
- If 3c >= 11w-1-c > 2c, finalEncryptionKey = Concat(EncryptionKey, EncryptionKey, EncryptionKey(11w-1-3c))
etc
Step9: Get the encryptedAddress = XOR(rawAddress(11w-1-c),finalEncryptionKey)
Step10: Get the finalAddress = Concat(encryptedAddress,encryptionKey,0)
The last 0 denotes the address version
Step11: Convert finalAddress into mnemonic code following BIP-0039
==Decoding the mnemonic address==
Step1: Determine w = number of words in the mnemonic code
Step2: Convert mnemonic code into finalAddress following BIP-0039
Step3: If the last bit of finalAddress is 0,
drop it. If it is 1, return error.
Step4: Get the encryptionKey = least significant c bits of finalAddress
Step5: Get the finalEncryptionKey
- If 11w-1-c =< c, finalEncryptionKey = encryptionKey(11w-1-c)
- If 2c >= 11w-1-c > c, finalEncryptionKey = Concat(EncryptionKey, EncryptionKey(11w-1-2c))
- If 3c >= 11w-1-c > 2c, finalEncryptionKey = Concat(EncryptionKey, EncryptionKey, EncryptionKey(11w-1-3c))
etc
Step6: Get the decryptedAddress = XOR(finalAddress(11w-1-c),finalEncryptionKey)
Step7: Get the rawAddress = Concat(decryptedAddress, encryptionKey)
Step8: Determine the blockHeight
- If the first bit of rawAddress is 0, take the first 21 bit out of rawAddress. This is the blockHeight
- If the first bit of rawAddress is 1, drop it. Take the first 23 bit out of rawAddress. This is the blockHeight
- If the block does not exist, return error
Step9: Determine the txIndex
- Look up the blockchain for the referenced block and determine the total number of transactions in the block
- y1 = ceiling(log(total number of transactions in the block, 2))
- y2 = 11w-1-x-c
- y = min(y1, y2))
- Take the first y bits out of rawAddress. This is the txIndex
- If the transaction does not exist, return error
Step10: Determine the outputIndex
- Look up the referenced transaction and determine the total number of outputs in the transaction
- z1 = ceiling(log(total number of outputs in the transaction, 2))
- z2 = 11w-1-x-y-c
- z = min(z1, z2))
- Take the first z bits out of rawAddress. This is the outputIndex
- If the output does not exist, return error
Step11: Calculate the checksum
- Determine the blockHash and scriptPubKey
- rawChecksum = SHA256(SHA256(Concat(blockHash-txIndex-outputIndex-scriptPubKey)))
- checksum = rawChecksum(11w-1-x-y-z)
- If checksum equals to the remaining bits of rawAddress, the address is successfully resolved. Otherwise, return error.
==SPV client compatibility==
==Test vectors==
EDIT: I corrected a bug in the steps 3 and 4 of the generation code