From c56b60eb2d316876475f46386bc80442ba935a22 Mon Sep 17 00:00:00 2001 From: wanderer Date: Tue, 17 Nov 2015 17:33:32 +0000 Subject: [PATCH] added PoC docs --- preEIPS/README.md | 1 + preEIPS/poc1.md | 406 +++++++++++++++++++++++++++ preEIPS/poc3.md | 424 +++++++++++++++++++++++++++++ preEIPS/poc4.md | 679 ++++++++++++++++++++++++++++++++++++++++++++++ preEIPS/poc5.md | 125 +++++++++ preEIPS/poc6.md | 92 +++++++ 6 files changed, 1727 insertions(+) create mode 100644 preEIPS/README.md create mode 100644 preEIPS/poc1.md create mode 100644 preEIPS/poc3.md create mode 100644 preEIPS/poc4.md create mode 100644 preEIPS/poc5.md create mode 100644 preEIPS/poc6.md diff --git a/preEIPS/README.md b/preEIPS/README.md new file mode 100644 index 00000000..6b45da17 --- /dev/null +++ b/preEIPS/README.md @@ -0,0 +1 @@ +This folder contains the early Proof of Concept iteration. It is incompelete. PoC 2, 7, 8 and 9 are missing. diff --git a/preEIPS/poc1.md b/preEIPS/poc1.md new file mode 100644 index 00000000..8922ba4b --- /dev/null +++ b/preEIPS/poc1.md @@ -0,0 +1,406 @@ +Testnet simplifications: + +1. Difficulty formula + +D(genesisblock) = 2^22 +D(block) = D(block.parent) + D(block.parent) / 1024 * (1 if block.timestamp < block.parent.timestamp + 42 else -1) + + +2. Fees + +All fees are burned + +{ poc-2: +txFee = 100x +x = 100000000000000 = 10^14 +blockReward = 1500000000000000000 = 1.5 * 10^18; +} + +{ poc-3: +stepFee = 1x  +dataFee = 20x +memoryFee = 5x +extroFee = 40x +cryptoFee = 20x +newContractFee = 100x +txFee = 100x +x = 100000000000000 = 10^14 +blockReward = 1500000000000000000 = 1.5 * 10^18; +} + + +3. Premine + +We should all put our ethereum addresses made with the pyethtool.py script at https://github.com/ethereum/website/blob/master/pyethtool/pyethtool.py below: + +Each address gets 2^200 units premined + +{ poc-2: +8a40bfaa73256b60764c1bf40675a99083efb075 (G) +93658b04240e4bd4046fd2d6d417d20f146f4b43 (J) +1e12515ce3e0f817a4ddef9ca55788a1d66bd2df (V) +80c01a26338f0d905e295fccb71fa9ea849ffa12 (A) +} +{ poc-3: +8a40bfaa73256b60764c1bf40675a99083efb075 (G) +e6716f9544a56c530d868e4bfbacb172315bdead (J) +1e12515ce3e0f817a4ddef9ca55788a1d66bd2df (V) +1a26338f0d905e295fccb71fa9ea849ffa12aaf4 (A) +} + + +4. PoW + +sha(sha(blockheader_without_nonce) ++ nonce) <= 2^256 / difficulty + +where: +nonce and all outputs from sha are byte arrays of length 32; +++ is the concatenation operator; +<= operands are treated as bytearrays in BE format. + + +5. Uncles + +Nodes should NOT attempt to collect any uncles, although uncles should be included in the reward calculation. + + +6. Block & transactions formats: + +Though RLP is data-agnostic, it does specify a canonical representation for integer quantities. It is big-endian with no leading zero-bytes. Thus for elements than feasibly can be stored as integers, it becomes important to specify whether they should adhere to this canonical representation or be left in some other (perhaps more 'native') format. + +In the case of counts, balances, fees and amounts of wei, the canon-integer form must be used when storing in RLP. We call these INTs. + +In the case of hashes (256-bit or 160-bit), user-visible strings and specialised byte-arrays (e.g. hex-prefix notation from the trie), they should be stored as unformatted byte-array data and not altered into some other form. We call these BINs. + +When interpreting RLP data, clients are required to consider non-canonical INT fields in the same way as otherwise invalid RLP data and dismiss it completely. + +Specifically: + +for the Block header: +[ +    parentHash: BIN, +    unclesHash: BIN, +    coinbase: BIN, +    stateRoot: BIN, +    transactionsHash: BIN, +    difficulty: INT, +    timestamp: INT, +    extraData: BIN, +    nonce: BIN +] + +(note: 'nonce', the last element, refers to a hash here and so is binary) + +for entries in the State trie for normal addresses: +[ +    balance: INT, +    nonce: INT +] + +and for contract addresses: +[ +    balance: INT, +    nonce: INT, +    contractRoot: BIN +] + +(note: 'nonce', the second element, refers to a tx-count here and so is integer) + +for transactions: +[ +    nonce: INT, +    recvAddr: BIN, +    value: INT, +    data: [...], +    v: INT, +    r: INT, +    s: INT +] + +(note: 'nonce', the first element, refers to a tx-count here and so is integer) + +The nonce in the transaction refers to the total amount of transactions send from the address up until that moment in time. Not the total amount (ie. equal to the sender's nonce specified in the address) + +for blocks, there are no immediate data field, but lists: +[ +    blockHeader: [...] +    uncleList: [uncleHash1: BIN, uncleHash2: BIN, ...] +    txList: [...] +] + +Uncle-blocks contain only the uncle's header. + + +8. Block hashes + +When mining a block we use the header of the block without the nonce. This hash is also used during nonce validation [prevHash, uncleHash, coinbase, stateRoot, transactionsHash, difficulty, timestamp, extraData] + +When saving and refering to blocks (e.g. broadcasting, fetching, etc) we use the hash of the entire block ie [header (with nonce), uncle list, tx list] + + +9. Genesis Block + +The header of the genesis block is 8 items, and is specified thus: + +[zeroHash256, sha3(rlp([])), zeroHash160, state_root, sha3(rlp([])), 2**22, 0, "", 42] + +zeroHash256 refers to the parent hash, a 256-bit hash which is all zeroes. +zeroHash160 refers to the coinbase address, a 160-bit hash which is all zeroes. +2^22 refers to the difficulty. +0 refers to the timestamp (the Unix epoch). +"" refers to the extradata. +sha3(rlp([])) values refer to the hashes of the transaction and uncle lists, both empty. + +The SHA-3 hash of the RLP of this block (in its entirety) is: + +ab6b9a5613970faa771b12d449b2e9bb925ab7a369f0a4b86b286e9d540099cf + + +10. VM + +When a contract address receives a transaction, a virtual machine is initiated with the contract's state. + +10. a. Terms + +There exists a stack of variable size that stores 256-bit values at each location. (Note: most instructions operate solely on the stack altering its state in some way.) + +S'[i] is the ith item counting down from the top of the pre-stack (i.e. the stack immediately after instruction execution), with the top of the stack corresponding to i == 0. + +S[i] is the ith item counting down from the top of the post-stack (i.e. the stack immediately prior to instruction execution), with the top of the stack corresponding to i == 0. + + +The exists a permanent store addressable by a 256-bit value that stores 256-bit values at each location. + +P'[i] is the permanent store (sometimes refered to as 'state' or 'store') of the VM at index i counting from zero PRIOR to instruction execution. + +P[i] is the permanent store (sometimes refered to as 'state' or 'store') of the VM at index i counting from zero AFTER to instruction execution. + + +The exists a temporary store addressable by a 256-bit value that stores 256-bit values at each location. + +T'[i] is the temporary store (sometimes refered to as 'memory') of the VM at index i counting from zero PRIOR to instruction execution. + +T[i] is the temporary store (sometimes refered to as 'memory') of the VM at index i counting from zero AFTER instruction execution. + + +PC' is the program counter PRIOR to instruction execution. + +PC is the program counter AFTER instruction execution. + + +FEE(I, S', P', D) is the fee associated with the execution of instruction I with a machine of stack S', permanent store P' and which has already completed D operations. + +It is defined as F where: + +IF I == SSTORE AND P[ S'[0] ] != 0 AND S'[1] == 0 THEN +    F = S + dataFee - memoryFee +IF I == SSTORE AND P[ S'[0] ] == 0 AND S'[1] != 0 THEN +    F = S + dataFee + memoryFee +IF I == SLOAD +    F = S + dataFee +IF I == EXTRO OR I == BALANCE +    F = S + extroFee +IF I == MKTX +    F = S + txFee +IF I == SHA256 OR I == SHA3 OR I == RIPEMD160 OR I == ECMUL OR I == ECADD +    OR I == ECSIGN OR I == ECRECOVER OR I == ECVALID THEN +    F = S + cryptoFee  + +Where: + +S = D >= 16 ? stepFee : 0 + +Notably, MLOAD and MSTORE have no associated 'memory' cost. SLOAD and SSTORE both have a per-time fee (dataFee). There is also a usage 'fee' (not really a fee as it is all ultimately returned to the contract) that is owed to the contract for all non-zero permanent storage elements. This 'fee', memoryFee, is paid by the contract when a permanent storage address is set to a non-zero value and recovered when that address is set to a zero value. On SUICIDE, all permanent storage is dissolved and so all outstanding memoryFees are recovered. +     +     +B[ A ] is the balance of the address given by A, with A interpreted as an address. + +ADDRESS is the address of the present contract. + + +10. b. Initial Operation + +STEPSDONE := 0 +PC' := 0 +FOR ALL i: T'[i] := 0 +S' is initialised such that its cardinality is zero (i.e. the stack starts empty). +P' must be equal to the value of P when the previous execution halted. + +10. c. General Operation + +The given steps are looped: +1. Execution halts if B[ ADDRESS ] < F( P'[PC'], S', P', STEPSDONE ) +2. B[ ADDRESS ] := B[ ADDRESS ] - F( P'[PC'], S', P', STEPSDONE ) +3. The operation given by P'[PC'] determines PC, P, T, S. +4. PC' := PC; P' := P; T' := T; S' := S; STEPSDONE := STEPSDONE + 1 + +10. d. VM Operations + +Summary line: +: - + + +If PC is not defined explicitly, then it must be assumed PC := PC' + 1. Exceptions are PUSH, JMP and JMPI. + +The cardinality of S (i.e. size of the stack) is altered by A - R between S & S', by adding or removing items as necessary from the front. + +Where: +R: The minimal cardinality of the stack for this instruction to proceed. If this is not achieved then the machine halts with an stack underflow exception. (Note: In some cases of some implementations, this is also the number of values "popped" from the implementation's stack during the course of instruction execution.) +(A - R): The net change in cardinality of the stack over the course of instruction execution. + +FOR ALL i: if S[i] is not defined explicitly, then it must be assumed S[i] := S'[i + R - A] where i + R >= A. +FOR ALL i: if T[i] is not defined explicitly, then it must be assumed T[i] := T'[i]. +FOR ALL i: if P[i] is not defined explicitly, then it must be assumed P[i] := P'[i]. + +The expression (COND ? ONE : ZERO), where COND is an expression and ONE and ZERO are both value placeholders, evaluates to ONE if COND is true, and ZERO if COND is false. This is similar to the C-style ternary operator. + +When a 32-byte machine datum is interpreted as a 160-bit address or hash, the rightwards 20 bytes are taken (i.e. the low-order bytes when interpreting the data as Big-Endian). + +++ is the concatenation operator; all operands are byte arrays (mostly 32-byte arrays here, since that's the size of the VM's data & address types). + +LEFT_BYTES(A, n) returns the array bytes comprising the first (leftmost) n bytes of the 32 byte array A, which can be considered equivalent to a single value in the VM. + +10. e. VM Op-code Set + + • 0x00: STOP -0 +0 + ◦ Halts execution. + • 0x01: ADD -2 +1 + ◦ S[0] := S'[0] + S'[1] + • 0x02: MUL -2 +1 + ◦ S[0] := S'[0] * S'[1] + • 0x03: SUB -2 +1 + ◦ S[0] := S'[0] + S'[1] + • 0x04: DIV -2 +1 + ◦ S[0] := S'[0] / S'[1] + • 0x05: SDIV -2 +1 + ◦ S[0] := S'[0] / S'[1] + ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. + • 0x06: MOD -2 +1 + ◦ S[0] := S'[0] % S'[1] + • 0x07: SMOD -2 +1 + ◦ S[0] := S'[0] % S'[1] + ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. + • 0x08: EXP -2 +1 + ◦ S[0] := S'[0] + S'[1] + • 0x09: NEG -1 +1 + ◦ S[0] := -S'[0] + • 0x0a: LT -2 +1 + ◦ S[0] := S'[0] < S'[1] ? 1 : 0 + • 0x0b: LE -2 +1 + ◦ S[0] := S'[0] <= S'[1] ? 1 : 0 + • 0x0c: GT -2 +1 + ◦ S[0] := S'[0] > S'[1] ? 1 : 0 + • 0x0d: GE -2 +1 + ◦ S[0] := S'[0] >= S'[1] ? 1 : 0 + • 0x0e: EQ -2 +1 + ◦ S[0] := S'[0] == S'[1] ? 1 : 0 + • 0x0f: NOT -1 +1 + ◦ S[0] := S'[0] == 0 ? 1 : 0 + • 0x10: MYADDRESS -0 +1 + ◦ S[0] := ADDRESS + • 0x11: TXSENDER -0 +1 + ◦ S[0] := A + ◦ Where A is the address of the sender of the transaction that initiated this instance. + • 0x12: TXVALUE -0 +1 + ◦ S[0] := V + ◦ Where V is the value of the transaction that initiated this instance. + • 0x13: TXDATAN -0 +1 + ◦ S[0] := N + ◦ Where N is the number of data items of the transaction that initiated this instance. + • 0x14: TXDATA -1 +1 + ◦ S[0] := D[ S'[0] ] + ◦ Where D[i] is the ith data item, counting from zero, of the transaction that initiated this instance. + • 0x15: BLK_PREVHASH -0 +1 + ◦ S[0] := H + ◦ Where H is the SHA3 hash of the previous block. + • 0x16: BLK_COINBASE -0 +1 + ◦ S[0] := A + ◦ Where A is the coinbase address of the current block. + • 0x17: BLK_TIMESTAMP -0 +1 + ◦ S[0] := T + ◦ Where T is the timestamp of the current block (given as the Unix time_t when this block began its existence). + • 0x18: BLK_NUMBER -0 +1 + ◦ S[0] := N + ◦ Where N is the block number of the current block (counting upwards from genesis block which has N == 0). + • 0x19: BLK_DIFFICULTY -0 +1 + ◦ S[0] := D + ◦ Where D is the difficulty of the current block. + • 0x1a: BLK_NONCE -0 +1 + ◦ S[0] := H + ◦ Where H is the none of the previous block. + • 0x1b: BASEFEE -0 +1 + ◦ S[0] := V + ◦ Where V is the value of the current base fee (i.e. the fee multiplier). + •  0x20: SHA256 -(minimum: 1) +1 + ◦ S[0] := SHA256( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) + ◦ Where: + ◦ N = FLOOR(S'[0] / 32) + ◦ R = S'[0] % 32 + •  0x21: RIPEMD160 -(minimum: 1) +1 + ◦ S[0] := RIPEMD160( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) + ◦ Where all entities are as in SHA256 (0x20), above. + • 0x22: ECMUL -3 +1 + • 0x23: ECADD -4 +1 + • 0x24: ECSIGN -2 +1 + • 0x25: ECRECOVER -4 +1 + • 0x26: ECVALID -2 +1 + • 0x27: SHA3 -(minimum: 1) +1 + ◦ S[0] := SHA3( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) + ◦ Where all entities are as in SHA256 (0x20), above. + • 0x30: PUSH X -0 +1 + ◦ PC := PC' + 2 + ◦ S[0] := P[PC' + 1] + • 0x31: POP -1 +0 + • 0x32: DUP -1 +2 + ◦ S[0] := S'[0] + • 0x33: SWAP -2 +2 + ◦ S[0] := S'[1] + ◦ S[1] := S'[0] + • 0x34: MLOAD -1 +1 + ◦ S[0] := T'[ S'[0] ] + • 0x35: MSTORE -2 +0 + ◦ T[ S'[0] ] := S'[1] + • 0x36: SLOAD -1 +1 + ◦ S[0] := P'[ S'[0] ] + • 0x37: SSTORE -2 +0 + ◦ P[ S'[0] ] := S'[1] + • 0x38: JMP -1 +0 + ◦ PC := S'[0] + • 0x39: JMPI -2 +0 + ◦ PC := S'[0] == 0 ? PC' : S'[1] + • 0x3a: IND -0 +1 + ◦ S[0] := PC + • 0x3b: EXTRO -2 +1 + ◦ S[0] := CONTRACT[ S'[0] ].P[ S'[1] ] + ◦ Where CONTRACT[ A ].P is the permanent store of the contract A, with A interpreted as an address. + • 0x3c: BALANCE -1 +1 + ◦ S[0] := B[ S'[0] ] + • 0x3d: MKTX -(minimum: 3) +0 + ◦ Executes a transaction where: + ◦ The recipient is given by S'[0], when interpreted as an address. + ◦ The value is given by S'[1] + ◦ The data of the transaction is given by S'[3], S'[4], ... S'[ 2 + S'[2] ] + ◦ (Thus the number of data items of the transaction is given by S'[2].) + • 0x3f: SUICIDE -1 +0 + ◦ Halts execution. + ◦ FOR ALL i: IF P[i] NOT EQUAL TO 0 THEN B[ S'[0] ] := B[ S'[0] ] + memoryFee + ◦ B[ S'[0] ] := B[ S'[0] ] + B[ ADDRESS ] + ◦ Removes all contract-related information from the Ethereum system. + + +11. VM Memory State + +The memory state of the contract (which forms contractRoot) is formed by a secondary trie which may exist within the same database as the rest of the state. The root of this secondary trie defines the contractRoot. + +Whereas the main state trie has keys of length 160-bit (pertaining to an address in ethereum), the secondary contract state trie has keys of length 256-bit (pertaining to a point in memory of the virtual machine). In both cases, the key is a fixed length number of bytes. Leftly zeroes are not removed. + +Both tries have values encoded as RLP, whereby the value is interpreted as a single RLP element that is a 256-bit binary block (i.e. a 32 byte array). + +11. a. No Zeroes Stored in Trie + +Nodes in the memory trie may have any value EXCEPT zero (which is encoded in RLP as the empty byte array). We are able to do this because we assume that the value of a memory location, if not specified in the trie, defaults to zero. + +If a location in memory ever becomes zero, no value is stored in the trie for that location (requiring the removal of an entry from the trie if the previous value at that location is non-zero). If a memory lookup (i.e. SLOAD) ever happens for an undefined key, then the value returned is zero. + + +12. VM Tests + diff --git a/preEIPS/poc3.md b/preEIPS/poc3.md new file mode 100644 index 00000000..37901237 --- /dev/null +++ b/preEIPS/poc3.md @@ -0,0 +1,424 @@ +Testnet simplifications: + +1. Difficulty formula + +D(genesisblock) = 2^22 +D(block) = D(block.parent) + D(block.parent) / 1024 * (1 if block.timestamp < block.parent.timestamp + 42 else -1) + + +2. Fees + +All fees are burned + +{ poc-2: +txFee = 100x +x = 100000000000000 = 10^14 +blockReward = 1500000000000000000 = 1.5 * 10^18; +} + +{ poc-3: +stepFee = 1x  +dataFee = 20x +memoryFee = 5x +extroFee = 40x +cryptoFee = 20x +newContractFee = 100x +txFee = 100x +x = 100000000000000 = 10^14 +blockReward = 1500000000000000000 = 1.5 * 10^18; +} + + +3. Premine + +We should all put our ethereum addresses made with the pyethtool.py script at https://github.com/ethereum/website/blob/master/pyethtool/pyethtool.py below: + +Each address gets 2^200 units premined + +{ poc-2: +8a40bfaa73256b60764c1bf40675a99083efb075 (G) +93658b04240e4bd4046fd2d6d417d20f146f4b43 (J) +1e12515ce3e0f817a4ddef9ca55788a1d66bd2df (V) +80c01a26338f0d905e295fccb71fa9ea849ffa12 (A) +} +{ poc-3 & above: +8a40bfaa73256b60764c1bf40675a99083efb075 (G) +e6716f9544a56c530d868e4bfbacb172315bdead (J) +1e12515ce3e0f817a4ddef9ca55788a1d66bd2df (V) +1a26338f0d905e295fccb71fa9ea849ffa12aaf4 (A) +} + + +4. PoW + +sha(sha(blockheader_without_nonce) ++ nonce) <= 2^256 / difficulty + +where: +nonce and all outputs from sha are byte arrays of length 32; +++ is the concatenation operator; +<= operands are treated as bytearrays in BE format. + + +5. Uncles + +Nodes should NOT attempt to collect any uncles, although uncles should be included in the reward calculation. + + +6. Block & transactions formats: + +Though RLP is data-agnostic, it does specify a canonical representation for integer quantities. It is big-endian with no leading zero-bytes. Thus for elements than feasibly can be stored as integers, it becomes important to specify whether they should adhere to this canonical representation or be left in some other (perhaps more 'native') format. + +In the case of counts, balances, fees and amounts of wei, the canon-integer form must be used when storing in RLP. We call these INTs. + +In the case of hashes (256-bit or 160-bit), user-visible strings and specialised byte-arrays (e.g. hex-prefix notation from the trie), they should be stored as unformatted byte-array data and not altered into some other form. We call these BINs. + +When interpreting RLP data, clients are required to consider non-canonical INT fields in the same way as otherwise invalid RLP data and dismiss it completely. + +Specifically: + +for the Block header: +[ +    parentHash: BIN, +    unclesHash: BIN, +    coinbase: BIN, +    stateRoot: BIN, +    transactionsHash: BIN, +    difficulty: INT, +    timestamp: INT, +    extraData: BIN, +    nonce: BIN +] + +(note: 'nonce', the last element, refers to a hash here and so is binary) + +for entries in the State trie for normal addresses: +[ +    balance: INT, +    nonce: INT +] + +and for contract addresses: +[ +    balance: INT, +    nonce: INT, +    contractRoot: BIN +] + +(note: 'nonce', the second element, refers to a tx-count here and so is integer) + +for transactions: +[ +    nonce: INT, +    recvAddr: BIN, +    value: INT, +    data:  +    v: INT, +    r: INT, +    s: INT +] + +(note: 'nonce', the first element, refers to a tx-count here and so is integer) + +The nonce in the transaction refers to the total amount of transactions sent from the address up until that moment in time. + +for blocks, there are no immediate data field, but lists: +[ +    blockHeader: [...] +    uncleList: [ [...], [...], ... ] +    txList: [ [...], [...], ... ] +] + +Uncle-blocks contain only the uncle's header. + + +7. Network + +As specified on https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-Wire-Protocol + + +8. Block hashes + +When mining a block we use the header of the block without the nonce. This hash is also used during nonce validation. This header-without-nonce therefore contains [prevHash, uncleHash, coinbase, stateRoot, transactionsHash, difficulty, timestamp, extraData]. + +When saving and refering to blocks (e.g. broadcasting, fetching, etc) we use the hash of the entire block ie [header (with nonce), uncle list, tx list] + + +9. Genesis Block + +The header of the genesis block is 9 items, and is specified thus: + +[zeroHash256, sha3(rlp([])), zeroHash160, state_root, sha3(rlp([])), 2**22, 0, "", 42] + +zeroHash256 refers to the parent hash, a 256-bit hash which is all zeroes. +zeroHash160 refers to the coinbase address, a 160-bit hash which is all zeroes. +2^22 refers to the difficulty. +0 refers to the timestamp (the Unix epoch). +"" refers to the extradata. +sha3(rlp([])) values refer to the hashes of the transaction and uncle lists, both empty. + +The SHA-3 hash of the RLP of this block (in its entirety) is: + +ab6b9a5613970faa771b12d449b2e9bb925ab7a369f0a4b86b286e9d540099cf + + +10. VM + +When a contract address receives a transaction, a virtual machine is initiated with the contract's state. + +10. a. Terms + +There exists a stack of variable size that stores 256-bit values at each location. (Note: most instructions operate solely on the stack altering its state in some way.) + +S'[i] is the ith item counting down from the top of the pre-stack (i.e. the stack immediately after instruction execution), with the top of the stack corresponding to i == 0. + +S[i] is the ith item counting down from the top of the post-stack (i.e. the stack immediately prior to instruction execution), with the top of the stack corresponding to i == 0. + + +The exists a permanent store addressable by a 256-bit value that stores 256-bit values at each location. + +P'[i] is the permanent store (sometimes refered to as 'state' or 'store') of the VM at index i counting from zero PRIOR to instruction execution. + +P[i] is the permanent store (sometimes refered to as 'state' or 'store') of the VM at index i counting from zero AFTER to instruction execution. + + +The exists a temporary store addressable by a 256-bit value that stores 256-bit values at each location. + +T'[i] is the temporary store (sometimes refered to as 'memory') of the VM at index i counting from zero PRIOR to instruction execution. + +T[i] is the temporary store (sometimes refered to as 'memory') of the VM at index i counting from zero AFTER instruction execution. + + +PC' is the program counter PRIOR to instruction execution. + +PC is the program counter AFTER instruction execution. + + +FEE(I, S', P', D) is the fee associated with the execution of instruction I with a machine of stack S', permanent store P' and which has already completed D operations. + +It is defined as F where: + +IF I == SSTORE AND P[ S'[0] ] != 0 AND S'[1] == 0 THEN +    F = S + dataFee - memoryFee +IF I == SSTORE AND P[ S'[0] ] == 0 AND S'[1] != 0 THEN +    F = S + dataFee + memoryFee +IF I == SLOAD +    F = S + dataFee +IF I == EXTRO OR I == BALANCE +    F = S + extroFee +IF I == MKTX +    F = S + txFee +IF I == SHA256 OR I == SHA3 OR I == RIPEMD160 OR I == ECMUL OR I == ECADD +    OR I == ECSIGN OR I == ECRECOVER OR I == ECVALID THEN +    F = S + cryptoFee  + +Where: + +S = D >= 16 ? stepFee : 0 + +Notably, MLOAD and MSTORE have no associated 'memory' cost. SLOAD and SSTORE both have a per-time fee (dataFee). There is also a usage 'fee' (not really a fee as it is all ultimately returned to the contract) that is owed to the contract for all non-zero permanent storage elements. This 'fee', memoryFee, is paid by the contract when a permanent storage address is set to a non-zero value and recovered when that address is set to a zero value. On SUICIDE, all permanent storage is dissolved and so all outstanding memoryFees are recovered. +     +     +B[ A ] is the balance of the address given by A, with A interpreted as an address. + +ADDRESS is the address of the present contract. + + +10. b. Initial Operation + +STEPSDONE := 0 +PC' := 0 +FOR ALL i: T'[i] := 0 +S' is initialised such that its cardinality is zero (i.e. the stack starts empty). +P' must be equal to the value of P when the previous execution halted. + + +10. c. General Operation + +The given steps are looped: +1. Execution halts if B[ ADDRESS ] < F( P'[PC'], S', P', STEPSDONE ) +2. B[ ADDRESS ] := B[ ADDRESS ] - F( P'[PC'], S', P', STEPSDONE ) +3. The operation given by P'[PC'] determines PC, P, T, S. +4. PC' := PC; P' := P; T' := T; S' := S; STEPSDONE := STEPSDONE + 1 + + +10. d. VM Operations + +Summary line: +: - + + +If PC is not defined explicitly, then it must be assumed PC := PC' + 1. Exceptions are PUSH, JMP and JMPI. + +The cardinality of S (i.e. size of the stack) is altered by A - R between S & S', by adding or removing items as necessary from the front. + +Where: +R: The minimal cardinality of the stack for this instruction to proceed. If this is not achieved then the machine halts with a stack underflow exception. (Note: In some cases of some implementations, this is also the number of values "popped" from the implementation's stack during the course of instruction execution.) +(A - R): The net change in cardinality of the stack over the course of instruction execution. + +FOR ALL i: if S[i] is not defined explicitly, then it must be assumed S[i] := S'[i + R - A] where i + R >= A. +FOR ALL i: if T[i] is not defined explicitly, then it must be assumed T[i] := T'[i]. +FOR ALL i: if P[i] is not defined explicitly, then it must be assumed P[i] := P'[i]. + +The expression (COND ? ONE : ZERO), where COND is an expression and ONE and ZERO are both value placeholders, evaluates to ONE if COND is true, and ZERO if COND is false. This is similar to the C-style ternary operator. + +When a 32-byte machine datum is interpreted as a 160-bit address or hash, the rightwards 20 bytes are taken (i.e. the low-order bytes when interpreting the data as Big-Endian). + +++ is the concatenation operator; all operands are byte arrays (mostly 32-byte arrays here, since that's the size of the VM's data & address types). + +LEFT_BYTES(A, n) returns the array bytes comprising the first (leftmost) n bytes of the 32 byte array A, which can be considered equivalent to a single value in the VM. + +10. e. VM Op-code Set + + • 0x00: STOP -0 +0 + ◦ Halts execution. + • 0x01: ADD -2 +1 + ◦ S[0] := S'[0] + S'[1] + • 0x02: MUL -2 +1 + ◦ S[0] := S'[0] * S'[1] + • 0x03: SUB -2 +1 + ◦ S[0] := S'[0] + S'[1] + • 0x04: DIV -2 +1 + ◦ S[0] := S'[0] / S'[1] + • 0x05: SDIV -2 +1 + ◦ S[0] := S'[0] / S'[1] + ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. + • 0x06: MOD -2 +1 + ◦ S[0] := S'[0] % S'[1] + • 0x07: SMOD -2 +1 + ◦ S[0] := S'[0] % S'[1] + ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. + • 0x08: EXP -2 +1 + ◦ S[0] := S'[0] + S'[1] + • 0x09: NEG -1 +1 + ◦ S[0] := -S'[0] + • 0x0a: LT -2 +1 + ◦ S[0] := S'[0] < S'[1] ? 1 : 0 + • 0x0b: LE -2 +1 + ◦ S[0] := S'[0] <= S'[1] ? 1 : 0 + • 0x0c: GT -2 +1 + ◦ S[0] := S'[0] > S'[1] ? 1 : 0 + • 0x0d: GE -2 +1 + ◦ S[0] := S'[0] >= S'[1] ? 1 : 0 + • 0x0e: EQ -2 +1 + ◦ S[0] := S'[0] == S'[1] ? 1 : 0 + • 0x0f: NOT -1 +1 + ◦ S[0] := S'[0] == 0 ? 1 : 0 + • 0x10: MYADDRESS -0 +1 + ◦ S[0] := ADDRESS + • 0x11: TXSENDER -0 +1 + ◦ S[0] := A + ◦ Where A is the address of the sender of the transaction that initiated this instance. + • 0x12: TXVALUE -0 +1 + ◦ S[0] := V + ◦ Where V is the value of the transaction that initiated this instance. + • 0x13: TXDATAN -0 +1 + ◦ S[0] := N + ◦ Where N is the number of data items of the transaction that initiated this instance. + • 0x14: TXDATA -1 +1 + ◦ S[0] := D[ S'[0] ] + ◦ Where D[i] is the ith data item, counting from zero, of the transaction that initiated this instance. + • 0x15: BLK_PREVHASH -0 +1 + ◦ S[0] := H + ◦ Where H is the SHA3 hash of the previous block. + • 0x16: BLK_COINBASE -0 +1 + ◦ S[0] := A + ◦ Where A is the coinbase address of the current block. + • 0x17: BLK_TIMESTAMP -0 +1 + ◦ S[0] := T + ◦ Where T is the timestamp of the current block (given as the Unix time_t when this block began its existence). + • 0x18: BLK_NUMBER -0 +1 + ◦ S[0] := N + ◦ Where N is the block number of the current block (counting upwards from genesis block which has N == 0). + • 0x19: BLK_DIFFICULTY -0 +1 + ◦ S[0] := D + ◦ Where D is the difficulty of the current block. + • 0x1a: BLK_NONCE -0 +1 + ◦ S[0] := H + ◦ Where H is the none of the previous block. + • 0x1b: BASEFEE -0 +1 + ◦ S[0] := V + ◦ Where V is the value of the current base fee (i.e. the fee multiplier). + •  0x20: SHA256 -(minimum: 1) +1 + ◦ S[0] := SHA256( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) + ◦ Where: + ◦ N = FLOOR(S'[0] / 32) + ◦ R = S'[0] % 32 + •  0x21: RIPEMD160 -(minimum: 1) +1 + ◦ S[0] := RIPEMD160( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) + ◦ Where all entities are as in SHA256 (0x20), above. + • 0x22: ECMUL -3 +1 + • 0x23: ECADD -4 +1 + • 0x24: ECSIGN -2 +1 + • 0x25: ECRECOVER -4 +1 + • 0x26: ECVALID -2 +1 + • 0x27: SHA3 -(minimum: 1) +1 + ◦ S[0] := SHA3( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) + ◦ Where all entities are as in SHA256 (0x20), above. + • 0x30: PUSH X -0 +1 + ◦ PC := PC' + 2 + ◦ S[0] := P[PC' + 1] + • 0x31: POP -1 +0 + • 0x32: DUP -1 +2 + ◦ S[0] := S'[0] + • 0x33: SWAP -2 +2 + ◦ S[0] := S'[1] + ◦ S[1] := S'[0] + • 0x34: MLOAD -1 +1 + ◦ S[0] := T'[ S'[0] ] + • 0x35: MSTORE -2 +0 + ◦ T[ S'[0] ] := S'[1] + • 0x36: SLOAD -1 +1 + ◦ S[0] := P'[ S'[0] ] + • 0x37: SSTORE -2 +0 + ◦ P[ S'[0] ] := S'[1] + • 0x38: JMP -1 +0 + ◦ PC := S'[0] + • 0x39: JMPI -2 +0 + ◦ PC := S'[0] == 0 ? PC' : S'[1] + • 0x3a: IND -0 +1 + ◦ S[0] := PC + • 0x3b: EXTRO -2 +1 + ◦ S[0] := CONTRACT[ S'[0] ].P[ S'[1] ] + ◦ Where CONTRACT[ A ].P is the permanent store of the contract A, with A interpreted as an address. + • 0x3c: BALANCE -1 +1 + ◦ S[0] := B[ S'[0] ] + • 0x3d: MKTX -(minimum: 3) +0 + ◦ Immediately executes a transaction where: + ◦ The recipient is given by S'[0], when interpreted as an address. + ◦ The value is given by S'[1] + ◦ The data of the transaction is given by S'[3], S'[4], ... S'[ 2 + S'[2] ] + ◦ (Thus the number of data items of the transaction is given by S'[2].) + ◦ NOTE: This transaction is not queued; full ramifications take effect immediately, including balance transfers and any contract invokations. + • 0x3f: SUICIDE -1 +0 + ◦ Halts execution. + ◦ FOR ALL i: IF P[i] NOT EQUAL TO 0 THEN B[ S'[0] ] := B[ S'[0] ] + memoryFee + ◦ B[ S'[0] ] := B[ S'[0] ] + B[ ADDRESS ] + ◦ Removes all contract-related information from the Ethereum system. + + +11. VM Memory State + +The memory state of the contract (which forms contractRoot) is formed by a secondary trie which may exist within the same database as the rest of the state. The root of this secondary trie defines the contractRoot. + +Whereas the main state trie has keys of length 160-bit (pertaining to an address in ethereum), the secondary contract state trie has keys of length 256-bit (pertaining to a point in memory of the virtual machine). In both cases, the key is a fixed length number of bytes. Leftly zeroes are not removed. + +Both tries have values encoded as RLP, whereby the value is interpreted as a single RLP element that is a 256-bit binary block (i.e. a 32 byte array). + + +11. a. No Zeroes Stored in Trie + +Nodes in the memory trie may have any value EXCEPT zero (which is encoded in RLP as the empty byte array). We are able to do this because we assume that the value of a memory location, if not specified in the trie, defaults to zero. + +If a location in memory ever becomes zero, no value is stored in the trie for that location (requiring the removal of an entry from the trie if the previous value at that location is non-zero). If a memory lookup (i.e. SLOAD) ever happens for an undefined key, then the value returned is zero. + + +12. Transaction Execution + +Transactions should be executed once the validity of the transaction is ascertained. Validity is defined as: + + • Sender address balance at least transaction value + fee. + • Sender address nonce equal to transaction nonce. + • Only when the transaction creates a contract: There is no address collision. + +Once validity is ascertained, the balance may be transfered and the nonce incremented. If the transaction creates a contract then the memory should be initialised according to the transaction data. If the transaction invokes a contract, then that contract should be executed, by restarting an Ethereum Virtual Machine with the contract's state. + + diff --git a/preEIPS/poc4.md b/preEIPS/poc4.md new file mode 100644 index 00000000..08e8b5d8 --- /dev/null +++ b/preEIPS/poc4.md @@ -0,0 +1,679 @@ +PoC 4 + +### Big Changes + +We now make a distinction between state and code. Code is stored as an immutable byte array node in the state tree. Accounts have both a state and code hash. When creating contracts, two byte arrays containing EVM code are given: an initialiser (run once then discarded) and the body (stored in the state tree as mentioned). + +Transaction types are distinguished between  + +(i) A message call transaction now contains the following fields: + +    [ NONCE, VALUE, GASPRICE, GAS, TO, DATA, V, R, S ] + +(i) b. Whereas a contract creation transaction contains: + +    [ NONCE, VALUE, GASPRICE, GAS, 0, CODE, INIT, V, R, S ] (do we need the 0? take it out and it becomes ambiguous with the message call transaction above - How so, there's INIT which takes out the ambiguousity?) - both INIT and DATA are bytearrays hence the ambiguity. + +INIT gets run on creation. If this means that  + +### VM Execution Model + +The current operation is no longer taken from the (256-bit int) storage (P), but instead from a separate immutable byte array of code (C). All operations are bytes, and so are mostly the same as before. The only difference is for PUSH, which must now be split into 32 different opcodes, one for each length of data you wish to push onto the stack. This will mostly be PUSH32 or PUSH1. + +So, given C is the list of bytes of the currently executing code (which, could be CODE or INIT). So the operation to be done is O: + +O = C[ PC' ] + +### Addresses & Words + +Addresses are now formed from words by taking the left 160-bits. Words are formed from addresses conversely, through left-alignment. + +### VM Opcode Set + +# 0s: arithmetic operations + + • 0x00: STOP -0 +0 + ◦ Halts execution. + ◦ Any gas left over gets returned to caller (or in the case of the top-level call, the sender converted back to ETH). + • 0x01: ADD -2 +1 + ◦ S[0] := S'[0] + S'[1] + • 0x02: MUL -2 +1 + ◦ S[0] := S'[0] * S'[1] + • 0x03: SUB -2 +1 + ◦ S[0] := S'[0] - S'[1] + • 0x04: DIV -2 +1 + ◦ S[0] := S'[0] / S'[1] + • 0x05: SDIV -2 +1 + ◦ S[0] := S'[0] / S'[1] + ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. + • 0x06: MOD -2 +1 + ◦ S[0] := S'[0] % S'[1] + • 0x07: SMOD -2 +1 + ◦ S[0] := S'[0] % S'[1] + ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. + • 0x08: EXP -2 +1 + ◦ S[0] := S'[0] + S'[1] + • 0x09: NEG -1 +1 + ◦ S[0] := -S'[0] + • 0x0a: LT -2 +1 + ◦ S[0] := S'[0] < S'[1] ? 1 : 0 + • 0x0b: GT -2 +1 + ◦ S[0] := S'[0] > S'[1] ? 1 : 0 + • 0x0c: EQ -2 +1 + ◦ S[0] := S'[0] == S'[1] ? 1 : 0 + • 0x0d: NOT -1 +1 + ◦ S[0] := S'[0] == 0 ? 1 : 0 + +# 10s: bit operations + + • 0x10: AND -2 +1 + ◦ S[0] := S'[0] AND S'[1] + • 0x11: OR -2 +1 + ◦ S[0] := S'[0] OR S'[1] + • 0x12: XOR -2 +1 + ◦ S[0] := S'[0] XOR S'[1] + • 0x13: BYTE -2 +1 + ◦ S[0] := S'[0]th byte of S'[1] + ▪ if S'[0] < 32 + ◦ S[0] := 0 + ▪ otherwise + ◦ for Xth byte, we count from left - 0th is therefore the leftmost (most significant in BE) byte. + +# 20s: crypto opcodes + + • 0x20: SHA3 -2 +1 + ◦ S[0] := SHA3( T'[ S'[0] ++ ... ++ (S'[0] + S'[1]) ]) + +# 30s: closure state opcodes + + • 0x30: ADDRESS -0 +1 + ◦ S[0] := ADDRESS + ◦ i.e. the address of this closure. + • 0x31: BALANCE -1 +1 + ◦ S[0] := B[ S'[0] ] + ◦ i.e. the balance of this closure. + • 0x32: ORIGIN -0 +1 + ◦ S[0] := A + ◦ Where A is the address of the account that made the original transaction leading to the current closure and is paying the fees + • 0x33: CALLER -0 +1 + ◦ S[0] := A + ◦ Where A is the address of the object that made this call. + • 0x34: CALLVALUE -0 +1 + ◦ S[0] := V + ◦ Where V is the value attached to this call. + • 0x35: CALLDATALOAD -1 +0 + ◦ S[0] := D[ S'[0] ... (S'[0] + 31) ] + ◦ Where D is the data attached to this call (as a byte array). + ◦ Any bytes that are out of bounds of the data are defined as zero. + • 0x36: CALLDATASIZE -0 +1 + ◦ S[0] := DS + ◦ Where DS is the number of bytes of data attached to this call. + • 0x37: GASPRICE -0 +1 + ◦ S[0] := V + ◦ Where V is the current gas price (né fee multiplier). + +# 40s: block operations + + • 0x40: PREVHASH -0 +1 + ◦ S[0] := H + ◦ Where H is the SHA3 hash of the previous block. + • 0x41: COINBASE -0 +1 + ◦ S[0] := A + ◦ Where A is the coinbase address of the current block. + • 0x42: TIMESTAMP -0 +1 + ◦ S[0] := T + ◦ Where T is the timestamp of the current block (given as the Unix time_t when this block began its existence). + • 0x43: NUMBER -0 +1 + ◦ S[0] := N + ◦ Where N is the block number of the current block (counting upwards from genesis block which has N == 0). + • 0x44: DIFFICULTY -0 +1 + ◦ S[0] := D + ◦ Where D is the difficulty of the current block. + • 0x45: GASLIMIT -0 +1 + ◦ S[0] := L + ◦ Where L is the total gas limit of the current block. Always 10^6. + +# 50s: stack, memory, storage and execution path operations + + • 0x51: POP -1 +0 + • 0x52: DUP -1 +2 + ◦ S[0] := S'[0] + • 0x53: SWAP -2 +2 + ◦ S[0] := S'[1] + ◦ S[1] := S'[0] + • 0x54: MLOAD -1 +1 + ◦ S[0] := T'[ S'[0] ... S'[0] + 31 ] + • 0x55: MSTORE -2 +0 + ◦ T[ S'[0] ... S'[0] + 31 ] := S'[1] + • 0x56: MSTORE8 -2 +0 + ◦ T[ S'[0] ... S'[0] + 31 ] := S'[1] & 0xff + • 0x57: SLOAD -1 +1 + ◦ S[0] := P'[ S'[0] ] + • 0x58: SSTORE -2 +0 + ◦ P[ S'[0] ] := S'[1] + • 0x59: JUMP -1 +0 + ◦ PC := S'[0] + • 0x5a: JUMPI -2 +0 + ◦ PC := S'[1] == 0 ? PC' : S'[0] + • 0x:5b PC -0 +1 + ◦ S[0] := PC + • 0x5c: MSIZE -0 +1 + ◦ S[0] = sizeof(T) + • 0x5d: GAS + ◦ S[0] := G + ◦ Where G is the amount of gas remaining after executing the opcode. + +# 60s & 70s: push + • 0x60: PUSH1 0 +1 + ◦ S[0] := C[ PC' + 1 ] + ◦ PC := PC' + 2 + • 0x61: PUSH2 0 +1 + ◦ S[0] := C[ PC' + 1 ] ++ C[ PC' + 2 ] + ◦ PC := PC' + 3 +... + • 0x7f: PUSH32 0 +1 + ◦ S[0] := C[ PC' + 1 ] ++ C[ PC' + 2 ] ++ ... ++ C[ PC' + 32 ] + ◦ PC := PC' + 33 + +# f0s: closure-level operations + + • 0xf0: CREATE -5 +1 + ◦ Immediately creates a contract where: + ◦ The endowment is given by S'[0] + ◦ The body code of the eventual closure is given by T'[ S'[1] ... ( S'[1] + S'[2] - 1 ) ] + ◦ The initialisation code of the eventual closure is given by T'[ S'[3] ... ( S'[3] + S'[4] - 1 ) ] + ◦ (Thus the total number of bytes of the transaction data is given by S'[2] + S'[4].) + ◦ S[0] = A + ◦ where A is the address of the created contract or 0 if the creation failed. + ◦ Fees are deducted from the sender balance to pay for enough gas to complete the operation (i.e. contract creation fee + initial storage fee). If there was not enough gas to complete the operation, then all gas will be deducted and the operation fails. + • 0xf1: CALL -7 +1 + ◦ Immediately executes a call where: + ◦ The recipient is given by S'[0], when interpreted as an address. + ◦ The value is given by S'[1] + ◦ The gas is given by S'[2] + ◦ The input data of the call is given by T'[ S'[3] ... ( S'[3] + S'[4] - 1 ) ] + ◦ (Thus the number of bytes of the transaction is given by S'[4].) + ◦ The output data of the call is given by T[ S'[5] ... ( S'[5] + MIN( S'[6], S[0] ) - 1 ) ] + ◦ If 0 gas is specified, transfer all gas from the caller to callee gas balance, otherwise transfer only the amount given. If there isn't enough gas in the caller balance, operation fails. + ◦ If the value is less than the amount in the caller's balance then nothing is executed and the S'[2] gas gets refunded to the caller. + ◦ See Appendix A for execution. + ◦ Add any remaining callee gas to the caller's gas. + ◦ S[0] = R + ◦ where R = 1 when the instrinsic return code of the call is true, R = 0 otherwise. + • NOT YET: POST -5 +1 + ◦ Registers for delayed execution a call where: + ◦ The recipient is given by S'[0], when interpreted as an address. + ◦ The value is given by S'[1] + ◦ The gas to supply the transaction with is given by S'[2] (paid for from the current gas balance) + ◦ The input data of the call is given by T'[ S'[3] ... ( S'[3] + S'[4] - 1 ) ] + ◦ (Thus the number of bytes of the transaction is given by S'[4].) + ◦ Contract pays for itself to run at a defered time from its own GAS supply. The miner has no choice but to execute. + • NOT YET: ALARM -6 +1 + ◦ Registers for delayed execution a call where: + ◦ The recipient is given by S'[0], when interpreted as an address. + ◦ The value is given by S'[1] + ◦ The gas (to convert from ETH at the later time) is given by S'[2] + ◦ The number of blocks to wait before executing is S'[3] + ◦ The input data of the call is given by T'[ S'[4] ... ( S'[4] + S'[5] - 1 ) ] + ◦ (Thus the number of bytes of the transaction is given by S'[5].) + ◦ Total gas used now is S'[3] * S'[5] * deferFee. + ◦ Contract pays for itself to run at the defered time converting given amount of gas from its ETH balance; if it cannot pay it terminates as a bad transaction. TODO: include baseFee and allow miner freedom to determine whether to execute or not. If not, the next miner will have the chance. + • 0xf2: RETURN -2 +0 + ◦ Halts execution. + ◦ R := T[ S'[0] ... ( S'[0] + S'[1] - 1 ) ] + ◦ Where the output data of the call is specified as R. + ◦ Any gas left over gets returned to caller (or in the case of the top-level call, the sender converted back to ETH). + • 0xff: SUICIDE -1 +0 + ◦ Halts execution. + ◦ FOR ALL i: IF P[i] NOT EQUAL TO 0 THEN B[ S'[0] ] := B[ S'[0] ] + memoryFee + ◦ B[ S'[0] ] := B[ S'[0] ] + B[ ADDRESS ] + ◦ Removes all contract-related information from the Ethereum system. + + + +## Appendix A:  + +CALL has intrinsic parameters: + +TO, VALUE, GAS, INOFFSET, INSIZE, OUTOFFSET, OUTSIZE + +It also finishes an intrinsic boolean value relating to the success of the operation. + +The process for evaluating CALL is as follows: + +1. Let ROLLBACK := S where S is the current state. +2. Let program counter (PC) = 0. +Let it be known that all storage operations operate on TO's state. +Note that the memory is empty, thus (last used index + 1) = 0. +3. Set TXDATA to the first INSIZE bytes of memory starting from INOFFSET in the caller memory. +4. Repeat +    * Calculate the cost of the current instruction (see below), set to C +        * If the instruction is invalid or STOP, goto step 6. +    * If GAS < C then GAS := 0; S := ROLLBACK and evaluation finishes, returning false.  +    * GAS := GAS - C +    * Apply the instruction. +    Until an operation execution error has occured or the instruction is STOP, RETURN or SUICIDE. +5. If the output data of the call (R) is specified (through RETURN), then let the OUTSIZE bytes of caller memory beginning at OUTOFFSET. +6. Returns true. + + +## Appendix B + +Creation of a contract requires than an address be made: this is now defined as the left 160 bits of the SHA3 hash of the RLP encoded structure: + +[ SENDER, NONCE ] + +Should this address already be in use (i.e. have a node in the state tree) then, the address is incremented (as a bigendian int) and retried until it succeeds. + + +## Examples in HLL + +A few new contracts: + +### Namecoin + +    if tx.data[0] > 1000 and !contract.storage[tx.data[0]]: +         contract.storage[tx.data[0]] = tx.data[1] + +### Currency + +    if !contract.storage[1000]: +        contract.storage[1000] = 1 +                contract.storage[tx.sender] = 10^18 +    else: +        fbal = contract.storage[tx.sender] +        tbal = contract.storage[tx.data[0]] +        if fbal >= tx.data[1]: +            contract.storage[tx.sender] = fbal - tx.data[1] +            contract.storage[tx.data[0]] = tbal + tx.data[1] +                 +### Proprietary data feed + +    if tx.sender = : +        contract.storage[tx.data[0]] = tx.data[1] +    else: +        a = bytes(32) +        a[0] = contract.storage[tx.data[0]] +        return(a,32) + +### Stdlib (callable namecoin) + +Idea: [ 0, key, value ] to register, [ 1, key, returnsize, data... ] to use + +        if tx.data[0] == 0: +                if tx.data[1] > 1000 and !contract.storage[tx.data[1]]: +                        contract.storage[tx.data[1]] = tx.data[2] +        else: +                a = bytes(tx.data[2]) +                call(contract.storage[tx.data[1]],tx.value,tx.data+96,tx.datan-96,a,tx.data[2]) +                return(a,tx.data[2]) + +### Compilation tricks + +* Compile `bytes(expr)` as MSIZE DUP < EXPR > 1 SUB 0 PUSH SWAP MSTORE8 +* At the start of every compiled program, if `tx.data` is used more than zero times put `<(n+1)*32> CALLDATA PUSH (n+1) DUP MSTORE` where `n` represents the number of variables in the program (known at compile-time). + + +PoC 4 (was PoC 3.5) + +EVM: + +'Contracts' become 'Closures'. +'Transactions' become the things that are signed in some way and go in the transaction block. A transaction is enacted with a Message Call. +'Message Calls' encode a transfer of value (ETH) and invoke any code associated with the receiving object. + +The original caller (i.e. the original transaction's txsender) pre-pays for a specific amount of 'GAS'. What was baseFee now describes the ETH -> GAS price. Gas is the internal currency of the transaction. Execution operations deplete the GAS supply, as per the original ratios. Once the transaction is finished, any remaining GAS is reconverted back to ETH and refunded. + +Storage remains 256-bit address, 256-bit data. + +Word size: 256-bit (i.e. stack item size 256-bit). + +Memory is byte array (256-bit address, 8-bit data); memoryFee is proportional to greatest index that has ever been referenced in this instance and thus it's highly unlikely addresses will ever go above 32-bit. Whenever a higher memory index is used, the fee difference to take it to the higher usage from the original (lower) usage is charged. MEMSIZE is initially just the size of the input data. Note: MSTORE and MLOAD increase the highest-accessed index to their target index + 31. + +### Big Changes + +NOTE: Crypto functions, except SHA3, removed. +NOTE: SHA3 takes memory location & byte count. + +(i) A transaction now contains the following fields: + +    [ NONCE, VALUE, GASPRICE, GAS, TO, DATA, V, R, S ] + +* NONCE is a number, as in PoC-3 +* VALUE is a number, as in PoC-3 +* GAS is (as a number) the amount of GAS that will be exchanged from the sender's ETH balance in order to pay for all costs that happen due to this transaction. +* TO is a number (no longer the fixed 20-byte address that it was in PoC-3) +* GASPRICE is the wei per gas that the sender is willing to pay, as a number. +* DATA is a series of bytes +* V, R, S are numbers as before + +To evaluate: + +Let GASFEE := GAS * GASPRICE + +1. If GAS < TXDATAGAS * len(DATA) + CALLGAS , exit +1. Subtract GASFEE + VALUE from the sender's balance. If the sender's balance is too low, exit. +2. Let G := GAS - (TXDATAGAS * len(DATA) + CALLGAS) +3. Execute CALL operation with the instrinsic parameters (TO, VALUE, G, DATA, sizeof(DATA), 0, 0), (see Appendix A). +4. Add G * GASPRICE to sender's ETH balance where G is the remaining balance of gas from the CALL operation. + +(i) b. If the transaction creates a contract, it must be of the form: + +    [ NONCE, VALUE, GASPRICE, STORAGE, V, R, S ] + +Execution works as follows: 4. The algorithm is relatively computationally quick to verify, although  there is no “nice” verification formula that can be run inside EVM  code. + +Let GASFEE = (SSTOREGAS * D + CREATEGAS) * GASPRICE +where: +D is number of non-zero items of STORAGE + +1. Subtract GASFEE + VALUE from the sender's balance. If the sender's balance is too low, the transaction is declared invalid and no state change is recorded. +2. Put the contract into the blockchain, with the first portion of storage initialised to STORAGE and balance initialised to VALUE. + +NOTE: +(i) To determine if the transaction RLP encodes contract creation, extract nonce/value/basefee and then check if the following (fourth) item is a list - if so it's a creation transaction.     + +(ii) MKTX is renamed CALL. See appendix A for its execution. + +(iii) A new opcode RETURN is added. This allows the caller's memory bounded between OUTOFFSET and OUTOFFSET + OUTSIZE to be specified + +(iv) There is a block size limit (i.e. total gas allowed to be spent per block) which for PoC-3.5 is 10^6. + +### How to define instruction/step cost: + +Constants: + +* STEPGAS = 1 +* SHA3GAS = 20 +* SLOADGAS = 20 +* SSTOREGAS = 100 +* BALANCEGAS = 20 +* CREATEGAS = 100 +* CALLGAS = 20 +* MEMORYGAS = 1 +* TXDATAGAS = 5 [not used in the VM] + +Given an instruction, it is possible to calculate the gas cost of executing it as follows: + +* Unless covered by another rule below, an operation costs < STEPGAS > gas +* SHA3 costs < SHA3GAS > gas +* SLOAD costs < SLOADGAS > gas +* BALANCE costs < BALANCEGAS > gas +* SSTORE costs < D * SSTOREGAS > gas where: +- if the new value of the storage is non-zero and the old is zero, D = 2; +- if the new value of the storage is zero and the old is non-zero, D = 0; +- 1 otherwise. +* CALL costs < CALLGAS + G > gas, where G is the quantity of gas provided; some gas may be refunded though. +* CREATE costs < CREATEGAS + G > gas, where G is the quantity of gas provided. +* When you read or write memory with MSTORE, MLOAD, RETURN, SHA3, CALLDATA or CALL, enlarge the memory so that all bytes now fit in it (memory must always be a whole number of 32-byte words). Suppose that the highest previously accessed memory index is M, and the new index is N. If (N + 31) / 32 > (M + 31) / 32, add an additional < ((N + 31) / 32 - (M + 31) / 32) * MEMORYGAS > gas to the cost. + +For example, if you call `(TO, VALUE, 5000, 512, 512, 1024, 1024)`, and currently `N = 1024`, then we note that the total size of memory required is 2048 (the destination range is [1024, 2047]) and so 1024 addition , so the cost is `CALLGAS + 5000 + 1024 * MEMORYGAS = 6044`. + +### VM Opcode Set + +# 0s: arithmetic operations + + • 0x00: STOP -0 +0 + ◦ Halts execution. + ◦ Any gas left over gets returned to caller (or in the case of the top-level call, the sender converted back to ETH). + • 0x01: ADD -2 +1 + ◦ S[0] := S'[0] + S'[1] + • 0x02: MUL -2 +1 + ◦ S[0] := S'[0] * S'[1] + • 0x03: SUB -2 +1 + ◦ S[0] := S'[0] - S'[1] + • 0x04: DIV -2 +1 + ◦ S[0] := S'[0] / S'[1] + • 0x05: SDIV -2 +1 + ◦ S[0] := S'[0] / S'[1] + ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. + • 0x06: MOD -2 +1 + ◦ S[0] := S'[0] % S'[1] + • 0x07: SMOD -2 +1 + ◦ S[0] := S'[0] % S'[1] + ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. + • 0x08: EXP -2 +1 + ◦ S[0] := S'[0] + S'[1] + • 0x09: NEG -1 +1 + ◦ S[0] := -S'[0] + • 0x0a: LT -2 +1 + ◦ S[0] := S'[0] < S'[1] ? 1 : 0 + • 0x0b: GT -2 +1 + ◦ S[0] := S'[0] > S'[1] ? 1 : 0 + • 0x0c: EQ -2 +1 + ◦ S[0] := S'[0] == S'[1] ? 1 : 0 + • 0x0d: NOT -1 +1 + ◦ S[0] := S'[0] == 0 ? 1 : 0 + +# 10s: bit operations + + • 0x10: AND -2 +1 + ◦ S[0] := S'[0] AND S'[1] + • 0x11: OR -2 +1 + ◦ S[0] := S'[0] OR S'[1] + • 0x12: XOR -2 +1 + ◦ S[0] := S'[0] XOR S'[1] + • 0x13: BYTE -2 +1 + ◦ S[0] := S'[0]th byte of S'[1] + ▪ if S'[0] < 32 + ◦ S[0] := 0 + ▪ otherwise + ◦ for Xth byte, we count from left - 0th is therefore the leftmost (most significant in BE) byte. + +# 20s: crypto opcodes + + • 0x20: SHA3 -2 +1 + ◦ S[0] := SHA3( T'[ S'[0] ++ ... ++ (S'[0] + S'[1]) ]) + +# 30s: closure state opcodes + + • 0x30: ADDRESS -0 +1 + ◦ S[0] := ADDRESS + ◦ i.e. the address of this closure. + • 0x31: BALANCE -1 +1 + ◦ S[0] := B[ S'[0] ] + ◦ i.e. the balance of this closure. + • 0x32: ORIGIN -0 +1 + ◦ S[0] := A + ◦ Where A is the address of the account that made the original transaction leading to the current closure and is paying the fees + • 0x33: CALLER -0 +1 + ◦ S[0] := A + ◦ Where A is the address of the object that made this call. + • 0x34: CALLVALUE -0 +1 + ◦ S[0] := V + ◦ Where V is the value attached to this call. + • 0x35: CALLDATALOAD -1 +0 + ◦ S[0] := D[ S'[0] ... (S'[0] + 31) ] + ◦ Where D is the data attached to this call (as a byte array). + ◦ Any bytes that are out of bounds of the data are defined as zero. + • 0x36: CALLDATASIZE -0 +1 + ◦ S[0] := DS + ◦ Where DS is the number of bytes of data attached to this call. + • 0x37: GASPRICE -0 +1 + ◦ S[0] := V + ◦ Where V is the current gas price (né fee multiplier). + +# 40s: block operations + + • 0x40: PREVHASH -0 +1 + ◦ S[0] := H + ◦ Where H is the SHA3 hash of the previous block. + • 0x41: COINBASE -0 +1 + ◦ S[0] := A + ◦ Where A is the coinbase address of the current block. + • 0x42: TIMESTAMP -0 +1 + ◦ S[0] := T + ◦ Where T is the timestamp of the current block (given as the Unix time_t when this block began its existence). + • 0x43: NUMBER -0 +1 + ◦ S[0] := N + ◦ Where N is the block number of the current block (counting upwards from genesis block which has N == 0). + • 0x44: DIFFICULTY -0 +1 + ◦ S[0] := D + ◦ Where D is the difficulty of the current block. + • 0x45: GASLIMIT -0 +1 + ◦ S[0] := L + ◦ Where L is the total gas limit of the current block. Always 10^6. + +# 50s: stack, memory, storage and execution path operations + + • 0x50: PUSH X -0 +1 + ◦ PC := PC' + 2 + ◦ S[0] := P[PC' + 1] + • 0x51: POP -1 +0 + • 0x52: I -1 +2 + ◦ S[0] := S'[0] + • 0x53: SWAP -2 +2 + ◦ S[0] := S'[1] + ◦ S[1] := S'[0] + • 0x54: MLOAD -1 +1 + ◦ S[0] := T'[ S'[0] ... S'[0] + 31 ] + • 0x55: MSTORE -2 +0 + ◦ T[ S'[0] ... S'[0] + 31 ] := S'[1] + • 0x56: MSTORE8 -2 +0 + ◦ T[ S'[0] ... S'[0] + 31 ] := S'[1] & 0xff + • 0x57: SLOAD -1 +1 + ◦ S[0] := P'[ S'[0] ] + • 0x58: SSTORE -2 +0 + ◦ P[ S'[0] ] := S'[1] + • 0x59: JUMP -1 +0 + ◦ PC := S'[0] + • 0x5a: JUMPI -2 +0 + ◦ PC := S'[1] == 0 ? PC' : S'[0] + • 0x:5b PC -0 +1 + ◦ S[0] := PC + • 0x5c: MSIZE -0 +1 + ◦ S[0] = sizeof(T) + • 0x5d: GAS + ◦ S[0] := G + ◦ Where G is the amount of gas remaining after executing the opcode. + +# 60s: closure-level operations + + • 0x60: CREATE -5 +1 + ◦ Immediately creates a contract where: + ◦ The endowment is given by S'[0] + ◦ The input data of the call is given by T'[ S'[1] ... ( S'[1] + S'[2] - 1 ) ] + ◦ (Thus the number of bytes of the transaction data is given by S'[2].) + ◦ S[0] = A + ◦ where A is the address of the created contract. + ◦ Fees are deducted from the sender balance to pay for enough gas to complete the operation (i.e. contract creation fee + initial storage fee). + • 0x61: CALL -7 +1 + ◦ Immediately executes a call where: + ◦ The recipient is given by S'[0], when interpreted as an address. + ◦ The value is given by S'[1] + ◦ The gas is given by S'[2] + ◦ The input data of the call is given by T'[ S'[3] ... ( S'[3] + S'[4] - 1 ) ] + ◦ (Thus the number of bytes of the transaction is given by S'[4].) + ◦ The output data of the call is given by T[ S'[5] ... ( S'[5] + MIN( S'[6], S[0] ) - 1 ) ] + ◦ If 0 gas is specified, transfer all gas from the caller to callee gas balance, otherwise transfer only the amount given. If there isn't enough gas in the caller balance, operation fails. + ◦ If the value is less than the amount in the caller's balance then nothing is executed and the S'[2] gas gets refunded to the caller. + ◦ See Appendix A for execution. + ◦ Add any remaining callee gas to the caller's gas. + ◦ S[0] = R + ◦ where R = 1 when the instrinsic return code of the call is true, R = 0 otherwise. + • NOT YET: POST -5 +1 + ◦ Registers for delayed execution a call where: + ◦ The recipient is given by S'[0], when interpreted as an address. + ◦ The value is given by S'[1] + ◦ The gas to supply the transaction with is given by S'[2] (paid for from the current gas balance) + ◦ The input data of the call is given by T'[ S'[3] ... ( S'[3] + S'[4] - 1 ) ] + ◦ (Thus the number of bytes of the transaction is given by S'[4].) + ◦ Contract pays for itself to run at a defered time from its own GAS supply. The miner has no choice but to execute. + • NOT YET: ALARM -6 +1 + ◦ Registers for delayed execution a call where: + ◦ The recipient is given by S'[0], when interpreted as an address. + ◦ The value is given by S'[1] + ◦ The gas (to convert from ETH at the later time) is given by S'[2] + ◦ The number of blocks to wait before executing is S'[3] + ◦ The input data of the call is given by T'[ S'[4] ... ( S'[4] + S'[5] - 1 ) ] + ◦ (Thus the number of bytes of the transaction is given by S'[5].) + ◦ Total gas used now is S'[3] * S'[5] * deferFee. + ◦ Contract pays for itself to run at the defered time converting given amount of gas from its ETH balance; if it cannot pay it terminates as a bad transaction. TODO: include baseFee and allow miner freedom to determine whether to execute or not. If not, the next miner will have the chance. + • 0x62: RETURN -2 +0 + ◦ Halts execution. + ◦ R := T[ S'[0] ... ( S'[0] + S'[1] - 1 ) ] + ◦ Where the output data of the call is specified as R. + ◦ Any gas left over gets returned to caller (or in the case of the top-level call, the sender converted back to ETH). + • 0x7f: SUICIDE -1 +0 + ◦ Halts execution. + ◦ FOR ALL i: IF P[i] NOT EQUAL TO 0 THEN B[ S'[0] ] := B[ S'[0] ] + memoryFee + ◦ B[ S'[0] ] := B[ S'[0] ] + B[ ADDRESS ] + ◦ Removes all contract-related information from the Ethereum system. + +## Appendix A:  + +CALL has intrinsic parameters: + +TO, VALUE, GAS, INOFFSET, INSIZE, OUTOFFSET, OUTSIZE + +It also finishes an intrinsic boolean value relating to the success of the operation. + +The process for evaluating CALL is as follows: + +1. Let ROLLBACK := S where S is the current state. +2. Let program counter (PC) = 0. +Let it be known that all storage operations operate on TO's state. +Note that the memory is empty, thus (last used index + 1) = 0. +3. Set TXDATA to the first INSIZE bytes of memory starting from INOFFSET in the caller memory. +4. Repeat +    * Calculate the cost of the current instruction (see below), set to C +        * If the instruction is invalid or STOP, goto step 6. +    * If GAS < C then GAS := 0; S := ROLLBACK and evaluation finishes, returning false.  +    * GAS := GAS - C +    * Apply the instruction. +    Until an operation execution error has occured or the instruction is STOP, RETURN or SUICIDE. +5. If the output data of the call (R) is specified (through RETURN), then let the OUTSIZE bytes of caller memory beginning at OUTOFFSET. +6. Returns true. + + +## Appendix B + +Creation of a contract is as before, except that should there be an address collision in the creation of contract, the address is incremented (as a bigendian int) and retried until it succeeds. + + +## Examples in HLL + +A few new contracts: + +### Namecoin + +    if tx.data[0] > 1000 and !contract.storage[tx.data[0]]: +         contract.storage[tx.data[0]] = tx.data[1] + +### Currency + +    if !contract.storage[1000]: +        contract.storage[1000] = 1 +                contract.storage[tx.sender] = 10^18 +    else: +        fbal = contract.storage[tx.sender] +        tbal = contract.storage[tx.data[0]] +        if fbal >= tx.data[1]: +            contract.storage[tx.sender] = fbal - tx.data[1] +            contract.storage[tx.data[0]] = tbal + tx.data[1] +                 +### Proprietary data feed + +    if tx.sender = : +        contract.storage[tx.data[0]] = tx.data[1] +    else: +        a = bytes(32) +        a[0] = contract.storage[tx.data[0]] +        return(a,32) + +### Stdlib (callable namecoin) + +Idea: [ 0, key, value ] to register, [ 1, key, returnsize, data... ] to use + +        if tx.data[0] == 0: +                if tx.data[1] > 1000 and !contract.storage[tx.data[1]]: +                        contract.storage[tx.data[1]] = tx.data[2] +        else: +                a = bytes(tx.data[2]) +                call(contract.storage[tx.data[1]],tx.value,tx.data+96,tx.datan-96,a,tx.data[2]) +                return(a,tx.data[2]) + +### Compilation tricks + +* Compile `bytes(expr)` as MSIZE DUP < EXPR > 1 SUB 0 PUSH SWAP MSTORE8 +* At the start of every compiled program, if `tx.data` is used more than zero times put `<(n+1)*32> CALLDATA PUSH (n+1) DUP MSTORE` where `n` represents the number of variables in the program (known at compile-time). \ No newline at end of file diff --git a/preEIPS/poc5.md b/preEIPS/poc5.md new file mode 100644 index 00000000..d6f558be --- /dev/null +++ b/preEIPS/poc5.md @@ -0,0 +1,125 @@ +ALTERATIONS FOR SUICIDE + +Suicide's semantics are now: + +All funds are immediately transferred to the nominated recipient account, but the account itself remains valid. It is tagged for destruction, to be completed simultaneously with all remaining gas being refunded to the origination account (this can safely happen simultaneously since the suicidal account is necessarily a contract account and the transaction originator is necessarily externally controlled, non-contract account). + + + + +All accounts become the same type; code/storage is just empty for the non-contract accounts. + +Contract creation just specifies an initialiser; return of initialiser is body. + +[ nonce, price, gas, to, value, data, v, r, s] (to is 0 for contract creation) + +CALLDATACOPY instruction: +CALLDATACOPY MEMINDEX CALLDATAINDEX LEN? +CODESIZE +CODECOPY MEMINDEX CODEINDEX LEN + +CALL is now [ gas, to, value, datain, datain_sz, dataout, dataout_sz ] +CREATE is now [ value, datain, datain_sz ] + +Section 0x30 is now: +        ADDRESS, +        BALANCE, +        ORIGIN, +        CALLER, +        CALLVALUE, +        CALLDATALOAD, +        CALLDATASIZE, +        CALLDATACOPY = 0x37, +        CODESIZE = 0x38, +        CODECOPY = 0x39, +        GASPRICE = 0x3a, + + +Section 0x00 is now: +        STOP = 0x00,                ///< halts execution +        ADD, +        MUL, +        SUB, +        DIV, +        SDIV, +        MOD, +        SMOD, +        EXP, +        NEG, +        LT, +        GT, +        SLT = 0x0c,    // signed less than +        SGT = 0x0d,    // signed greater than +        EQ = 0x0e, +        NOT, + + + + +Use actual formula (LTMA) for gas limit: +gasLimit = floor((parent.gasLimit * (EMAFACTOR - 1) + floor(parent.gasUsed * BLK_LIMIT_FACTOR_NUM / BLK_LIMIT_FACTOR_DEN)) / EMA_FACTOR) + +BLK_LIMIT_FACTOR_NUM = 6 +BLK_LIMIT_FACTOR_DEN = 5 +EMA_FACTOR = 1024 + +For network protocol, switch IP Address to a 4-byte byte-array rather than a list of numbers.  + +Block format is now: +[ header, [ [tx0, s0, g0], [tx1, s1, g1], ...], [u0, u1, u2, ...] ] + +Block header format: +[prevHash, unclesHash, coinbase, stateRoot, txsTrieRoot, difficulty, number, minGasPrice, gasLimit, gasUsed, timestamp, extraData, nonce] + +extraData is a byte array length <= 1024. + +minGasPrice can default to 10 szabo for now. + +use triehash for the txlist instead of sha3ing the RLP: +triehash = Trie("").update(0, [tx0, s0, g0]).update(1, [tx1, s1, g1]).update( ..... ).root + +Where [tx(i), s(i), g(i)] are the ith transaction, the state root after applying the ith transaction, and the gas after applying the ith transaction and 0,1, etc are just numbers + +GAS costs: +Remove gas burn for tx data +5 GAS per byte of TXDATA +500 GAS per TXCOST +TXs no longer pay CREATE/CALL. + + +Genesis block + +Genesis block is: ( B32(0, 0, ...), B32(sha3(B())), B20(0, 0, ...), B32(stateRoot), B32(0, 0, ...), P(2^22), P(0), P(0), P(1000000), P(0), P(0), B(), B32(sha3(B(42))), B(), B() ) + +Genesis block items (as hex) are: +parentHash: 00000000000000000000000000000000000000000000000000000000000000000 +unclesHash: 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 +coinbase: 0000000000000000000000000000000000000000 +stateRoot: 11cc4aaa3b2f97cd6c858fcc0903b9b34b071e1798c91645f0e05e267028cb4a +txsTrieRoot: <> +difficulty: 400000 +number: <> +mixGasPrice: <> +gasLimit: 0f4240 +gasUsed: <> +timestamp: <> +extraData: <> +nonce: 04994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829 +transaction: <> +uncles: <> + +Genesis block RLP encoded (as hex) is: +f8abf8a7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a011cc4aaa3b2f97cd6c858fcc0903b9b34b071e1798c91645f0e05e267028cb4aa1680834000008080830f4240808080a004994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829c0c0 + +Note: B32 specifies a byte array of length 32, B20 specifies a byte array of length 20, B32(0, 0, ...) specifies a byte array filled with zeroes, B() specifies an empty byte array, B(42) specified a byte array of length 1 whose only element is of vaue 42, P specifies a positive integer (to be encoded as a bytearray in bigendian with no leading zeroes). + + +Javascript Bindings + +async & sync + +async is getX(..., function() {}) +sync is X(...) + + + diff --git a/preEIPS/poc6.md b/preEIPS/poc6.md new file mode 100644 index 00000000..900546ce --- /dev/null +++ b/preEIPS/poc6.md @@ -0,0 +1,92 @@ +POC-7 https://ethereum.etherpad.mozilla.org/14? +Latest changes: + + +--------------------------------------------------- + +Stateless contracts: +Additional opcode: 0xf4: CALLSTATELESS +Calls self, but grabbing the code from the TO argument instead of from one's own address +DONE PY,C++, go/Java + +-------------------------------------------------------- + +0x3b EXTCODESIZE +0x3c EXTCODECOPY +like CODECOPY, CODESIZE but takes an additional parameter at beginning (top of stack) containing address from which to copy. +DONE C++, Go, Java,JS + +-------------------------------------------------------- + +* zero-size memory reads/writes do not lead to a size increase for fee purposes + +DONE PY,C++, go, Java,JS + +-------------------------------------------------------- + +New opcodes: + +0x80...8f: DUP1 ... DUP16 +0x90...9f: SWAP1...SWAP16 (for LLVM cross-compilation) +0x14: ADDMOD +0x15: MULMOD (to make ecrecover easier) + +0x51, 0x52 are INVALID. + +DONE C++/GO/PY/Java,JS + +-------------------------------------------------------- + +0xf3: POST (same as call, except 5 arguments in and 0 arguments out, and instead of immediately calling it adds the call to a postqueue, to be executed after everything else (including prior-created posts) within the scope of that transaction execution is executed) + +Transaction finalisation: +- Create contract if transaction was contract-creation +- Keep executing earliest POST while postqueue isn't empty. +- Refund unused gas to caller (this includes gas unused from POSTs) & give fees to miner. +- Execute SUICIDEs. + +DONE C++/GO/PY,JS + +---------------------------------------------------- + +New GHOST protocol + + • A block can contain as uncles headers which satisfy all of the following criteria: + ◦ They are valid headers (not necessarily valid blocks) + ◦ Their parent is a kth generation ancestor for k in {2, 3, 4, 5, 6, 7} + ◦ They were not uncles of the kth generation ancestor for k in {1, 2, 3, 4, 5, 6} + • The uncle reward is increased to 15/16x the main block reward + • The nephew reward (ie. reward for including an uncle) is set to 1/32x the main block reward + • The target block time is 12s (ie. s/42/9/g in the diff adjustment algo) + • >= 5 -> increase + • <= 4 -> reduce + +SUGGESTION: target block time 4s (eg. >= 3 increase <= 2 reduce) as a temporary stress test + +DONE C++/PY/node.js, go/Java + +---------------------------------------------------- + +for blocks, block.hash = sha3(rlp.encode(block.header)) + +for accounts which don't have code, the code is "" +and the codehash is "" (instead of sha3(()) as in PoC5) + +for contract-creation transactions, address is empty rather than 000000000000000... + +DONE C++/PY, go/Java/node.js + +--------------------------------------------------- + +CALL, CREATE, CALLDATACOPY, etc should take memory indices as given, and not as mod 2^64 (this could just be implemented as a <=2^64 error check in the code, since using 2^64 memory will be prohibitively expensive) + +DONE C++/PY, Go/Java + +--------------------------------------------------- + +PoC-6 Networking (parallel downloads) + +DONE C++, Go, node.js/Java + +--------------------------------------------------- +