diff --git a/core/vm/dasigners.go b/core/vm/dasigners.go index a8a443b666..eb766345a3 100644 --- a/core/vm/dasigners.go +++ b/core/vm/dasigners.go @@ -221,16 +221,24 @@ func (d *DASignersPrecompile) MakeEpoch( // new epoch epoch += 1 cnt := d.epochRegistration(evm, epoch) - ballots := make([]Ballot, cnt) + ballots := []Ballot{} for index := range cnt { account := d.epochRegisteredSigner(evm, epoch, index) sigHash, _ := d.getRegistration(evm, epoch, account) - ballots[index] = Ballot{ - account: account, - content: sigHash, + votes := d.getVotes(evm, epoch, account) + // MaxVotesPerSigner is hard limit + if params.MaxVotesPerSigner.Int64() < int64(votes) { + votes = int(params.MaxVotesPerSigner.Int64()) + } + content := sigHash + for j := 0; j < votes; j += 1 { + ballots = append(ballots, Ballot{ + account: account, + content: content, + }) + content = crypto.Keccak256(content) } } - // TODO: calculate ballots based on staked amount sort.Slice(ballots, func(i, j int) bool { return bytes.Compare(ballots[i].content, ballots[j].content) < 0 }) @@ -289,6 +297,23 @@ func (d *DASignersPrecompile) setSigner(evm *EVM, signer dasigners.IDASignersSig return nil } +func (d *DASignersPrecompile) getRegistry() common.Address { + // This is a upgradeable contract deployed in Beacon-Proxy pattern in three raw transaction: + // raw tx params: + // from: 0xeb995d37799ad4a2db524e5ff0825ae2d4711757 + // nonce: 0..2 + // gasPrice: 100 Gwei + // gasLimit: 1000000 + // The sender is an ephemeral account, nobody holds its private key and this is the only transaction it signed. + // This transaction is a legacy transaction without chain ID so it can be deployed at any EVM chain which supports pre-EIP155 transactions. + // raw tx #0(implementation): 0xf90b708085174876e800830f42408080b90b1d608060405234801561001057600080fd5b50610afd806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063807f063a1161005b578063807f063a146100b25780638129fc1c146100d75780638da5cb5b146100df578063f2fde38b1461010f57600080fd5b806356a3237214610082578063715018a6146100975780637ca4dd5e1461009f575b600080fd5b6100956100903660046106e6565b610122565b005b610095610242565b6100956100ad3660046107b5565b610256565b6100bb61100081565b6040516001600160a01b03909116815260200160405180910390f35b610095610395565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03166100bb565b61009561011d3660046108bd565b6104b7565b33321461014257604051630f15d65160e01b815260040160405180910390fd5b6000806110006001600160a01b0316630f62bda560e01b3385600160405160240161016f939291906108d8565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516101ad9190610934565b6000604051808303816000865af19150503d80600081146101ea576040519150601f19603f3d011682016040523d82523d6000602084013e6101ef565b606091505b509150915081816040516020016102069190610950565b6040516020818303038152906040529061023c5760405162461bcd60e51b815260040161023391906109c1565b60405180910390fd5b50505050565b61024a6104f5565b6102546000610550565b565b33321461027657604051630f15d65160e01b815260040160405180910390fd5b81516001600160a01b031633146102a057604051631024390d60e21b815260040160405180910390fd5b6000806110006001600160a01b0316637ca4dd5e60e01b85856040516024016102ca9291906109f7565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516103089190610934565b6000604051808303816000865af19150503d8060008114610345576040519150601f19603f3d011682016040523d82523d6000602084013e61034a565b606091505b509150915081816040516020016103619190610a82565b6040516020818303038152906040529061038e5760405162461bcd60e51b815260040161023391906109c1565b5050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156103db5750825b905060008267ffffffffffffffff1660011480156103f85750303b155b905081158015610406575080155b156104245760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561044e57845460ff60401b1916600160401b1785555b61046b732d7f2d2286994477ba878f321b17a7e40e52cda46105c1565b831561038e57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050505050565b6104bf6104f5565b6001600160a01b0381166104e957604051631e4fbdf760e01b815260006004820152602401610233565b6104f281610550565b50565b336105277f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146102545760405163118cdaa760e01b8152336004820152602401610233565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6105c96105d2565b6104f28161061b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661025457604051631afcd79f60e31b815260040160405180910390fd5b6104bf6105d2565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561065c5761065c610623565b60405290565b6040516080810167ffffffffffffffff8111828210171561065c5761065c610623565b604051601f8201601f1916810167ffffffffffffffff811182821017156106ae576106ae610623565b604052919050565b6000604082840312156106c857600080fd5b6106d0610639565b9050813581526020820135602082015292915050565b6000604082840312156106f857600080fd5b61070283836106b6565b9392505050565b80356001600160a01b038116811461072057600080fd5b919050565b600082601f83011261073657600080fd5b61073e610639565b80604084018581111561075057600080fd5b845b8181101561076a578035845260209384019301610752565b509095945050505050565b60006080828403121561078757600080fd5b61078f610639565b905061079b8383610725565b81526107aa8360408401610725565b602082015292915050565b600080606083850312156107c857600080fd5b823567ffffffffffffffff808211156107e057600080fd5b9084019061010082870312156107f557600080fd5b6107fd610662565b61080683610709565b81526020808401358381111561081b57600080fd5b8401601f8101891361082c57600080fd5b80358481111561083e5761083e610623565b610850601f8201601f19168401610685565b9450808552898382840101111561086657600080fd5b808383018487013760008382870101525050828183015261088a88604086016106b6565b604083015261089c8860808601610775565b60608301528195506108b0888289016106b6565b9450505050509250929050565b6000602082840312156108cf57600080fd5b61070282610709565b6001600160a01b0384168152608081016108ff602083018580518252602090810151910152565b60ff83166060830152949350505050565b60005b8381101561092b578181015183820152602001610913565b50506000910152565b60008251610946818460208701610910565b9190910192915050565b7f72656769737465724e65787445706f63682063616c6c206661696c65643a200081526000825161098881601f850160208701610910565b91909101601f0192915050565b600081518084526109ad816020860160208601610910565b601f01601f19169290920160200192915050565b6020815260006107026020830184610995565b8060005b600281101561023c5781518452602093840193909101906001016109d8565b606080825283516001600160a01b03169082015260208301516101006080830152600090610a29610160840182610995565b6040860151805160a0860152602081015160c0860152909150506060850151610a5660e0850182516109d4565b60200151610a686101208501826109d4565b509050610702602083018480518252602090810151910152565b7f72656769737465725369676e65722063616c6c206661696c65643a2000000000815260008251610aba81601c850160208701610910565b91909101601c019291505056fea2646970667358221220bb50c03fb5e1cc5e8bb317ff0bf7889ef0b368a37ea3568a9d02d8379ebc351164736f6c634300081400331ba04ce6e58373b6023b7ffc717cc0db01847ed8da661c7c3c98693957d3248af35fa0727edc90561444dcb4e91a329e8ef7916cb018dfef5f18e86e2bd90391e7a204 + // raw tx #1(beacon): 0xf904cb0185174876e800830f42408080b90478608060405234801561001057600080fd5b5060405161043838038061043883398101604081905261002f91610165565b806001600160a01b03811661005f57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61006881610079565b50610072826100c9565b5050610198565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b806001600160a01b03163b6000036100ff5760405163211eb15960e21b81526001600160a01b0382166004820152602401610056565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b80516001600160a01b038116811461016057600080fd5b919050565b6000806040838503121561017857600080fd5b61018183610149565b915061018f60208401610149565b90509250929050565b610291806101a76000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80633659cfe61461005c5780635c60da1b14610071578063715018a61461009a5780638da5cb5b146100a2578063f2fde38b146100b3575b600080fd5b61006f61006a36600461022b565b6100c6565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006f6100da565b6000546001600160a01b031661007e565b61006f6100c136600461022b565b6100ee565b6100ce61012e565b6100d78161015b565b50565b6100e261012e565b6100ec60006101db565b565b6100f661012e565b6001600160a01b03811661012557604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6100d7816101db565b6000546001600160a01b031633146100ec5760405163118cdaa760e01b815233600482015260240161011c565b806001600160a01b03163b6000036101915760405163211eb15960e21b81526001600160a01b038216600482015260240161011c565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561023d57600080fd5b81356001600160a01b038116811461025457600080fd5b939250505056fea26469706673582212205220e5b3095ab739313888ed7a605b359ca52e79f2a5a6297e03c439e8e8b30764736f6c634300081400330000000000000000000000007ad29425f6d68ed6bd8eb8a77d73bb2ad81b8afa0000000000000000000000002d7f2d2286994477ba878f321b17a7e40e52cda41ca0a1e38aac4e65cf5d87e9c2f857d3f0b3cc9f24d42639689f01c9876a45665ebda0330c349d845c3403c9be2b8e31ed0c17e5b3824d02c9e11e71564df71d6621ee + // raw tx #2(proxy): 0xf906720285174876e800830f42408080b9061f60a06040526040516105bf3803806105bf83398101604081905261002291610387565b61002c828261003e565b506001600160a01b031660805261047e565b610047826100fe565b6040516001600160a01b038316907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a28051156100f2576100ed826001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e79190610447565b82610211565b505050565b6100fa610288565b5050565b806001600160a01b03163b60000361013957604051631933b43b60e21b81526001600160a01b03821660048201526024015b60405180910390fd5b807fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b0392831617905560408051635c60da1b60e01b81529051600092841691635c60da1b9160048083019260209291908290030181865afa1580156101b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d99190610447565b9050806001600160a01b03163b6000036100fa57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610130565b6060600080846001600160a01b03168460405161022e9190610462565b600060405180830381855af49150503d8060008114610269576040519150601f19603f3d011682016040523d82523d6000602084013e61026e565b606091505b50909250905061027f8583836102a9565b95945050505050565b34156102a75760405163b398979f60e01b815260040160405180910390fd5b565b6060826102be576102b982610308565b610301565b81511580156102d557506001600160a01b0384163b155b156102fe57604051639996b31560e01b81526001600160a01b0385166004820152602401610130565b50805b9392505050565b8051156103185780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811461034857600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561037e578181015183820152602001610366565b50506000910152565b6000806040838503121561039a57600080fd5b6103a383610331565b60208401519092506001600160401b03808211156103c057600080fd5b818501915085601f8301126103d457600080fd5b8151818111156103e6576103e661034d565b604051601f8201601f19908116603f0116810190838211818310171561040e5761040e61034d565b8160405282815288602084870101111561042757600080fd5b610438836020830160208801610363565b80955050505050509250929050565b60006020828403121561045957600080fd5b61030182610331565b60008251610474818460208701610363565b9190910192915050565b6080516101276104986000396000601e01526101276000f3fe6080604052600a600c565b005b60186014601a565b60a0565b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156079573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190609b919060c3565b905090565b3660008037600080366000845af43d6000803e80801560be573d6000f35b3d6000fd5b60006020828403121560d457600080fd5b81516001600160a01b038116811460ea57600080fd5b939250505056fea264697066735822122039e43d51fa1bcd8fe79599db2a7e6dd3e5358b756c53210827bbf02fda62be6c64736f6c63430008140033000000000000000000000000762662fb644cdd051f35e0dd8fb6ac15a4bf65ad000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000001ca04189ff3e2929af3203bb5041d582084f676c866a1faae88b0a1fad3f616b90ada0309a30d2c3fabc8e659b9a747c75f62556f1db3b269b1377fa936b7c236685cb + // The owners of the contract and the beacon will be set to 0x2D7F2d2286994477Ba878f321b17A7e40E52cDa4, + // and after the network has launched and reached a stable state, ownership will be transferred to a timelock contract controlled by a multisig + return common.HexToAddress("0x20f30b2584f3096ea0d6c18c3b5cacc0585e12fc") +} + func (d *DASignersPrecompile) RegisterSigner( evm *EVM, contract *Contract, @@ -301,15 +326,12 @@ func (d *DASignersPrecompile) RegisterSigner( signer := args[0].(dasigners.IDASignersSignerDetail) signature := dasigners.SerializeG1(args[1].(dasigners.BN254G1Point)) // validation - if evm.Origin != signer.Signer { - return nil, dasigners.ErrInvalidSender - } - if contract.caller != evm.Origin { - return nil, precompiles.ErrSenderNotOrigin + if contract.caller != d.getRegistry() { + return nil, precompiles.ErrSenderNotRegistry } // execute // validate sender - // TODO: check staked + // staked value is checked in registry contract _, found, err := d.getSigner(evm, signer.Signer) if err != nil { return nil, err @@ -344,12 +366,14 @@ func (d *DASignersPrecompile) epochRegisteredSigner(evm *EVM, epoch uint64, inde return common.Address(h[12:]) } -func (d *DASignersPrecompile) storeRegistration(evm *EVM, epoch uint64, signer common.Address, signature []byte) error { +func (d *DASignersPrecompile) storeRegistration(evm *EVM, epoch uint64, signer common.Address, signature []byte, votes *big.Int) error { if _, found := d.getRegistration(evm, epoch, signer); found { return nil } // save signature hash evm.StateDB.SetState(d.Address(), dasigners.RegistrationKey(epoch, signer), crypto.Keccak256Hash(signature)) + // save votes + evm.StateDB.SetState(d.Address(), dasigners.VotesKey(epoch, signer), common.BigToHash(votes)) // increment epoch registration count registration := d.epochRegistration(evm, epoch) evm.StateDB.SetState(d.Address(), dasigners.EpochRegistrationKey(epoch), common.BigToHash(big.NewInt(int64(registration+1)))) @@ -364,18 +388,20 @@ func (d *DASignersPrecompile) RegisterNextEpoch( method *abi.Method, args []interface{}, ) ([]byte, error) { - if len(args) != 1 { + if len(args) != 3 { return nil, ErrExecutionReverted } - signature := dasigners.SerializeG1(args[0].(dasigners.BN254G1Point)) + account := args[0].(common.Address) + signature := dasigners.SerializeG1(args[1].(dasigners.BN254G1Point)) + votes := args[2].(*big.Int) // validation - if contract.caller != evm.Origin { - return nil, precompiles.ErrSenderNotOrigin + if contract.caller != d.getRegistry() { + return nil, precompiles.ErrSenderNotRegistry } // execute // get signer - // TODO: check staked - signer, found, err := d.getSigner(evm, contract.caller) + // staked value is checked in registry contract + signer, found, err := d.getSigner(evm, account) if err != nil { return nil, err } @@ -385,12 +411,12 @@ func (d *DASignersPrecompile) RegisterNextEpoch( // validate signature epochNumber := d.epochNumber(evm) chainID := evm.chainConfig.ChainID - hash := dasigners.EpochRegistrationHash(contract.caller, epochNumber+1, chainID) + hash := dasigners.EpochRegistrationHash(account, epochNumber+1, chainID) if !dasigners.ValidateSignature(signer, hash, bn254util.DeserializeG1(signature)) { return nil, dasigners.ErrInvalidSignature } // save registration - if err := d.storeRegistration(evm, epochNumber+1, contract.caller, signature); err != nil { + if err := d.storeRegistration(evm, epochNumber+1, account, signature, votes); err != nil { return nil, err } return method.Outputs.Pack() @@ -432,7 +458,7 @@ func (d *DASignersPrecompile) UpdateSocket( func (d *DASignersPrecompile) params() dasigners.IDASignersParams { return dasigners.IDASignersParams{ - TokensPerVote: big.NewInt(10), + TokensPerVote: big.NewInt(10), // deprecated MaxVotesPerSigner: big.NewInt(1024), MaxQuorums: big.NewInt(10), EpochBlocks: big.NewInt(5760), @@ -524,6 +550,10 @@ func (d *DASignersPrecompile) getRegistration(evm *EVM, epoch uint64, account co return h.Bytes(), true } +func (d *DASignersPrecompile) getVotes(evm *EVM, epoch uint64, account common.Address) int { + return int(evm.StateDB.GetState(d.Address(), dasigners.VotesKey(epoch, account)).Big().Int64()) +} + func (d *DASignersPrecompile) RegisteredEpoch(evm *EVM, method *abi.Method, args []interface{}) ([]byte, error) { if len(args) != 2 { return nil, ErrExecutionReverted diff --git a/core/vm/dasigners_test.go b/core/vm/dasigners_test.go index 2504b934d5..c7f67f0731 100644 --- a/core/vm/dasigners_test.go +++ b/core/vm/dasigners_test.go @@ -69,7 +69,7 @@ func (suite *DASignersTestSuite) registerSigner(testSigner common.Address, sk *b suite.Assert().NoError(err) oldLogs := suite.statedb.Logs() - _, err = suite.runTx(input, testSigner, 10000000, uint256.NewInt(0), false) + _, err = suite.runTx(input, suite.dasigners.getRegistry(), 10000000, uint256.NewInt(0), false) suite.Assert().NoError(err) logs := suite.statedb.Logs() suite.Assert().EqualValues(len(logs), len(oldLogs)+2) @@ -110,18 +110,20 @@ func (suite *DASignersTestSuite) updateSocket(testSigner common.Address, signer signer.Socket = "0.0.0.0:2345" } -func (suite *DASignersTestSuite) registerEpoch(testSigner common.Address, sk *big.Int) { +func (suite *DASignersTestSuite) registerEpoch(testSigner common.Address, sk *big.Int, votes *big.Int) { epoch := suite.dasigners.epochNumber(suite.evm) + 1 hash := dasigners.EpochRegistrationHash(testSigner, epoch, suite.evm.chainConfig.ChainID) signature := new(bn254.G1Affine).ScalarMultiplication(hash, sk) input, err := suite.abi.Pack( "registerNextEpoch", + testSigner, dasigners.NewBN254G1Point(bn254util.SerializeG1(signature)), + votes, ) suite.Assert().NoError(err) - _, err = suite.runTx(input, testSigner, 10000000, uint256.NewInt(0), false) + _, err = suite.runTx(input, suite.dasigners.getRegistry(), 10000000, uint256.NewInt(0), false) suite.Assert().NoError(err) } @@ -264,8 +266,8 @@ func (suite *DASignersTestSuite) Test_DASigners() { signer2 := suite.registerSigner(suite.signerTwo, big.NewInt(11)) suite.updateSocket(suite.signerOne, signer1) suite.updateSocket(suite.signerTwo, signer2) - suite.registerEpoch(suite.signerOne, big.NewInt(1)) - suite.registerEpoch(suite.signerTwo, big.NewInt(11)) + suite.registerEpoch(suite.signerOne, big.NewInt(1), big.NewInt(1)) + suite.registerEpoch(suite.signerTwo, big.NewInt(11), big.NewInt(2)) // move to next epochs daparams := suite.dasigners.params() suite.queryEpochNumber(suite.signerOne, big.NewInt(0)) @@ -274,8 +276,8 @@ func (suite *DASignersTestSuite) Test_DASigners() { suite.queryEpochNumber(suite.signerOne, big.NewInt(1)) suite.makeEpoch(suite.signerOne) suite.queryEpochNumber(suite.signerOne, big.NewInt(1)) - suite.registerEpoch(suite.signerOne, big.NewInt(1)) - suite.registerEpoch(suite.signerTwo, big.NewInt(11)) + suite.registerEpoch(suite.signerOne, big.NewInt(1), big.NewInt(1)) + suite.registerEpoch(suite.signerTwo, big.NewInt(11), big.NewInt(2)) // move to epoch 2 suite.evm.Context.BlockNumber = suite.evm.Context.BlockNumber.Add(suite.evm.Context.BlockNumber, daparams.EpochBlocks) suite.makeEpoch(suite.signerOne) @@ -307,10 +309,8 @@ func (suite *DASignersTestSuite) Test_DASigners() { twoPos = min(twoPos, i) } } - suite.Assert().EqualValues(cnt[suite.signerOne], len(quorum)/2) - suite.Assert().EqualValues(cnt[suite.signerTwo], len(quorum)/2) - // suite.Assert().EqualValues(cnt[suite.signerOne], len(quorum)/3) - // suite.Assert().EqualValues(cnt[suite.signerTwo], len(quorum)*2/3) + suite.Assert().EqualValues(cnt[suite.signerOne], len(quorum)/3) + suite.Assert().EqualValues(cnt[suite.signerTwo], len(quorum)*2/3) bitMap := make([]byte, len(quorum)/8) bitMap[onePos/8] |= 1 << (onePos % 8) @@ -321,8 +321,7 @@ func (suite *DASignersTestSuite) Test_DASigners() { }{ AggPkG1: dasigners.NewBN254G1Point(bn254util.SerializeG1(new(bn254.G1Affine).ScalarMultiplication(bn254util.GetG1Generator(), big.NewInt(1)))), Total: big.NewInt(int64(len(quorum))), - Hit: big.NewInt(int64(len(quorum) / 2)), - // Hit: big.NewInt(int64(len(quorum) / 3)), + Hit: big.NewInt(int64(len(quorum) / 3)), }) bitMap[twoPos/8] |= 1 << (twoPos % 8) diff --git a/core/vm/precompiles/dasigners/contract.go b/core/vm/precompiles/dasigners/contract.go index 268c11d70c..083bec8fa9 100644 --- a/core/vm/precompiles/dasigners/contract.go +++ b/core/vm/precompiles/dasigners/contract.go @@ -30,7 +30,7 @@ var ( // DASignersMetaData contains all meta data concerning the DASigners contract. var DASignersMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structBN254.G1Point\",\"name\":\"pkG1\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"X\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"Y\",\"type\":\"uint256[2]\"}],\"indexed\":false,\"internalType\":\"structBN254.G2Point\",\"name\":\"pkG2\",\"type\":\"tuple\"}],\"name\":\"NewSigner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"socket\",\"type\":\"string\"}],\"name\":\"SocketUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"epochNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_quorumId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_quorumBitmap\",\"type\":\"bytes\"}],\"name\":\"getAggPkG1\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"internalType\":\"structBN254.G1Point\",\"name\":\"aggPkG1\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"total\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"hit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_quorumId\",\"type\":\"uint256\"}],\"name\":\"getQuorum\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_quorumId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_rowIndex\",\"type\":\"uint32\"}],\"name\":\"getQuorumRow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_account\",\"type\":\"address[]\"}],\"name\":\"getSigner\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"socket\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"internalType\":\"structBN254.G1Point\",\"name\":\"pkG1\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"X\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"Y\",\"type\":\"uint256[2]\"}],\"internalType\":\"structBN254.G2Point\",\"name\":\"pkG2\",\"type\":\"tuple\"}],\"internalType\":\"structIDASigners.SignerDetail[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"isSigner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"makeEpoch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"params\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"tokensPerVote\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxVotesPerSigner\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxQuorums\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"epochBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"encodedSlices\",\"type\":\"uint256\"}],\"internalType\":\"structIDASigners.Params\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"quorumCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"internalType\":\"structBN254.G1Point\",\"name\":\"_signature\",\"type\":\"tuple\"}],\"name\":\"registerNextEpoch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"socket\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"internalType\":\"structBN254.G1Point\",\"name\":\"pkG1\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"X\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"Y\",\"type\":\"uint256[2]\"}],\"internalType\":\"structBN254.G2Point\",\"name\":\"pkG2\",\"type\":\"tuple\"}],\"internalType\":\"structIDASigners.SignerDetail\",\"name\":\"_signer\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"internalType\":\"structBN254.G1Point\",\"name\":\"_signature\",\"type\":\"tuple\"}],\"name\":\"registerSigner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"registeredEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_socket\",\"type\":\"string\"}],\"name\":\"updateSocket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structBN254.G1Point\",\"name\":\"pkG1\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"X\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"Y\",\"type\":\"uint256[2]\"}],\"indexed\":false,\"internalType\":\"structBN254.G2Point\",\"name\":\"pkG2\",\"type\":\"tuple\"}],\"name\":\"NewSigner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"socket\",\"type\":\"string\"}],\"name\":\"SocketUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"epochNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_quorumId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_quorumBitmap\",\"type\":\"bytes\"}],\"name\":\"getAggPkG1\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"internalType\":\"structBN254.G1Point\",\"name\":\"aggPkG1\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"total\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"hit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_quorumId\",\"type\":\"uint256\"}],\"name\":\"getQuorum\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_quorumId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_rowIndex\",\"type\":\"uint32\"}],\"name\":\"getQuorumRow\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_account\",\"type\":\"address[]\"}],\"name\":\"getSigner\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"socket\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"internalType\":\"structBN254.G1Point\",\"name\":\"pkG1\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"X\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"Y\",\"type\":\"uint256[2]\"}],\"internalType\":\"structBN254.G2Point\",\"name\":\"pkG2\",\"type\":\"tuple\"}],\"internalType\":\"structIDASigners.SignerDetail[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"isSigner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"makeEpoch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"params\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"tokensPerVote\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxVotesPerSigner\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxQuorums\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"epochBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"encodedSlices\",\"type\":\"uint256\"}],\"internalType\":\"structIDASigners.Params\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"quorumCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"internalType\":\"structBN254.G1Point\",\"name\":\"_signature\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"votes\",\"type\":\"uint256\"}],\"name\":\"registerNextEpoch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"socket\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"internalType\":\"structBN254.G1Point\",\"name\":\"pkG1\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"X\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"Y\",\"type\":\"uint256[2]\"}],\"internalType\":\"structBN254.G2Point\",\"name\":\"pkG2\",\"type\":\"tuple\"}],\"internalType\":\"structIDASigners.SignerDetail\",\"name\":\"_signer\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"internalType\":\"structBN254.G1Point\",\"name\":\"_signature\",\"type\":\"tuple\"}],\"name\":\"registerSigner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"registeredEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_socket\",\"type\":\"string\"}],\"name\":\"updateSocket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } // DASignersABI is the input ABI used to generate the binding from. @@ -498,25 +498,25 @@ func (_DASigners *DASignersTransactorSession) MakeEpoch() (*types.Transaction, e return _DASigners.Contract.MakeEpoch(&_DASigners.TransactOpts) } -// RegisterNextEpoch is a paid mutator transaction binding the contract method 0x56a32372. +// RegisterNextEpoch is a paid mutator transaction binding the contract method 0x0f62bda5. // -// Solidity: function registerNextEpoch((uint256,uint256) _signature) returns() -func (_DASigners *DASignersTransactor) RegisterNextEpoch(opts *bind.TransactOpts, _signature BN254G1Point) (*types.Transaction, error) { - return _DASigners.contract.Transact(opts, "registerNextEpoch", _signature) +// Solidity: function registerNextEpoch(address signer, (uint256,uint256) _signature, uint256 votes) returns() +func (_DASigners *DASignersTransactor) RegisterNextEpoch(opts *bind.TransactOpts, signer common.Address, _signature BN254G1Point, votes *big.Int) (*types.Transaction, error) { + return _DASigners.contract.Transact(opts, "registerNextEpoch", signer, _signature, votes) } -// RegisterNextEpoch is a paid mutator transaction binding the contract method 0x56a32372. +// RegisterNextEpoch is a paid mutator transaction binding the contract method 0x0f62bda5. // -// Solidity: function registerNextEpoch((uint256,uint256) _signature) returns() -func (_DASigners *DASignersSession) RegisterNextEpoch(_signature BN254G1Point) (*types.Transaction, error) { - return _DASigners.Contract.RegisterNextEpoch(&_DASigners.TransactOpts, _signature) +// Solidity: function registerNextEpoch(address signer, (uint256,uint256) _signature, uint256 votes) returns() +func (_DASigners *DASignersSession) RegisterNextEpoch(signer common.Address, _signature BN254G1Point, votes *big.Int) (*types.Transaction, error) { + return _DASigners.Contract.RegisterNextEpoch(&_DASigners.TransactOpts, signer, _signature, votes) } -// RegisterNextEpoch is a paid mutator transaction binding the contract method 0x56a32372. +// RegisterNextEpoch is a paid mutator transaction binding the contract method 0x0f62bda5. // -// Solidity: function registerNextEpoch((uint256,uint256) _signature) returns() -func (_DASigners *DASignersTransactorSession) RegisterNextEpoch(_signature BN254G1Point) (*types.Transaction, error) { - return _DASigners.Contract.RegisterNextEpoch(&_DASigners.TransactOpts, _signature) +// Solidity: function registerNextEpoch(address signer, (uint256,uint256) _signature, uint256 votes) returns() +func (_DASigners *DASignersTransactorSession) RegisterNextEpoch(signer common.Address, _signature BN254G1Point, votes *big.Int) (*types.Transaction, error) { + return _DASigners.Contract.RegisterNextEpoch(&_DASigners.TransactOpts, signer, _signature, votes) } // RegisterSigner is a paid mutator transaction binding the contract method 0x7ca4dd5e. diff --git a/core/vm/precompiles/dasigners/types.go b/core/vm/precompiles/dasigners/types.go index 7d76a6e05c..f27b930b2e 100644 --- a/core/vm/precompiles/dasigners/types.go +++ b/core/vm/precompiles/dasigners/types.go @@ -71,12 +71,13 @@ func SerializeG2(p BN254G2Point) []byte { var ( signerKey = []byte{0x00} // signer => registered signer info quorumKey = []byte{0x01} // epoch => quorumId => quorum - registrationKey = []byte{0x02} // signer => signature hash - quorumCountKey = []byte{0x03} // epoch => quorum count - epochNumberKey = []byte{0x04} // epoch number - epochBlockKey = []byte{0x05} // epoch number => block number - epochRegistrationKey = []byte{0x06} // epoch number => registration count - epochRegisteredSignerKey = []byte{0x07} // epoch number => index => signer + registrationKey = []byte{0x02} // epoch => signer => signature(vrf) + votesKey = []byte{0x03} // epoch => signer => votes + quorumCountKey = []byte{0x04} // epoch => quorum count + epochNumberKey = []byte{0x05} // epoch number + epochBlockKey = []byte{0x06} // epoch number => block number + epochRegistrationKey = []byte{0x07} // epoch number => registration count + epochRegisteredSignerKey = []byte{0x08} // epoch number => index => signer ) func SignerKey(account common.Address) common.Hash { @@ -91,6 +92,10 @@ func RegistrationKey(epochNumber uint64, account common.Address) common.Hash { return crypto.Keccak256Hash(append(append(registrationKey, common.Uint64ToBytes(epochNumber)...), account.Bytes()...)) } +func VotesKey(epochNumber uint64, account common.Address) common.Hash { + return crypto.Keccak256Hash(append(append(votesKey, common.Uint64ToBytes(epochNumber)...), account.Bytes()...)) +} + func QuorumCountKey(epochNumber uint64) common.Hash { return crypto.Keccak256Hash(append(quorumCountKey, common.Uint64ToBytes(epochNumber)...)) } diff --git a/core/vm/precompiles/errors.go b/core/vm/precompiles/errors.go index c2b23b44f6..6d0cffd6c1 100644 --- a/core/vm/precompiles/errors.go +++ b/core/vm/precompiles/errors.go @@ -3,5 +3,6 @@ package precompiles import "errors" var ( - ErrSenderNotOrigin = errors.New("sender not origin") + ErrSenderNotOrigin = errors.New("sender not origin") + ErrSenderNotRegistry = errors.New("sender not registry") ) diff --git a/core/vm/precompiles/interfaces/abis/IDASigners.json b/core/vm/precompiles/interfaces/abis/IDASigners.json index d75f52ee55..65054a5d39 100644 --- a/core/vm/precompiles/interfaces/abis/IDASigners.json +++ b/core/vm/precompiles/interfaces/abis/IDASigners.json @@ -336,6 +336,11 @@ }, { "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + }, { "components": [ { @@ -352,6 +357,11 @@ "internalType": "struct BN254.G1Point", "name": "_signature", "type": "tuple" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" } ], "name": "registerNextEpoch", diff --git a/core/vm/precompiles/interfaces/contracts/IDASigners.sol b/core/vm/precompiles/interfaces/contracts/IDASigners.sol index 050a1a69c6..d17f6d93a8 100644 --- a/core/vm/precompiles/interfaces/contracts/IDASigners.sol +++ b/core/vm/precompiles/interfaces/contracts/IDASigners.sol @@ -24,7 +24,7 @@ interface IDASigners { } struct Params { - uint tokensPerVote; + uint tokensPerVote; // deprecated uint maxVotesPerSigner; uint maxQuorums; uint epochBlocks; @@ -75,7 +75,11 @@ interface IDASigners { uint _epoch ) external view returns (bool); - function registerNextEpoch(BN254.G1Point memory _signature) external; + function registerNextEpoch( + address signer, + BN254.G1Point memory _signature, + uint votes + ) external; function makeEpoch() external;