diff --git a/configs/constant_presets/mainnet.yaml b/configs/constant_presets/mainnet.yaml index d72b276c1..c0b7c6e9c 100644 --- a/configs/constant_presets/mainnet.yaml +++ b/configs/constant_presets/mainnet.yaml @@ -48,7 +48,7 @@ GENESIS_FORK_VERSION: 0x00000000 GENESIS_SLOT: 0 # 2**64 - 1 FAR_FUTURE_EPOCH: 18446744073709551615 -BLS_WITHDRAWAL_PREFIX_BYTE: 0x00 +BLS_WITHDRAWAL_PREFIX: 0 # Time parameters @@ -90,7 +90,7 @@ SLASHED_EXIT_LENGTH: 8192 # Reward and penalty quotients # --------------------------------------------------------------- # 2**5 (= 32) -BASE_REWARD_QUOTIENT: 32 +BASE_REWARD_FACTOR: 32 # 2**9 (= 512) WHISTLEBLOWING_REWARD_QUOTIENT: 512 # 2**3 (= 8) diff --git a/configs/constant_presets/minimal.yaml b/configs/constant_presets/minimal.yaml index 25f1e8419..cdd919927 100644 --- a/configs/constant_presets/minimal.yaml +++ b/configs/constant_presets/minimal.yaml @@ -47,7 +47,7 @@ GENESIS_FORK_VERSION: 0x00000000 GENESIS_SLOT: 0 # 2**64 - 1 FAR_FUTURE_EPOCH: 18446744073709551615 -BLS_WITHDRAWAL_PREFIX_BYTE: 0x00 +BLS_WITHDRAWAL_PREFIX: 0 # Time parameters @@ -58,23 +58,23 @@ SECONDS_PER_SLOT: 6 MIN_ATTESTATION_INCLUSION_DELAY: 2 # [customized] fast epochs SLOTS_PER_EPOCH: 8 -# 2**0 (= 1) epochs 6.4 minutes +# 2**0 (= 1) epochs MIN_SEED_LOOKAHEAD: 1 -# 2**2 (= 4) epochs 25.6 minutes +# 2**2 (= 4) epochs ACTIVATION_EXIT_DELAY: 4 # [customized] higher frequency new deposits from eth1 for testing SLOTS_PER_ETH1_VOTING_PERIOD: 16 # [customized] smaller state SLOTS_PER_HISTORICAL_ROOT: 64 -# 2**8 (= 256) epochs ~27 hours +# 2**8 (= 256) epochs MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 -# 2**11 (= 2,048) epochs 9 days +# 2**11 (= 2,048) epochs PERSISTENT_COMMITTEE_PERIOD: 2048 -# 2**6 (= 64) epochs ~7 hours +# 2**6 (= 64) epochs MAX_EPOCHS_PER_CROSSLINK: 64 -# 2**2 (= 4) epochs 25.6 minutes +# 2**2 (= 4) epochs MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4 -# [customized] 2**12 (= 4,096) epochs 18 days +# [customized] 2**12 (= 4,096) epochs EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS: 4096 @@ -91,7 +91,7 @@ SLASHED_EXIT_LENGTH: 64 # Reward and penalty quotients # --------------------------------------------------------------- # 2**5 (= 32) -BASE_REWARD_QUOTIENT: 32 +BASE_REWARD_FACTOR: 32 # 2**9 (= 512) WHISTLEBLOWING_REWARD_QUOTIENT: 512 # 2**3 (= 8) diff --git a/deposit_contract/contracts/validator_registration.json b/deposit_contract/contracts/validator_registration.json index 08d57f80a..1988b28c0 100644 --- a/deposit_contract/contracts/validator_registration.json +++ b/deposit_contract/contracts/validator_registration.json @@ -1 +1 @@ -{"abi": [{"name": "Deposit", "inputs": [{"type": "bytes", "name": "pubkey", "indexed": false}, {"type": "bytes", "name": "withdrawal_credentials", "indexed": false}, {"type": "bytes", "name": "amount", "indexed": false}, {"type": "bytes", "name": "signature", "indexed": false}, {"type": "bytes", "name": "merkle_tree_index", "indexed": false}], "anonymous": false, "type": "event"}, {"name": "Eth2Genesis", "inputs": [{"type": "bytes32", "name": "deposit_root", "indexed": false}, {"type": "bytes", "name": "deposit_count", "indexed": false}, {"type": "bytes", "name": "time", "indexed": false}], "anonymous": false, "type": "event"}, {"outputs": [], "inputs": [], "constant": false, "payable": false, "type": "constructor"}, {"name": "to_little_endian_64", "outputs": [{"type": "bytes", "name": "out"}], "inputs": [{"type": "uint256", "name": "value"}], "constant": true, "payable": false, "type": "function", "gas": 7077}, {"name": "get_deposit_root", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 79221}, {"name": "get_deposit_count", "outputs": [{"type": "bytes", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 11026}, {"name": "deposit", "outputs": [], "inputs": [{"type": "bytes", "name": "pubkey"}, {"type": "bytes", "name": "withdrawal_credentials"}, {"type": "bytes", "name": "signature"}], "constant": false, "payable": true, "type": "function", "gas": 445994}, {"name": "chainStarted", "outputs": [{"type": "bool", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 603}], "bytecode": "0x600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052341561009e57600080fd5b6101406000601f818352015b600061014051602081106100bd57600080fd5b600060c052602060c020015460208261016001015260208101905061014051602081106100e957600080fd5b600060c052602060c020015460208261016001015260208101905080610160526101609050602060c0825160208401600060025af161012757600080fd5b60c0519050606051600161014051018060405190131561014657600080fd5b809190121561015457600080fd5b6020811061016157600080fd5b600060c052602060c02001555b81516001018083528114156100aa575b505061140756600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a0526380673289600051141561026b57602060046101403734156100b457600080fd5b67ffffffffffffffff6101405111156100cc57600080fd5b60006101605261014051610180526101a060006008818352015b6101605160086000811215610103578060000360020a820461010a565b8060020a82025b905090506101605260ff61018051166101c052610160516101c0516101605101101561013557600080fd5b6101c051610160510161016052610180517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8600081121561017e578060000360020a8204610185565b8060020a82025b90509050610180525b81516001018083528114156100e6575b505060186008602082066101e001602082840111156101bc57600080fd5b60208061020082610160600060046015f15050818152809050905090508051602001806102a0828460006004600a8704601201f16101f957600080fd5b50506102a05160206001820306601f82010390506103006102a0516008818352015b8261030051111561022b57610247565b6000610300516102c001535b815160010180835281141561021b575b50505060206102805260406102a0510160206001820306601f8201039050610280f3005b63c5f2892f60005114156103c357341561028457600080fd5b6000610140526002546101605261018060006020818352015b600160016101605116141561031e57600061018051602081106102bf57600080fd5b600160c052602060c02001546020826102200101526020810190506101405160208261022001015260208101905080610220526102209050602060c0825160208401600060025af161031057600080fd5b60c05190506101405261038c565b6000610140516020826101a0010152602081019050610180516020811061034457600080fd5b600060c052602060c02001546020826101a0010152602081019050806101a0526101a09050602060c0825160208401600060025af161038257600080fd5b60c0519050610140525b610160600261039a57600080fd5b60028151048152505b815160010180835281141561029d575b50506101405160005260206000f3005b63621fd13060005114156104995734156103dc57600080fd5b60606101c060246380673289610140526002546101605261015c6000305af161040457600080fd5b6101e0805160200180610260828460006004600a8704601201f161042757600080fd5b50506102605160206001820306601f82010390506102c0610260516008818352015b826102c051111561045957610475565b60006102c05161028001535b8151600101808352811415610449575b5050506020610240526040610260510160206001820306601f8201039050610240f3005b63c47e300d600051141561125657606060046101403760506004356004016101a03760306004356004013511156104cf57600080fd5b60406024356004016102203760206024356004013511156104ef57600080fd5b608060443560040161028037606060443560040135111561050f57600080fd5b63ffffffff6002541061052157600080fd5b60306101a0511461053157600080fd5b6020610220511461054157600080fd5b6060610280511461055157600080fd5b633b9aca00610340526103405161056757600080fd5b61034051340461032052633b9aca0061032051101561058557600080fd5b6060610440602463806732896103c052610320516103e0526103dc6000305af16105ae57600080fd5b610460805160200180610360828460006004600a8704601201f16105d157600080fd5b50506002546104a05260006104c0526104a05160016104a0510110156105f657600080fd5b60016104a051016104e05261050060006020818352015b600160016104e05116141561062157610674565b6104c060605160018251018060405190131561063c57600080fd5b809190121561064a57600080fd5b8152506104e0600261065b57600080fd5b60028151048152505b815160010180835281141561060d575b505060006101a06030806020846105e001018260208501600060046016f1505080518201915050600060106020820661056001602082840111156106b757600080fd5b60208061058082610520600060046015f15050818152809050905090506010806020846105e001018260208501600060046013f1505080518201915050806105e0526105e09050602060c0825160208401600060025af161071757600080fd5b60c051905061054052600060006040602082066106800161028051828401111561074057600080fd5b6060806106a0826020602088068803016102800160006004601bf1505081815280905090509050602060c0825160208401600060025af161078057600080fd5b60c051905060208261088001015260208101905060006040602060208206610740016102805182840111156107b457600080fd5b606080610760826020602088068803016102800160006004601bf150508181528090509050905060208060208461080001018260208501600060046015f15050805182019150506105205160208261080001015260208101905080610800526108009050602060c0825160208401600060025af161083157600080fd5b60c051905060208261088001015260208101905080610880526108809050602060c0825160208401600060025af161086857600080fd5b60c051905061066052600060006105405160208261092001015260208101905061022060208060208461092001018260208501600060046015f150508051820191505080610920526109209050602060c0825160208401600060025af16108ce57600080fd5b60c0519050602082610aa00101526020810190506000610360600880602084610a2001018260208501600060046012f150508051820191505060006018602082066109a0016020828401111561092357600080fd5b6020806109c082610520600060046015f1505081815280905090509050601880602084610a2001018260208501600060046014f150508051820191505061066051602082610a2001015260208101905080610a2052610a209050602060c0825160208401600060025af161099657600080fd5b60c0519050602082610aa001015260208101905080610aa052610aa09050602060c0825160208401600060025af16109cd57600080fd5b60c051905061090052610b2060006020818352015b6104c051610b20511215610a62576000610b205160208110610a0357600080fd5b600160c052602060c0200154602082610b4001015260208101905061090051602082610b4001015260208101905080610b4052610b409050602060c0825160208401600060025af1610a5457600080fd5b60c051905061090052610a67565b610a78565b5b81516001018083528114156109e2575b5050610900516104c05160208110610a8f57600080fd5b600160c052602060c02001556002805460018254011015610aaf57600080fd5b60018154018155506060610c4060246380673289610bc0526104a051610be052610bdc6000305af1610ae057600080fd5b610c60805160200180610ca0828460006004600a8704601201f1610b0357600080fd5b505060a0610d2052610d2051610d60526101a0805160200180610d2051610d6001828460006004600a8704601201f1610b3b57600080fd5b5050610d2051610d60015160206001820306601f8201039050610d2051610d6001610d0081516040818352015b83610d0051101515610b7957610b96565b6000610d00516020850101535b8151600101808352811415610b68575b505050506020610d2051610d60015160206001820306601f8201039050610d20510101610d2052610d2051610d8052610220805160200180610d2051610d6001828460006004600a8704601201f1610bed57600080fd5b5050610d2051610d60015160206001820306601f8201039050610d2051610d6001610d0081516020818352015b83610d0051101515610c2b57610c48565b6000610d00516020850101535b8151600101808352811415610c1a575b505050506020610d2051610d60015160206001820306601f8201039050610d20510101610d2052610d2051610da052610360805160200180610d2051610d6001828460006004600a8704601201f1610c9f57600080fd5b5050610d2051610d60015160206001820306601f8201039050610d2051610d6001610d0081516020818352015b83610d0051101515610cdd57610cfa565b6000610d00516020850101535b8151600101808352811415610ccc575b505050506020610d2051610d60015160206001820306601f8201039050610d20510101610d2052610d2051610dc052610280805160200180610d2051610d6001828460006004600a8704601201f1610d5157600080fd5b5050610d2051610d60015160206001820306601f8201039050610d2051610d6001610d0081516060818352015b83610d0051101515610d8f57610dac565b6000610d00516020850101535b8151600101808352811415610d7e575b505050506020610d2051610d60015160206001820306601f8201039050610d20510101610d2052610d2051610de052610ca0805160200180610d2051610d6001828460006004600a8704601201f1610e0357600080fd5b5050610d2051610d60015160206001820306601f8201039050610d2051610d6001610d0081516020818352015b83610d0051101515610e4157610e5e565b6000610d00516020850101535b8151600101808352811415610e30575b505050506020610d2051610d60015160206001820306601f8201039050610d20510101610d20527fdc5fc95703516abd38fa03c3737ff3b52dc52347055c8028460fdf5bbe2f12ce610d2051610d60a164077359400061032051101515611254576003805460018254011015610ed357600080fd5b60018154018155506201000060035414156112535742610e205242610e405262015180610eff57600080fd5b62015180610e405106610e20511015610f1757600080fd5b42610e405262015180610f2957600080fd5b62015180610e405106610e2051036202a30042610e205242610e405262015180610f5257600080fd5b62015180610e405106610e20511015610f6a57600080fd5b42610e405262015180610f7c57600080fd5b62015180610e405106610e205103011015610f9657600080fd5b6202a30042610e205242610e405262015180610fb157600080fd5b62015180610e405106610e20511015610fc957600080fd5b42610e405262015180610fdb57600080fd5b62015180610e405106610e20510301610e00526020610ee0600463c5f2892f610e8052610e9c6000305af161100f57600080fd5b610ee051610e60526060610f8060246380673289610f0052600254610f2052610f1c6000305af161103f57600080fd5b610fa0805160200180610fe0828460006004600a8704601201f161106257600080fd5b505060606110c06024638067328961104052610e00516110605261105c6000305af161108d57600080fd5b6110e0805160200180611120828460006004600a8704601201f16110b057600080fd5b5050610e60516111e05260606111a0526111a05161120052610fe08051602001806111a0516111e001828460006004600a8704601201f16110f057600080fd5b50506111a0516111e0015160206001820306601f82010390506111a0516111e00161118081516020818352015b836111805110151561112e5761114b565b6000611180516020850101535b815160010180835281141561111d575b5050505060206111a0516111e0015160206001820306601f82010390506111a05101016111a0526111a051611220526111208051602001806111a0516111e001828460006004600a8704601201f16111a257600080fd5b50506111a0516111e0015160206001820306601f82010390506111a0516111e00161118081516020818352015b83611180511015156111e0576111fd565b6000611180516020850101535b81516001018083528114156111cf575b5050505060206111a0516111e0015160206001820306601f82010390506111a05101016111a0527f08b71ef3f1b58f7a23ffb82e27f12f0888c8403f1ceb0ea7ea26b274e2189d4c6111a0516111e0a160016004555b5b005b63845980e8600051141561127c57341561126f57600080fd5b60045460005260206000f3005b60006000fd5b61018561140703610185600039610185611407036000f3"} \ No newline at end of file +{"abi": [{"name": "Deposit", "inputs": [{"type": "bytes", "name": "pubkey", "indexed": false}, {"type": "bytes", "name": "withdrawal_credentials", "indexed": false}, {"type": "bytes", "name": "amount", "indexed": false}, {"type": "bytes", "name": "signature", "indexed": false}, {"type": "bytes", "name": "index", "indexed": false}], "anonymous": false, "type": "event"}, {"outputs": [], "inputs": [], "constant": false, "payable": false, "type": "constructor"}, {"name": "get_deposit_root", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 79221}, {"name": "get_deposit_count", "outputs": [{"type": "bytes", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 10433}, {"name": "deposit", "outputs": [], "inputs": [{"type": "bytes", "name": "pubkey"}, {"type": "bytes", "name": "withdrawal_credentials"}, {"type": "bytes", "name": "signature"}], "constant": false, "payable": true, "type": "function", "gas": 1334417}], "bytecode": "0x600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052341561009e57600080fd5b6101406000601f818352015b600061014051602081106100bd57600080fd5b600260c052602060c020015460208261016001015260208101905061014051602081106100e957600080fd5b600260c052602060c020015460208261016001015260208101905080610160526101609050602060c0825160208401600060025af161012757600080fd5b60c0519050606051600161014051018060405190131561014657600080fd5b809190121561015457600080fd5b6020811061016157600080fd5b600260c052602060c02001555b81516001018083528114156100aa575b50506111c656600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052600015610277575b6101605261014052600061018052610140516101a0526101c060006008818352015b61018051600860008112156100da578060000360020a82046100e1565b8060020a82025b905090506101805260ff6101a051166101e052610180516101e0516101805101101561010c57600080fd5b6101e0516101805101610180526101a0517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86000811215610155578060000360020a820461015c565b8060020a82025b905090506101a0525b81516001018083528114156100bd575b50506018600860208206610200016020828401111561019357600080fd5b60208061022082610180600060046015f15050818152809050905090508051602001806102c0828460006004600a8704601201f16101d057600080fd5b50506102c05160206001820306601f82010390506103206102c0516008818352015b826103205111156102025761021e565b6000610320516102e001535b81516001018083528114156101f2575b50505060206102a05260406102c0510160206001820306601f8201039050610280525b6000610280511115156102535761026f565b602061028051036102a001516020610280510361028052610241565b610160515650005b63c5f2892f60005114156103cf57341561029057600080fd5b6000610140526001546101605261018060006020818352015b600160016101605116141561032a57600061018051602081106102cb57600080fd5b600060c052602060c02001546020826102200101526020810190506101405160208261022001015260208101905080610220526102209050602060c0825160208401600060025af161031c57600080fd5b60c051905061014052610398565b6000610140516020826101a0010152602081019050610180516020811061035057600080fd5b600260c052602060c02001546020826101a0010152602081019050806101a0526101a09050602060c0825160208401600060025af161038e57600080fd5b60c0519050610140525b61016060026103a657600080fd5b60028151048152505b81516001018083528114156102a9575b50506101405160005260206000f3005b63621fd13060005114156104e15734156103e857600080fd5b63806732896101405260015461016052610160516006580161009b565b506101c0526000610220525b6101c05160206001820306601f8201039050610220511015156104335761044c565b610220516101e001526102205160200161022052610411565b6101c0805160200180610280828460006004600a8704601201f161046f57600080fd5b50506102805160206001820306601f82010390506102e0610280516008818352015b826102e05111156104a1576104bd565b60006102e0516102a001535b8151600101808352811415610491575b5050506020610260526040610280510160206001820306601f8201039050610260f3005b63c47e300d600051141561103b57606060046101403760506004356004016101a037603060043560040135111561051757600080fd5b604060243560040161022037602060243560040135111561053757600080fd5b608060443560040161028037606060443560040135111561055757600080fd5b63ffffffff6001541061056957600080fd5b633b9aca00610340526103405161057f57600080fd5b61034051340461032052633b9aca0061032051101561059d57600080fd5b60306101a051146105ad57600080fd5b602061022051146105bd57600080fd5b606061028051146105cd57600080fd5b6101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e05161030051610320516103405161036051610380516103a05163806732896103c052610320516103e0526103e0516006580161009b565b506104405260006104a0525b6104405160206001820306601f82010390506104a05110151561065d57610676565b6104a05161046001526104a0516020016104a05261063b565b6103a05261038052610360526103405261032052610300526102e0526102c0526102a05261028052610260526102405261022052610200526101e0526101c0526101a052610440805160200180610360828460006004600a8704601201f16106dd57600080fd5b50506101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e05161030051610320516103405161036051610380516103a0516103c0516103e05161040051610420516104405161046051610480516104a05163806732896104c0526001546104e0526104e0516006580161009b565b506105405260006105a0525b6105405160206001820306601f82010390506105a05110151561078e576107a7565b6105a05161056001526105a0516020016105a05261076c565b6104a05261048052610460526104405261042052610400526103e0526103c0526103a05261038052610360526103405261032052610300526102e0526102c0526102a05261028052610260526102405261022052610200526101e0526101c0526101a0526105408051602001806105c0828460006004600a8704601201f161082e57600080fd5b505060a06106405261064051610680526101a08051602001806106405161068001828460006004600a8704601201f161086657600080fd5b505061064051610680015160206001820306601f8201039050610640516106800161062081516040818352015b83610620511015156108a4576108c1565b6000610620516020850101535b8151600101808352811415610893575b50505050602061064051610680015160206001820306601f820103905061064051010161064052610640516106a0526102208051602001806106405161068001828460006004600a8704601201f161091857600080fd5b505061064051610680015160206001820306601f8201039050610640516106800161062081516020818352015b836106205110151561095657610973565b6000610620516020850101535b8151600101808352811415610945575b50505050602061064051610680015160206001820306601f820103905061064051010161064052610640516106c0526103608051602001806106405161068001828460006004600a8704601201f16109ca57600080fd5b505061064051610680015160206001820306601f8201039050610640516106800161062081516020818352015b8361062051101515610a0857610a25565b6000610620516020850101535b81516001018083528114156109f7575b50505050602061064051610680015160206001820306601f820103905061064051010161064052610640516106e0526102808051602001806106405161068001828460006004600a8704601201f1610a7c57600080fd5b505061064051610680015160206001820306601f8201039050610640516106800161062081516060818352015b8361062051101515610aba57610ad7565b6000610620516020850101535b8151600101808352811415610aa9575b50505050602061064051610680015160206001820306601f82010390506106405101016106405261064051610700526105c08051602001806106405161068001828460006004600a8704601201f1610b2e57600080fd5b505061064051610680015160206001820306601f8201039050610640516106800161062081516020818352015b8361062051101515610b6c57610b89565b6000610620516020850101535b8151600101808352811415610b5b575b50505050602061064051610680015160206001820306601f8201039050610640510101610640527fdc5fc95703516abd38fa03c3737ff3b52dc52347055c8028460fdf5bbe2f12ce61064051610680a160006107205260006101a06030806020846107e001018260208501600060046016f150508051820191505060006010602082066107600160208284011115610c2057600080fd5b60208061078082610720600060046015f15050818152809050905090506010806020846107e001018260208501600060046013f1505080518201915050806107e0526107e09050602060c0825160208401600060025af1610c8057600080fd5b60c0519050610740526000600060406020820661088001610280518284011115610ca957600080fd5b6060806108a0826020602088068803016102800160006004601bf1505081815280905090509050602060c0825160208401600060025af1610ce957600080fd5b60c0519050602082610a800101526020810190506000604060206020820661094001610280518284011115610d1d57600080fd5b606080610960826020602088068803016102800160006004601bf1505081815280905090509050602080602084610a0001018260208501600060046015f150508051820191505061072051602082610a0001015260208101905080610a0052610a009050602060c0825160208401600060025af1610d9a57600080fd5b60c0519050602082610a8001015260208101905080610a8052610a809050602060c0825160208401600060025af1610dd157600080fd5b60c0519050610860526000600061074051602082610b20010152602081019050610220602080602084610b2001018260208501600060046015f150508051820191505080610b2052610b209050602060c0825160208401600060025af1610e3757600080fd5b60c0519050602082610ca00101526020810190506000610360600880602084610c2001018260208501600060046012f15050805182019150506000601860208206610ba00160208284011115610e8c57600080fd5b602080610bc082610720600060046015f1505081815280905090509050601880602084610c2001018260208501600060046014f150508051820191505061086051602082610c2001015260208101905080610c2052610c209050602060c0825160208401600060025af1610eff57600080fd5b60c0519050602082610ca001015260208101905080610ca052610ca09050602060c0825160208401600060025af1610f3657600080fd5b60c0519050610b00526001805460018254011015610f5357600080fd5b6001815401815550600154610d2052610d4060006020818352015b60016001610d2051161415610fa357610b0051610d405160208110610f9257600080fd5b600060c052602060c0200155611037565b6000610d405160208110610fb657600080fd5b600060c052602060c0200154602082610d60010152602081019050610b0051602082610d6001015260208101905080610d6052610d609050602060c0825160208401600060025af161100757600080fd5b60c0519050610b0052610d20600261101e57600080fd5b60028151048152505b8151600101808352811415610f6e575b5050005b60006000fd5b6101856111c6036101856000396101856111c6036000f3"} \ No newline at end of file diff --git a/deposit_contract/contracts/validator_registration.v.py b/deposit_contract/contracts/validator_registration.v.py index 1d475311a..14f100520 100644 --- a/deposit_contract/contracts/validator_registration.v.py +++ b/deposit_contract/contracts/validator_registration.v.py @@ -1,140 +1,103 @@ MIN_DEPOSIT_AMOUNT: constant(uint256) = 1000000000 # Gwei -FULL_DEPOSIT_AMOUNT: constant(uint256) = 32000000000 # Gwei -CHAIN_START_FULL_DEPOSIT_THRESHOLD: constant(uint256) = 65536 # 2**16 DEPOSIT_CONTRACT_TREE_DEPTH: constant(uint256) = 32 -SECONDS_PER_DAY: constant(uint256) = 86400 -MAX_64_BIT_VALUE: constant(uint256) = 18446744073709551615 # 2**64 - 1 +MAX_DEPOSIT_COUNT: constant(uint256) = 4294967295 # 2**DEPOSIT_CONTRACT_TREE_DEPTH - 1 PUBKEY_LENGTH: constant(uint256) = 48 # bytes WITHDRAWAL_CREDENTIALS_LENGTH: constant(uint256) = 32 # bytes +AMOUNT_LENGTH: constant(uint256) = 8 # bytes SIGNATURE_LENGTH: constant(uint256) = 96 # bytes -MAX_DEPOSIT_COUNT: constant(uint256) = 4294967295 # 2**DEPOSIT_CONTRACT_TREE_DEPTH - 1 Deposit: event({ pubkey: bytes[48], withdrawal_credentials: bytes[32], amount: bytes[8], signature: bytes[96], - merkle_tree_index: bytes[8], + index: bytes[8], }) -Eth2Genesis: event({deposit_root: bytes32, deposit_count: bytes[8], time: bytes[8]}) -zerohashes: bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] branch: bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] deposit_count: uint256 -full_deposit_count: uint256 -chainStarted: public(bool) - +# Compute hashes in empty sparse Merkle tree +zero_hashes: bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] @public def __init__(): for i in range(DEPOSIT_CONTRACT_TREE_DEPTH - 1): - self.zerohashes[i+1] = sha256(concat(self.zerohashes[i], self.zerohashes[i])) + self.zero_hashes[i + 1] = sha256(concat(self.zero_hashes[i], self.zero_hashes[i])) -@public +@private @constant def to_little_endian_64(value: uint256) -> bytes[8]: - assert value <= MAX_64_BIT_VALUE - - # array access for bytes[] not currently supported in vyper so - # reversing bytes using bitwise uint256 manipulations + # Reversing bytes using bitwise uint256 manipulations + # Note: array accesses of bytes[] are not currently supported in Vyper + # Note: this function is only called when `value < 2**64` y: uint256 = 0 x: uint256 = value - for i in range(8): + for _ in range(8): y = shift(y, 8) y = y + bitwise_and(x, 255) x = shift(x, -8) - return slice(convert(y, bytes32), start=24, len=8) @public @constant def get_deposit_root() -> bytes32: - root: bytes32 = 0x0000000000000000000000000000000000000000000000000000000000000000 + node: bytes32 = 0x0000000000000000000000000000000000000000000000000000000000000000 size: uint256 = self.deposit_count - for h in range(DEPOSIT_CONTRACT_TREE_DEPTH): - if bitwise_and(size, 1) == 1: - root = sha256(concat(self.branch[h], root)) + for height in range(DEPOSIT_CONTRACT_TREE_DEPTH): + if bitwise_and(size, 1) == 1: # More gas efficient than `size % 2 == 1` + node = sha256(concat(self.branch[height], node)) else: - root = sha256(concat(root, self.zerohashes[h])) + node = sha256(concat(node, self.zero_hashes[height])) size /= 2 - return root + return node + @public @constant def get_deposit_count() -> bytes[8]: return self.to_little_endian_64(self.deposit_count) + @payable @public def deposit(pubkey: bytes[PUBKEY_LENGTH], withdrawal_credentials: bytes[WITHDRAWAL_CREDENTIALS_LENGTH], signature: bytes[SIGNATURE_LENGTH]): - # Prevent edge case in computing `self.branch` when `self.deposit_count == MAX_DEPOSIT_COUNT` - # NOTE: reaching this point with the constants as currently defined is impossible due to the - # uni-directional nature of transfers from eth1 to eth2 and the total ether supply (< 130M). + # Avoid overflowing the Merkle tree (and prevent edge case in computing `self.branch`) assert self.deposit_count < MAX_DEPOSIT_COUNT + # Validate deposit data + deposit_amount: uint256 = msg.value / as_wei_value(1, "gwei") + assert deposit_amount >= MIN_DEPOSIT_AMOUNT assert len(pubkey) == PUBKEY_LENGTH assert len(withdrawal_credentials) == WITHDRAWAL_CREDENTIALS_LENGTH assert len(signature) == SIGNATURE_LENGTH - deposit_amount: uint256 = msg.value / as_wei_value(1, "gwei") - assert deposit_amount >= MIN_DEPOSIT_AMOUNT + # Emit `Deposit` log amount: bytes[8] = self.to_little_endian_64(deposit_amount) + log.Deposit(pubkey, withdrawal_credentials, amount, signature, self.to_little_endian_64(self.deposit_count)) - index: uint256 = self.deposit_count - - # add deposit to merkle tree - i: int128 = 0 - size: uint256 = index + 1 - for _ in range(DEPOSIT_CONTRACT_TREE_DEPTH): - if bitwise_and(size, 1) == 1: - break - i += 1 - size /= 2 - - zero_bytes_32: bytes32 - pubkey_root: bytes32 = sha256(concat(pubkey, slice(zero_bytes_32, start=0, len=16))) + # Compute `DepositData` root + zero_bytes32: bytes32 = 0x0000000000000000000000000000000000000000000000000000000000000000 + pubkey_root: bytes32 = sha256(concat(pubkey, slice(zero_bytes32, start=0, len=64 - PUBKEY_LENGTH))) signature_root: bytes32 = sha256(concat( sha256(slice(signature, start=0, len=64)), - sha256(concat(slice(signature, start=64, len=32), zero_bytes_32)) + sha256(concat(slice(signature, start=64, len=SIGNATURE_LENGTH - 64), zero_bytes32)), )) - value: bytes32 = sha256(concat( + node: bytes32 = sha256(concat( sha256(concat(pubkey_root, withdrawal_credentials)), - sha256(concat( - amount, - slice(zero_bytes_32, start=0, len=24), - signature_root, - )) + sha256(concat(amount, slice(zero_bytes32, start=0, len=32 - AMOUNT_LENGTH), signature_root)), )) - for j in range(DEPOSIT_CONTRACT_TREE_DEPTH): - if j < i: - value = sha256(concat(self.branch[j], value)) - else: - break - self.branch[i] = value + # Add `DepositData` root to Merkle tree (update a single `branch` node) self.deposit_count += 1 - log.Deposit( - pubkey, - withdrawal_credentials, - amount, - signature, - self.to_little_endian_64(index), - ) + size: uint256 = self.deposit_count + for height in range(DEPOSIT_CONTRACT_TREE_DEPTH): + if bitwise_and(size, 1) == 1: # More gas efficient than `size % 2 == 1` + self.branch[height] = node + break + node = sha256(concat(self.branch[height], node)) + size /= 2 - if deposit_amount >= FULL_DEPOSIT_AMOUNT: - self.full_deposit_count += 1 - if self.full_deposit_count == CHAIN_START_FULL_DEPOSIT_THRESHOLD: - timestamp_day_boundary: uint256 = ( - as_unitless_number(block.timestamp) - - as_unitless_number(block.timestamp) % SECONDS_PER_DAY + - 2 * SECONDS_PER_DAY - ) - new_deposit_root: bytes32 = self.get_deposit_root() - log.Eth2Genesis(new_deposit_root, - self.to_little_endian_64(self.deposit_count), - self.to_little_endian_64(timestamp_day_boundary)) - self.chainStarted = True diff --git a/deposit_contract/tests/contracts/conftest.py b/deposit_contract/tests/contracts/conftest.py index 69ece247d..d4c7da9aa 100644 --- a/deposit_contract/tests/contracts/conftest.py +++ b/deposit_contract/tests/contracts/conftest.py @@ -26,7 +26,6 @@ from .utils import ( # Constants MIN_DEPOSIT_AMOUNT = 1000000000 # Gwei FULL_DEPOSIT_AMOUNT = 32000000000 # Gwei -CHAIN_START_FULL_DEPOSIT_THRESHOLD = 65536 # 2**16 DEPOSIT_CONTRACT_TREE_DEPTH = 32 TWO_TO_POWER_OF_TREE_DEPTH = 2**DEPOSIT_CONTRACT_TREE_DEPTH @@ -63,45 +62,6 @@ def registration_contract(w3, tester): return registration_deployed -@pytest.fixture(scope="session") -def chain_start_full_deposit_thresholds(): - return [randint(1, 5), randint(6, 10), randint(11, 15)] - - -@pytest.fixture(params=[0, 1, 2]) -def modified_registration_contract( - request, - w3, - tester, - chain_start_full_deposit_thresholds): - # Set CHAIN_START_FULL_DEPOSIT_THRESHOLD to different threshold t - registration_code = get_deposit_contract_code() - t = str(chain_start_full_deposit_thresholds[request.param]) - modified_registration_code = re.sub( - r'CHAIN_START_FULL_DEPOSIT_THRESHOLD: constant\(uint256\) = [0-9]+', - 'CHAIN_START_FULL_DEPOSIT_THRESHOLD: constant(uint256) = ' + t, - registration_code, - ) - assert modified_registration_code != registration_code - contract_bytecode = compiler.compile_code(modified_registration_code)['bytecode'] - contract_abi = compiler.mk_full_signature(modified_registration_code) - registration = w3.eth.contract( - abi=contract_abi, - bytecode=contract_bytecode) - tx_hash = registration.constructor().transact() - tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash) - registration_deployed = w3.eth.contract( - address=tx_receipt.contractAddress, - abi=contract_abi - ) - setattr( - registration_deployed, - 'chain_start_full_deposit_threshold', - chain_start_full_deposit_thresholds[request.param] - ) - return registration_deployed - - @pytest.fixture def assert_tx_failed(tester): def assert_tx_failed(function_to_test, exception=eth_tester.exceptions.TransactionFailed): diff --git a/deposit_contract/tests/contracts/test_deposit.py b/deposit_contract/tests/contracts/test_deposit.py index 8492d6347..783af3356 100644 --- a/deposit_contract/tests/contracts/test_deposit.py +++ b/deposit_contract/tests/contracts/test_deposit.py @@ -49,28 +49,6 @@ def deposit_input(): ) -@pytest.mark.parametrize( - 'value,success', - [ - (0, True), - (10, True), - (55555, True), - (2**64 - 1, True), - (2**64, False), - ] -) -def test_to_little_endian_64(registration_contract, value, success, assert_tx_failed): - call = registration_contract.functions.to_little_endian_64(value) - - if success: - little_endian_64 = call.call() - assert little_endian_64 == (value).to_bytes(8, 'little') - else: - assert_tx_failed( - lambda: call.call() - ) - - @pytest.mark.parametrize( 'success,deposit_amount', [ @@ -151,8 +129,7 @@ def test_deposit_log(registration_contract, a0, w3, deposit_input): assert log['withdrawal_credentials'] == deposit_input[1] assert log['amount'] == deposit_amount_list[i].to_bytes(8, 'little') assert log['signature'] == deposit_input[2] - assert log['merkle_tree_index'] == i.to_bytes(8, 'little') - + assert log['index'] == i.to_bytes(8, 'little') def test_deposit_tree(registration_contract, w3, assert_tx_failed, deposit_input): log_filter = registration_contract.events.Deposit.createFilter( @@ -172,7 +149,7 @@ def test_deposit_tree(registration_contract, w3, assert_tx_failed, deposit_input assert len(logs) == 1 log = logs[0]['args'] - assert log["merkle_tree_index"] == i.to_bytes(8, 'little') + assert log["index"] == i.to_bytes(8, 'little') deposit_data = DepositData( pubkey=deposit_input[0], @@ -184,53 +161,3 @@ def test_deposit_tree(registration_contract, w3, assert_tx_failed, deposit_input leaf_nodes.append(hash_tree_root_result) root = compute_merkle_root(leaf_nodes) assert root == registration_contract.functions.get_deposit_root().call() - - -def test_chain_start(modified_registration_contract, w3, assert_tx_failed, deposit_input): - t = getattr(modified_registration_contract, 'chain_start_full_deposit_threshold') - # CHAIN_START_FULL_DEPOSIT_THRESHOLD is set to t - min_deposit_amount = MIN_DEPOSIT_AMOUNT * eth_utils.denoms.gwei # in wei - full_deposit_amount = FULL_DEPOSIT_AMOUNT * eth_utils.denoms.gwei - log_filter = modified_registration_contract.events.Eth2Genesis.createFilter( - fromBlock='latest', - ) - - index_not_full_deposit = randint(0, t - 1) - for i in range(t): - if i == index_not_full_deposit: - # Deposit with value below FULL_DEPOSIT_AMOUNT - modified_registration_contract.functions.deposit( - *deposit_input, - ).transact({"value": min_deposit_amount}) - logs = log_filter.get_new_entries() - # Eth2Genesis event should not be triggered - assert len(logs) == 0 - else: - # Deposit with value FULL_DEPOSIT_AMOUNT - modified_registration_contract.functions.deposit( - *deposit_input, - ).transact({"value": full_deposit_amount}) - logs = log_filter.get_new_entries() - # Eth2Genesis event should not be triggered - assert len(logs) == 0 - - # Make 1 more deposit with value FULL_DEPOSIT_AMOUNT to trigger Eth2Genesis event - modified_registration_contract.functions.deposit( - *deposit_input, - ).transact({"value": full_deposit_amount}) - logs = log_filter.get_new_entries() - assert len(logs) == 1 - timestamp = int(w3.eth.getBlock(w3.eth.blockNumber)['timestamp']) - timestamp_day_boundary = timestamp + (86400 - timestamp % 86400) + 86400 - log = logs[0]['args'] - assert log['deposit_root'] == modified_registration_contract.functions.get_deposit_root().call() - assert int.from_bytes(log['time'], byteorder='little') == timestamp_day_boundary - assert modified_registration_contract.functions.chainStarted().call() is True - - # Make 1 deposit with value FULL_DEPOSIT_AMOUNT and - # check that Eth2Genesis event is not triggered - modified_registration_contract.functions.deposit( - *deposit_input, - ).transact({"value": full_deposit_amount}) - logs = log_filter.get_new_entries() - assert len(logs) == 0 diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 013d002c9..b4049bb30 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -95,7 +95,7 @@ - [`initiate_validator_exit`](#initiate_validator_exit) - [`slash_validator`](#slash_validator) - [Genesis](#genesis) - - [`Eth2Genesis`](#eth2genesis) + - [Genesis trigger](#genesis-trigger) - [Genesis state](#genesis-state) - [Genesis block](#genesis-block) - [Beacon chain state transition function](#beacon-chain-state-transition-function) @@ -941,6 +941,7 @@ def convert_to_indexed(state: BeaconState, attestation: Attestation) -> IndexedA """ attesting_indices = get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield) custody_bit_1_indices = get_attesting_indices(state, attestation.data, attestation.custody_bitfield) + assert set(custody_bit_1_indices).issubset(attesting_indices) custody_bit_0_indices = [index for index in attesting_indices if index not in custody_bit_1_indices] return IndexedAttestation( @@ -1106,20 +1107,45 @@ def slash_validator(state: BeaconState, ## Genesis -### `Eth2Genesis` +### Genesis trigger -When enough deposits of size `MAX_EFFECTIVE_BALANCE` have been made to the deposit contract an `Eth2Genesis` log is emitted triggering the genesis of the beacon chain. Let: +Before genesis has been triggered and whenever the deposit contract emits a `Deposit` log, call the function `is_genesis_trigger(deposits: List[Deposit], timestamp: uint64) -> bool` where: -* `eth2genesis` be the object corresponding to `Eth2Genesis` -* `genesis_eth1_data` be object of type `Eth1Data` where - * `genesis_eth1_data.deposit_root = eth2genesis.deposit_root` - * `genesis_eth1_data.deposit_count = eth2genesis.deposit_count` - * `genesis_eth1_data.block_hash` is the hash of the Ethereum 1.0 block that emitted the `Eth2Genesis` log -* `genesis_deposits` be the object of type `List[Deposit]` with deposits ordered chronologically up to and including the deposit that triggered the `Eth2Genesis` log +* `deposits` is the list of all deposits, ordered chronologically, up to and including the deposit triggering the latest `Deposit` log +* `timestamp` is the Unix timestamp in the Ethereum 1.0 block that emitted the latest `Deposit` log + +When `is_genesis_trigger(deposits, timestamp) is True` for the first time let: + +* `genesis_deposits = deposits` +* `genesis_time = timestamp - timestamp % SECONDS_PER_DAY + 2 * SECONDS_PER_DAY` where `SECONDS_PER_DAY = 86400` +* `genesis_eth1_data` be the object of type `Eth1Data` where: + * `genesis_eth1_data.block_hash` is the Ethereum 1.0 block hash that emitted the log for the last deposit in `deposits` + * `genesis_eth1_data.deposit_root` is the deposit root for the last deposit in `deposits` + * `genesis_eth1_data.deposit_count = len(genesis_deposits)` + +*Note*: The function `is_genesis_trigger` has yet to be agreed by the community, and can be updated as necessary. We define the following testing placeholder: + +```python +def is_genesis_trigger(deposits: List[Deposit], timestamp: uint64) -> bool: + # Process deposits + state = BeaconState() + for deposit in deposits: + process_deposit(state, deposit) + + # Count active validators at genesis + active_validator_count = 0 + for validator in state.validator_registry: + if validator.effective_balance == MAX_EFFECTIVE_BALANCE: + active_validator_count += 1 + + # Check effective balance to trigger genesis + GENESIS_ACTIVE_VALIDATOR_COUNT = 2**16 + return active_validator_count == GENESIS_ACTIVE_VALIDATOR_COUNT +``` ### Genesis state -Let `genesis_state = get_genesis_beacon_state(genesis_deposits, eth2genesis.genesis_time, genesis_eth1_data)`. +Let `genesis_state = get_genesis_beacon_state(genesis_deposits, genesis_time, genesis_eth1_data)`. ```python def get_genesis_beacon_state(deposits: List[Deposit], genesis_time: int, genesis_eth1_data: Eth1Data) -> BeaconState: @@ -1196,7 +1222,7 @@ def process_slot(state: BeaconState) -> None: ### Epoch processing -Note: the `# @LabelHere` lines below are placeholders to show that code will be inserted here in a future phase. +*Note*: the `# @LabelHere` lines below are placeholders to show that code will be inserted here in a future phase. ```python def process_epoch(state: BeaconState) -> None: @@ -1647,6 +1673,10 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: Process ``Attestation`` operation. """ data = attestation.data + + assert data.crosslink.shard < SHARD_COUNT + assert data.target_epoch in (get_previous_epoch(state), get_current_epoch(state)) + attestation_slot = get_attestation_data_slot(state, data) assert attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= attestation_slot + SLOTS_PER_EPOCH @@ -1657,7 +1687,6 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: proposer_index=get_beacon_proposer_index(state), ) - assert data.target_epoch in (get_previous_epoch(state), get_current_epoch(state)) if data.target_epoch == get_current_epoch(state): ffg_data = (state.current_justified_epoch, state.current_justified_root, get_current_epoch(state)) parent_crosslink = state.current_crosslinks[data.crosslink.shard] diff --git a/specs/core/0_deposit-contract.md b/specs/core/0_deposit-contract.md index d40553f43..338ece487 100644 --- a/specs/core/0_deposit-contract.md +++ b/specs/core/0_deposit-contract.md @@ -9,15 +9,12 @@ - [Table of contents](#table-of-contents) - [Introduction](#introduction) - [Constants](#constants) - - [Gwei values](#gwei-values) - [Contract](#contract) - [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) - - [Arguments](#arguments) + - [`deposit` function](#deposit-function) + - [Deposit amount](#deposit-amount) - [Withdrawal credentials](#withdrawal-credentials) - - [Amount](#amount) - - [Event logs](#event-logs) - - [`Deposit` logs](#deposit-logs) - - [`Eth2Genesis` log](#eth2genesis-log) + - [`Deposit` log](#deposit-log) - [Vyper code](#vyper-code) @@ -28,66 +25,40 @@ This document represents the specification for the beacon chain deposit contract ## Constants -### Gwei values - -| Name | Value | Unit | -| - | - | - | -| `FULL_DEPOSIT_AMOUNT` | `32 * 10**9` | Gwei | - ### Contract | Name | Value | | - | - | | `DEPOSIT_CONTRACT_ADDRESS` | **TBD** | | `DEPOSIT_CONTRACT_TREE_DEPTH` | `2**5` (= 32) | -| `CHAIN_START_FULL_DEPOSIT_THRESHOLD` | `2**16` (= 65,536) | ## Ethereum 1.0 deposit contract The initial deployment phases of Ethereum 2.0 are implemented without consensus changes to Ethereum 1.0. A deposit contract at address `DEPOSIT_CONTRACT_ADDRESS` is added to Ethereum 1.0 for deposits of ETH to the beacon chain. Validator balances will be withdrawable to the shards in Phase 2 (i.e. when the EVM 2.0 is deployed and the shards have state). -### Arguments +### `deposit` function -The deposit contract has a `deposit` function which takes the amount in Ethereum 1.0 transaction, and arguments `pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96]` corresponding to `DepositData`. +The deposit contract has a public `deposit` function to make deposits. It takes as arguments `pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96]` corresponding to a `DepositData` object. + +#### Deposit amount + +The amount of ETH (rounded down to the closest Gwei) sent to the deposit contract is the deposit amount, which must be of size at least `MIN_DEPOSIT_AMOUNT` Gwei. Note that ETH consumed by the deposit contract is no longer usable on Ethereum 1.0. #### Withdrawal credentials -One of the `DepositData` fields is `withdrawal_credentials`. It is a commitment to credentials for withdrawals to shards. The first byte of `withdrawal_credentials` is a version number. As of now, the only expected format is as follows: +One of the `DepositData` fields is `withdrawal_credentials`. It is a commitment to credentials for withdrawing validator balance (e.g. to another validator, or to shards). The first byte of `withdrawal_credentials` is a version number. As of now, the only expected format is as follows: * `withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX_BYTE` * `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]` where `withdrawal_pubkey` is a BLS pubkey The private key corresponding to `withdrawal_pubkey` will be required to initiate a withdrawal. It can be stored separately until a withdrawal is required, e.g. in cold storage. -#### Amount +#### `Deposit` log -* A valid deposit amount should be at least `MIN_DEPOSIT_AMOUNT` in Gwei. -* A deposit with an amount greater than or equal to `FULL_DEPOSIT_AMOUNT` in Gwei is considered as a full deposit. - -## Event logs - -### `Deposit` logs - -Every Ethereum 1.0 deposit, of size at least `MIN_DEPOSIT_AMOUNT`, emits a `Deposit` log for consumption by the beacon chain. The deposit contract does little validation, pushing most of the validator onboarding logic to the beacon chain. In particular, the proof of possession (a BLS12-381 signature) is not verified by the deposit contract. - -### `Eth2Genesis` log - -When `CHAIN_START_FULL_DEPOSIT_THRESHOLD` of full deposits have been made, the deposit contract emits the `Eth2Genesis` log. The beacon chain state may then be initialized by calling the `get_genesis_beacon_state` function (defined [here](./0_beacon-chain.md#genesis-state)) where: - -* `genesis_time` equals `time` in the `Eth2Genesis` log -* `eth1_data.deposit_root` equals `deposit_root` in the `Eth2Genesis` log -* `eth1_data.deposit_count` equals `deposit_count` in the `Eth2Genesis` log -* `eth1_data.block_hash` equals the hash of the block that included the log -* `genesis_validator_deposits` is a list of `Deposit` objects built according to the `Deposit` logs up to the deposit that triggered the `Eth2Genesis` log, processed in the order in which they were emitted (oldest to newest) +Every Ethereum 1.0 deposit emits a `Deposit` log for consumption by the beacon chain. The deposit contract does little validation, pushing most of the validator onboarding logic to the beacon chain. In particular, the proof of possession (a BLS12-381 signature) is not verified by the deposit contract. ## Vyper code -The source for the Vyper contract lives [here](./../../deposit_contract/contracts/validator_registration.v.py). +The deposit contract source code, written in Vyper, is available [here](https://github.com/ethereum/eth2.0-specs/blob/dev/deposit_contract/contracts/validator_registration.v.py). -*Note*: To save ~10x on gas, this contract uses a somewhat unintuitive progressive Merkle root calculation algo that requires only O(log(n)) storage. See https://github.com/ethereum/research/blob/master/beacon_chain_impl/progressive_merkle_tree.py for an implementation of the same algo in Python tested for correctness. - -For convenience, we provide the interface to the contract here: - -* `__init__()`: initializes the contract -* `get_deposit_root() -> bytes32`: returns the current root of the deposit tree -* `deposit(pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96])`: adds a deposit instance to the deposit tree, incorporating the input arguments and the value transferred in the given call. *Note*: The amount of value transferred *must* be at least `MIN_DEPOSIT_AMOUNT`. Each of these constants are specified in units of Gwei. +*Note*: To save on gas the deposit contract uses a progressive Merkle root calculation algorithm that requires only O(log(n)) storage. See [here](https://github.com/ethereum/research/blob/master/beacon_chain_impl/progressive_merkle_tree.py) for a Python implementation, and [here](https://github.com/runtimeverification/verified-smart-contracts/blob/master/deposit/formal-incremental-merkle-tree-algorithm.pdf) for a formal correctness proof. diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index d062e1d3b..ecbc5af27 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -147,7 +147,7 @@ def get_committee_assignment( committees_per_slot = get_epoch_committee_count(state, epoch) // SLOTS_PER_EPOCH epoch_start_slot = get_epoch_start_slot(epoch) - for slot in range(epoch_start_slot, epoch_start_slot + SLOTS_PER_EPOCH) + for slot in range(epoch_start_slot, epoch_start_slot + SLOTS_PER_EPOCH): offset = committees_per_slot * (slot % SLOTS_PER_EPOCH) slot_start_shard = (get_epoch_start_shard(state, epoch) + offset) % SHARD_COUNT for i in range(committees_per_slot): @@ -297,11 +297,11 @@ Set `attestation_data.beacon_block_root = signing_root(head_block)`. * Set `attestation_data.source_epoch = head_state.current_justified_epoch`. * Set `attestation_data.source_root = head_state.current_justified_root`. * Set `attestation_data.target_epoch = get_current_epoch(head_state)` -* Set `attestation_data.target_root = signing_root(epoch_boundary_block)` where `epoch_boundary_block` is the block at the most recent epoch boundary. +* Set `attestation_data.target_root = epoch_boundary_block_root` where `epoch_boundary_block_root` is the root of block at the most recent epoch boundary. -*Note*: `epoch_boundary_block` can be looked up in the state using: +*Note*: `epoch_boundary_block_root` can be looked up in the state using: * Let `epoch_start_slot = get_epoch_start_slot(get_current_epoch(head_state))`. -* Let `epoch_boundary_block = head if epoch_start_slot == head_state.slot else get_block_root(state, epoch_start_slot)`. +* Let `epoch_boundary_block_root = signing_root(head_block) if epoch_start_slot == head_state.slot else get_block_root(state, epoch_start_slot)`. ##### Crosslink vote diff --git a/test_generators/epoch_processing/main.py b/test_generators/epoch_processing/main.py index 2ce895fc5..846f463a1 100644 --- a/test_generators/epoch_processing/main.py +++ b/test_generators/epoch_processing/main.py @@ -2,7 +2,7 @@ from typing import Callable, Iterable from eth2spec.phase0 import spec as spec_phase0 from eth2spec.phase1 import spec as spec_phase1 -from eth2spec.test.epoch_processing import ( +from eth2spec.test.phase_0.epoch_processing import ( test_process_crosslinks, test_process_registry_updates ) @@ -33,8 +33,10 @@ def create_suite(transition_name: str, config_name: str, get_cases: Callable[[], if __name__ == "__main__": gen_runner.run_generator("epoch_processing", [ - create_suite('crosslinks', 'minimal', lambda: generate_from_tests(test_process_crosslinks)), - create_suite('crosslinks', 'mainnet', lambda: generate_from_tests(test_process_crosslinks)), - create_suite('registry_updates', 'minimal', lambda: generate_from_tests(test_process_registry_updates)), - create_suite('registry_updates', 'mainnet', lambda: generate_from_tests(test_process_registry_updates)), + create_suite('crosslinks', 'minimal', lambda: generate_from_tests(test_process_crosslinks, 'phase0')), + create_suite('crosslinks', 'mainnet', lambda: generate_from_tests(test_process_crosslinks, 'phase0')), + create_suite('registry_updates', 'minimal', + lambda: generate_from_tests(test_process_registry_updates, 'phase0')), + create_suite('registry_updates', 'mainnet', + lambda: generate_from_tests(test_process_registry_updates, 'phase0')), ]) diff --git a/test_generators/operations/main.py b/test_generators/operations/main.py index 82e05b307..38fa42f68 100644 --- a/test_generators/operations/main.py +++ b/test_generators/operations/main.py @@ -1,13 +1,13 @@ from typing import Callable, Iterable -from eth2spec.test.block_processing import ( +from eth2spec.test.phase_0.block_processing import ( test_process_attestation, test_process_attester_slashing, test_process_block_header, test_process_deposit, test_process_proposer_slashing, test_process_transfer, - test_process_voluntary_exit + test_process_voluntary_exit, ) from gen_base import gen_runner, gen_suite, gen_typing @@ -38,18 +38,18 @@ def create_suite(operation_name: str, config_name: str, get_cases: Callable[[], if __name__ == "__main__": gen_runner.run_generator("operations", [ - create_suite('attestation', 'minimal', lambda: generate_from_tests(test_process_attestation)), - create_suite('attestation', 'mainnet', lambda: generate_from_tests(test_process_attestation)), - create_suite('attester_slashing', 'minimal', lambda: generate_from_tests(test_process_attester_slashing)), - create_suite('attester_slashing', 'mainnet', lambda: generate_from_tests(test_process_attester_slashing)), - create_suite('block_header', 'minimal', lambda: generate_from_tests(test_process_block_header)), - create_suite('block_header', 'mainnet', lambda: generate_from_tests(test_process_block_header)), - create_suite('deposit', 'minimal', lambda: generate_from_tests(test_process_deposit)), - create_suite('deposit', 'mainnet', lambda: generate_from_tests(test_process_deposit)), - create_suite('proposer_slashing', 'minimal', lambda: generate_from_tests(test_process_proposer_slashing)), - create_suite('proposer_slashing', 'mainnet', lambda: generate_from_tests(test_process_proposer_slashing)), - create_suite('transfer', 'minimal', lambda: generate_from_tests(test_process_transfer)), - create_suite('transfer', 'mainnet', lambda: generate_from_tests(test_process_transfer)), - create_suite('voluntary_exit', 'minimal', lambda: generate_from_tests(test_process_voluntary_exit)), - create_suite('voluntary_exit', 'mainnet', lambda: generate_from_tests(test_process_voluntary_exit)), + create_suite('attestation', 'minimal', lambda: generate_from_tests(test_process_attestation, 'phase0')), + create_suite('attestation', 'mainnet', lambda: generate_from_tests(test_process_attestation, 'phase0')), + create_suite('attester_slashing', 'minimal', lambda: generate_from_tests(test_process_attester_slashing, 'phase0')), + create_suite('attester_slashing', 'mainnet', lambda: generate_from_tests(test_process_attester_slashing, 'phase0')), + create_suite('block_header', 'minimal', lambda: generate_from_tests(test_process_block_header, 'phase0')), + create_suite('block_header', 'mainnet', lambda: generate_from_tests(test_process_block_header, 'phase0')), + create_suite('deposit', 'minimal', lambda: generate_from_tests(test_process_deposit, 'phase0')), + create_suite('deposit', 'mainnet', lambda: generate_from_tests(test_process_deposit, 'phase0')), + create_suite('proposer_slashing', 'minimal', lambda: generate_from_tests(test_process_proposer_slashing, 'phase0')), + create_suite('proposer_slashing', 'mainnet', lambda: generate_from_tests(test_process_proposer_slashing, 'phase0')), + create_suite('transfer', 'minimal', lambda: generate_from_tests(test_process_transfer, 'phase0')), + create_suite('transfer', 'mainnet', lambda: generate_from_tests(test_process_transfer, 'phase0')), + create_suite('voluntary_exit', 'minimal', lambda: generate_from_tests(test_process_voluntary_exit, 'phase0')), + create_suite('voluntary_exit', 'mainnet', lambda: generate_from_tests(test_process_voluntary_exit, 'phase0')), ]) diff --git a/test_generators/sanity/main.py b/test_generators/sanity/main.py index a9c0fe160..fbef4da96 100644 --- a/test_generators/sanity/main.py +++ b/test_generators/sanity/main.py @@ -16,7 +16,7 @@ def create_suite(handler_name: str, config_name: str, get_cases: Callable[[], It spec_phase0.apply_constants_preset(presets) spec_phase1.apply_constants_preset(presets) - return ("%sanity_s_%s" % (handler_name, config_name), handler_name, gen_suite.render_suite( + return ("sanity_%s_%s" % (handler_name, config_name), handler_name, gen_suite.render_suite( title="sanity testing", summary="Sanity test suite, %s type, generated from pytests" % handler_name, forks_timeline="testing", @@ -30,8 +30,8 @@ def create_suite(handler_name: str, config_name: str, get_cases: Callable[[], It if __name__ == "__main__": gen_runner.run_generator("sanity", [ - create_suite('blocks', 'minimal', lambda: generate_from_tests(test_blocks)), - create_suite('blocks', 'mainnet', lambda: generate_from_tests(test_blocks)), - create_suite('slots', 'minimal', lambda: generate_from_tests(test_slots)), - create_suite('slots', 'mainnet', lambda: generate_from_tests(test_slots)), + create_suite('blocks', 'minimal', lambda: generate_from_tests(test_blocks, 'phase0')), + create_suite('blocks', 'mainnet', lambda: generate_from_tests(test_blocks, 'phase0')), + create_suite('slots', 'minimal', lambda: generate_from_tests(test_slots, 'phase0')), + create_suite('slots', 'mainnet', lambda: generate_from_tests(test_slots, 'phase0')), ]) diff --git a/test_generators/shuffling/main.py b/test_generators/shuffling/main.py index 862c4d910..291aa2c47 100644 --- a/test_generators/shuffling/main.py +++ b/test_generators/shuffling/main.py @@ -1,5 +1,4 @@ -from eth2spec.phase0 import spec as spec_phase0 -from eth2spec.phase1 import spec as spec_phase1 +from eth2spec.phase0 import spec as spec from eth_utils import ( to_dict, to_tuple ) @@ -8,7 +7,7 @@ from preset_loader import loader @to_dict -def shuffling_case(seed: spec.Bytes32, count: int): +def shuffling_case(seed, count): yield 'seed', '0x' + seed.hex() yield 'count', count yield 'shuffled', [spec.get_shuffled_index(i, count, seed) for i in range(count)] @@ -23,8 +22,7 @@ def shuffling_test_cases(): def mini_shuffling_suite(configs_path: str) -> gen_typing.TestSuiteOutput: presets = loader.load_presets(configs_path, 'minimal') - spec_phase0.apply_constants_preset(presets) - spec_phase1.apply_constants_preset(presets) + spec.apply_constants_preset(presets) return ("shuffling_minimal", "core", gen_suite.render_suite( title="Swap-or-Not Shuffling tests with minimal config", @@ -39,8 +37,7 @@ def mini_shuffling_suite(configs_path: str) -> gen_typing.TestSuiteOutput: def full_shuffling_suite(configs_path: str) -> gen_typing.TestSuiteOutput: presets = loader.load_presets(configs_path, 'mainnet') - spec_phase0.apply_constants_preset(presets) - spec_phase1.apply_constants_preset(presets) + spec.apply_constants_preset(presets) return ("shuffling_full", "core", gen_suite.render_suite( title="Swap-or-Not Shuffling tests with mainnet config", diff --git a/test_generators/ssz_static/main.py b/test_generators/ssz_static/main.py index 7de5237d1..9d9af8c5e 100644 --- a/test_generators/ssz_static/main.py +++ b/test_generators/ssz_static/main.py @@ -1,7 +1,10 @@ from random import Random +from inspect import getmembers, isclass + from eth2spec.debug import random_value, encode from eth2spec.phase0 import spec +from eth2spec.utils.ssz.ssz_typing import Container from eth2spec.utils.ssz.ssz_impl import ( hash_tree_root, signing_root, @@ -27,17 +30,23 @@ def create_test_case_contents(value, typ): @to_dict -def create_test_case(rng: Random, name: str, mode: random_value.RandomizationMode, chaos: bool): - typ = spec.get_ssz_type_by_name(name) +def create_test_case(rng: Random, name: str, typ, mode: random_value.RandomizationMode, chaos: bool): value = random_value.get_random_ssz_object(rng, typ, MAX_BYTES_LENGTH, MAX_LIST_LENGTH, mode, chaos) yield name, create_test_case_contents(value, typ) +def get_spec_ssz_types(): + return [ + (name, value) for (name, value) in getmembers(spec, isclass) + if issubclass(value, Container) and value != Container # only the subclasses, not the imported base class + ] + + @to_tuple def ssz_static_cases(rng: Random, mode: random_value.RandomizationMode, chaos: bool, count: int): - for type_name in spec.ssz_types: + for (name, ssz_type) in get_spec_ssz_types(): for i in range(count): - yield create_test_case(rng, type_name, mode, chaos) + yield create_test_case(rng, name, ssz_type, mode, chaos) def get_ssz_suite(seed: int, config_name: str, mode: random_value.RandomizationMode, chaos: bool, cases_if_random: int): @@ -81,8 +90,6 @@ if __name__ == "__main__": settings.append((seed, "mainnet", random_value.RandomizationMode.mode_random, False, 5)) seed += 1 - print("Settings: %d, SSZ-types: %d" % (len(settings), len(spec.ssz_types))) - gen_runner.run_generator("ssz_static", [ get_ssz_suite(seed, config_name, mode, chaos, cases_if_random) for (seed, config_name, mode, chaos, cases_if_random) in settings diff --git a/test_libs/gen_helpers/gen_from_tests/gen.py b/test_libs/gen_helpers/gen_from_tests/gen.py index e7d801131..3810c385e 100644 --- a/test_libs/gen_helpers/gen_from_tests/gen.py +++ b/test_libs/gen_helpers/gen_from_tests/gen.py @@ -1,9 +1,10 @@ from inspect import getmembers, isfunction -def generate_from_tests(src, bls_active=True): +def generate_from_tests(src, phase, bls_active=True): """ Generate a list of test cases by running tests from the given src in generator-mode. - :param src: to retrieve tests from (discovered using inspect.getmembers) + :param src: to retrieve tests from (discovered using inspect.getmembers). + :param phase: to run tests against particular phase. :param bls_active: optional, to override BLS switch preference. Defaults to True. :return: the list of test cases. """ @@ -16,7 +17,7 @@ def generate_from_tests(src, bls_active=True): for name in fn_names: tfn = getattr(src, name) try: - test_case = tfn(generator_mode=True, bls_active=bls_active) + test_case = tfn(generator_mode=True, phase=phase, bls_active=bls_active) # If no test case data is returned, the test is ignored. if test_case is not None: out.append(test_case) diff --git a/test_libs/pyspec/eth2spec/test/context.py b/test_libs/pyspec/eth2spec/test/context.py index cbc594cd8..97266acf2 100644 --- a/test_libs/pyspec/eth2spec/test/context.py +++ b/test_libs/pyspec/eth2spec/test/context.py @@ -116,12 +116,22 @@ def with_phases(phases): def decorator(fn): def run_with_spec_version(spec, *args, **kw): kw['spec'] = spec - fn(*args, **kw) + return fn(*args, **kw) def wrapper(*args, **kw): - if 'phase0' in phases: - run_with_spec_version(spec_phase0, *args, **kw) - if 'phase1' in phases: - run_with_spec_version(spec_phase1, *args, **kw) + run_phases = phases + + # limit phases if one explicitly specified + if 'phase' in kw: + phase = kw.pop('phase') + if phase not in phases: + return + run_phases = [phase] + + if 'phase0' in run_phases: + ret = run_with_spec_version(spec_phase0, *args, **kw) + if 'phase1' in run_phases: + ret = run_with_spec_version(spec_phase1, *args, **kw) + return ret return wrapper return decorator diff --git a/test_libs/pyspec/eth2spec/test/helpers/deposits.py b/test_libs/pyspec/eth2spec/test/helpers/deposits.py index e3bd839aa..20ff7440f 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/deposits.py +++ b/test_libs/pyspec/eth2spec/test/helpers/deposits.py @@ -67,7 +67,7 @@ def prepare_state_and_deposit(spec, state, validator_index, amount, withdrawal_c # insecurely use pubkey as withdrawal key if no credentials provided if withdrawal_credentials is None: - withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(pubkey)[1:] + withdrawal_credentials = spec.int_to_bytes(spec.BLS_WITHDRAWAL_PREFIX, length=1) + spec.hash(pubkey)[1:] deposit, root, deposit_data_leaves = build_deposit( spec, @@ -77,7 +77,7 @@ def prepare_state_and_deposit(spec, state, validator_index, amount, withdrawal_c privkey, amount, withdrawal_credentials, - signed + signed, ) state.eth1_data.deposit_root = root diff --git a/test_libs/pyspec/eth2spec/test/helpers/genesis.py b/test_libs/pyspec/eth2spec/test/helpers/genesis.py index 241706957..87b0446af 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/genesis.py +++ b/test_libs/pyspec/eth2spec/test/helpers/genesis.py @@ -5,7 +5,7 @@ from eth2spec.utils.ssz.ssz_impl import hash_tree_root def build_mock_validator(spec, i: int, balance: int): pubkey = pubkeys[i] # insecurely use pubkey as withdrawal key as well - withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(pubkey)[1:] + withdrawal_credentials = spec.int_to_bytes(spec.BLS_WITHDRAWAL_PREFIX, length=1) + spec.hash(pubkey)[1:] return spec.Validator( pubkey=pubkeys[i], withdrawal_credentials=withdrawal_credentials, diff --git a/test_libs/pyspec/eth2spec/test/helpers/transfers.py b/test_libs/pyspec/eth2spec/test/helpers/transfers.py index f7397ca38..acc6a35c5 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/transfers.py +++ b/test_libs/pyspec/eth2spec/test/helpers/transfers.py @@ -32,7 +32,7 @@ def get_valid_transfer(spec, state, slot=None, sender_index=None, amount=None, f # ensure withdrawal_credentials reproducible state.validators[transfer.sender].withdrawal_credentials = ( - spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(transfer.pubkey)[1:] + spec.int_to_bytes(spec.BLS_WITHDRAWAL_PREFIX, length=1) + spec.hash(transfer.pubkey)[1:] ) return transfer diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py index 7efb57871..63b94c638 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py @@ -101,7 +101,7 @@ def test_invalid_sig_top_up(spec, state): def test_invalid_withdrawal_credentials_top_up(spec, state): validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 - withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(b"junk")[1:] + withdrawal_credentials = spec.int_to_bytes(spec.BLS_WITHDRAWAL_PREFIX, length=1) + spec.hash(b"junk")[1:] deposit = prepare_state_and_deposit( spec, state, diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py index 967846cb7..afc58d36d 100644 --- a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py +++ b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py @@ -5,7 +5,7 @@ from eth2spec.utils.ssz.ssz_impl import signing_root from eth2spec.utils.bls import bls_sign from eth2spec.test.helpers.state import get_balance -from eth2spec.test.helpers.transfers import get_valid_transfer +# from eth2spec.test.helpers.transfers import get_valid_transfer from eth2spec.test.helpers.block import build_empty_block_for_next_slot, sign_block from eth2spec.test.helpers.keys import privkeys, pubkeys from eth2spec.test.helpers.attester_slashings import get_valid_attester_slashing @@ -303,38 +303,38 @@ def test_voluntary_exit(spec, state): assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_all_phases -@spec_state_test -def test_transfer(spec, state): +# @with_all_phases +# @spec_state_test +# def test_transfer(spec, state): # overwrite default 0 to test - spec.MAX_TRANSFERS = 1 + # spec.MAX_TRANSFERS = 1 - sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] - amount = get_balance(state, sender_index) + # sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] + # amount = get_balance(state, sender_index) - transfer = get_valid_transfer(spec, state, state.slot + 1, sender_index, amount, signed=True) - recipient_index = transfer.recipient - pre_transfer_recipient_balance = get_balance(state, recipient_index) + # transfer = get_valid_transfer(spec, state, state.slot + 1, sender_index, amount, signed=True) + # recipient_index = transfer.recipient + # pre_transfer_recipient_balance = get_balance(state, recipient_index) # un-activate so validator can transfer - state.validators[sender_index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH + # state.validators[sender_index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH - yield 'pre', state + # yield 'pre', state # Add to state via block transition - block = build_empty_block_for_next_slot(spec, state) - block.body.transfers.append(transfer) - sign_block(spec, state, block) + # block = build_empty_block_for_next_slot(spec, state) + # block.body.transfers.append(transfer) + # sign_block(spec, state, block) - yield 'blocks', [block], List[spec.BeaconBlock] + # yield 'blocks', [block], List[spec.BeaconBlock] - spec.state_transition(state, block) - yield 'post', state + # spec.state_transition(state, block) + # yield 'post', state - sender_balance = get_balance(state, sender_index) - recipient_balance = get_balance(state, recipient_index) - assert sender_balance == 0 - assert recipient_balance == pre_transfer_recipient_balance + amount + # sender_balance = get_balance(state, sender_index) + # recipient_balance = get_balance(state, recipient_index) + # assert sender_balance == 0 + # assert recipient_balance == pre_transfer_recipient_balance + amount @with_all_phases diff --git a/test_libs/pyspec/eth2spec/test/utils.py b/test_libs/pyspec/eth2spec/test/utils.py index b61801c3d..817c952b7 100644 --- a/test_libs/pyspec/eth2spec/test/utils.py +++ b/test_libs/pyspec/eth2spec/test/utils.py @@ -1,5 +1,6 @@ from typing import Dict, Any, Callable, Iterable from eth2spec.debug.encode import encode +from eth2spec.utils.ssz.ssz_typing import Container def spectest(description: str = None): @@ -30,9 +31,13 @@ def spectest(description: str = None): else: # Otherwise, try to infer the type, but keep it as-is if it's not a SSZ container. (key, value) = data - if hasattr(value.__class__, 'fields'): + if isinstance(value, Container): out[key] = encode(value, value.__class__) else: + # not a ssz value. + # It could be vector or bytes still, but it is a rare case, + # and lists can't be inferred fully (generics lose element type). + # In such cases, explicitly state the type of the yielded value as a third yielded object. out[key] = value if has_contents: return out diff --git a/test_libs/pyspec/eth2spec/utils/hash_function.py b/test_libs/pyspec/eth2spec/utils/hash_function.py index f965827d0..2c9b5a579 100644 --- a/test_libs/pyspec/eth2spec/utils/hash_function.py +++ b/test_libs/pyspec/eth2spec/utils/hash_function.py @@ -1,5 +1,28 @@ from hashlib import sha256 +ZERO_BYTES32 = b'\x00' * 32 + + +def _hash(x): + return sha256(x).digest() + + +# Minimal collection of (key, value) pairs, for fast hash-retrieval, to save on repetitive computation cost. +# Key = the hash input +# Value = the hash output +hash_cache = [] + + +def add_zero_hashes_to_cache(): + zerohashes = [(None, ZERO_BYTES32)] + for layer in range(1, 32): + k = zerohashes[layer - 1][1] + zerohashes[layer - 1][1] + zerohashes.append((k, _hash(k))) + hash_cache.extend(zerohashes[1:]) + def hash(x): - return sha256(x).digest() + for (k, h) in hash_cache: + if x == k: + return h + return _hash(x) diff --git a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py index 368041f90..55ced4ee2 100644 --- a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py +++ b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py @@ -513,13 +513,11 @@ def read_vector_elem_type(vector_typ: Type[Vector[T, L]]) -> T: def read_elem_type(typ): - if typ == bytes: + if typ == bytes or (isinstance(typ, type) and issubclass(typ, bytes)): # bytes or bytesN return byte elif is_list_type(typ): return read_list_elem_type(typ) elif is_vector_type(typ): return read_vector_elem_type(typ) - elif issubclass(typ, bytes): # bytes or bytesN - return byte else: raise TypeError("Unexpected type: {}".format(typ))