diff --git a/sharding/README.md b/sharding/README.md index b85b5b337de7..eb330e79529f 100644 --- a/sharding/README.md +++ b/sharding/README.md @@ -38,6 +38,14 @@ The project consists of the following parts, with each of them requiring compreh The VMC is built in Solidity and deployed to the geth node upon launch of the client if it does not exist in the network at a specified address. If the contract already exists, the client simply sets up an interface to programmatically call the internal contract functions and listens to transactions broadcasted to the geth node to begin the sharding system. +#### Generating Contract Bindings + +To generate the go bindings run the following command from this package: + +```bash +go generate +``` + ### VMC Wrapper & Sharding Client As we will be interacting with a geth node, we will create a Golang interface that wraps over the VMC and a client that connects to the local geth node upon launch via JSON-RPC. diff --git a/sharding/client.go b/sharding/client.go index 3ad384ea4eec..5fdd4059f79f 100644 --- a/sharding/client.go +++ b/sharding/client.go @@ -1,5 +1,7 @@ package sharding +//go:generate abigen --sol contracts/validator_manager.sol --pkg contracts --out contracts/validator_manager.go + import ( "context" "fmt" @@ -7,6 +9,8 @@ import ( "math/big" "strings" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/keystore" @@ -164,6 +168,35 @@ func (c *Client) createTXOps(value *big.Int) (bind.TransactOpts, error) { } +// Account to use for sharding transactions. +func (c *Client) Account() (*accounts.Account, error) { + accounts := c.keystore.Accounts() + if len(accounts) == 0 { + return nil, fmt.Errorf("no accounts found") + } + + if err := c.unlockAccount(accounts[0]); err != nil { + return nil, fmt.Errorf("cannot unlock account. %v", err) + } + + return &accounts[0], nil +} + +// ChainReader for interacting with the chain. +func (c *Client) ChainReader() ethereum.ChainReader { + return ethereum.ChainReader(c.client) +} + +// Client to interact with ethereum node. +func (c *Client) Client() *ethclient.Client { + return c.client +} + +// VMCCaller to interact with the validator management contract. +func (c *Client) VMCCaller() *contracts.VMCCaller { + return &c.vmc.VMCCaller +} + // dialRPC endpoint to node. func dialRPC(endpoint string) (*rpc.Client, error) { if endpoint == "" { diff --git a/sharding/collator.go b/sharding/collator.go index a4662643b498..90ab269ac32c 100644 --- a/sharding/collator.go +++ b/sharding/collator.go @@ -3,21 +3,31 @@ package sharding import ( "context" "fmt" + "math/big" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" - "math/big" + "github.com/ethereum/go-ethereum/sharding/contracts" ) +type collatorClient interface { + Account() (*accounts.Account, error) + ChainReader() ethereum.ChainReader + VMCCaller() *contracts.VMCCaller +} + // SubscribeBlockHeaders checks incoming block headers and determines if // we are an eligible proposer for collations. Then, it finds the pending tx's // from the running geth node and sorts them by descending order of gas price, // eliminates those that ask for too much gas, and routes them over // to the VMC to create a collation -func subscribeBlockHeaders(c *Client) error { +func subscribeBlockHeaders(c collatorClient) error { headerChan := make(chan *types.Header, 16) - _, err := c.client.SubscribeNewHead(context.Background(), headerChan) + _, err := c.ChainReader().SubscribeNewHead(context.Background(), headerChan) if err != nil { return fmt.Errorf("unable to subscribe to incoming headers. %v", err) } @@ -42,27 +52,25 @@ func subscribeBlockHeaders(c *Client) error { // collation for the available shards in the VMC. The function calls // getEligibleProposer from the VMC and proposes a collation if // conditions are met -func checkShardsForProposal(c *Client, head *types.Header) error { - - accounts := c.keystore.Accounts() - if len(accounts) == 0 { - return fmt.Errorf("no accounts found") - } - - if err := c.unlockAccount(accounts[0]); err != nil { - return fmt.Errorf("cannot unlock account. %v", err) +func checkShardsForProposal(c collatorClient, head *types.Header) error { + account, err := c.Account() + if err != nil { + return err } log.Info("Checking if we are an eligible collation proposer for a shard...") for s := int64(0); s < shardCount; s++ { // Checks if we are an eligible proposer according to the VMC period := head.Number.Div(head.Number, big.NewInt(periodLength)) - addr, err := c.vmc.VMCCaller.GetEligibleProposer(&bind.CallOpts{}, big.NewInt(s), period) + addr, err := c.VMCCaller().GetEligibleProposer(&bind.CallOpts{}, big.NewInt(s), period) // TODO: When we are not a proposer, we get the error of being unable to // unmarshal empty output. Open issue to deal with this. + if err != nil { + return err + } // If output is non-empty and the addr == coinbase - if err == nil && addr == accounts[0].Address { + if addr == account.Address { log.Info(fmt.Sprintf("Selected as collator on shard: %d", s)) err := proposeCollation(s) if err != nil { diff --git a/sharding/collator_test.go b/sharding/collator_test.go index 584be3b19d29..d20313e724b5 100644 --- a/sharding/collator_test.go +++ b/sharding/collator_test.go @@ -2,28 +2,125 @@ package sharding import ( "context" - "fmt" + "errors" + "math/big" + "strings" "testing" + "github.com/ethereum/go-ethereum" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/sharding/contracts" + "github.com/ethereum/go-ethereum/core/types" ) -type FakeClient struct { - client *FakeEthClient +type FakeCollatorClient struct { + accountAccount *accounts.Account + accountError error + chainReader FakeChainReader + contractCaller FakeContractCaller +} + +func (c FakeCollatorClient) Account() (*accounts.Account, error) { + return c.accountAccount, c.accountError } -type FakeEthClient struct{} +func (c FakeCollatorClient) ChainReader() ethereum.ChainReader { + return c.chainReader +} + +func (c FakeCollatorClient) VMCCaller() *contracts.VMCCaller { + VMCCaller, err := contracts.NewVMCCaller(common.HexToAddress("0x0"), c.contractCaller) + if err != nil { + panic(err) + } + return VMCCaller +} -type FakeSubscription struct{} +type FakeChainReader struct { + subscribeNewHeadSubscription ethereum.Subscription + subscribeNewHeadError error +} -func (ec *FakeEthClient) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (FakeSubscription, error) { - return FakeSubscription{}, fmt.Errorf("error, network disconnected!") +func (r FakeChainReader) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { + return r.subscribeNewHeadSubscription, r.subscribeNewHeadError +} +func (r FakeChainReader) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + return nil, nil +} +func (r FakeChainReader) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + return nil, nil +} +func (r FakeChainReader) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { + return nil, nil +} +func (r FakeChainReader) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + return nil, nil +} +func (r FakeChainReader) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { + return 0, nil +} +func (r FakeChainReader) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { + return nil, nil +} + +type FakeContractCaller struct { + codeAtBytes []byte + codeAtError error + callContractBytes []byte + callContractError error +} + +func (c FakeContractCaller) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { + return c.codeAtBytes, c.codeAtError +} + +func (c FakeContractCaller) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { + return c.callContractBytes, c.callContractError +} + +func TestCheckShardsForProposal(t *testing.T) { + tests := []struct { + Name string + Head *types.Header + ExpectedPeriod *big.Int + ExpectedError string + CollatorClient FakeCollatorClient + }{ + { + Name: "collatorClient.Account should return an error", + ExpectedError: "no account", + CollatorClient: FakeCollatorClient{ + accountError: errors.New("no account"), + }, + }, + { + Name: "VMCCaller.GetEligibleProposer should return an error", + ExpectedError: "there is no cake", + CollatorClient: FakeCollatorClient{ + accountAccount: &accounts.Account{}, + contractCaller: FakeContractCaller{ + callContractError: errors.New("there is no cake"), + }, + }, + Head: &types.Header{Number: big.NewInt(100)}, + }, + } + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + if err := checkShardsForProposal(tt.CollatorClient, tt.Head); !strings.Contains(safeError(err), tt.ExpectedError) { + t.Fatalf("Incorrect error! Wanted %v, got %v", tt.ExpectedError, err) + } + }) + } } -func TestSubscribeHeaders(t *testing.T) { - client := &FakeClient{client: &FakeEthClient{}} - err := subscribeBlockHeaders(client) +func safeError(err error) string { if err != nil { - t.Errorf("subscribe new headers should work", "no error", err) + return err.Error() } + return "nil" } diff --git a/sharding/contracts/README.md b/sharding/contracts/README.md deleted file mode 100644 index 2850af6fbe35..000000000000 --- a/sharding/contracts/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Sharding contracts - -Generate contract bindings from this directory: - -```bash - -go run ../../cmd/abigen/main.go --sol validator_manager.sol --pkg contracts --out validator_manager.go - -``` diff --git a/sharding/contracts/validator_manager.go b/sharding/contracts/validator_manager.go index 71766678a448..a5c65898f040 100644 --- a/sharding/contracts/validator_manager.go +++ b/sharding/contracts/validator_manager.go @@ -7,17 +7,19 @@ import ( "math/big" "strings" + ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" ) // VMCABI is the input ABI used to generate the binding from. const VMCABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"int256\"},{\"name\":\"_expectedPeriodNumber\",\"type\":\"uint256\"},{\"name\":\"_periodStartPrevHash\",\"type\":\"bytes32\"},{\"name\":\"_parentHash\",\"type\":\"bytes32\"},{\"name\":\"_transactionRoot\",\"type\":\"bytes32\"},{\"name\":\"_coinbase\",\"type\":\"address\"},{\"name\":\"_stateRoot\",\"type\":\"bytes32\"},{\"name\":\"_receiptRoot\",\"type\":\"bytes32\"},{\"name\":\"_number\",\"type\":\"int256\"}],\"name\":\"addHeader\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"shardCount\",\"outputs\":[{\"name\":\"\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_receiptId\",\"type\":\"int256\"},{\"name\":\"_txGasprice\",\"type\":\"uint256\"}],\"name\":\"updateGasPrice\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_shardId\",\"type\":\"int256\"},{\"name\":\"_txStartgas\",\"type\":\"uint256\"},{\"name\":\"_txGasprice\",\"type\":\"uint256\"},{\"name\":\"_data\",\"type\":\"bytes12\"}],\"name\":\"txToShard\",\"outputs\":[{\"name\":\"\",\"type\":\"int256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_validatorIndex\",\"type\":\"int256\"}],\"name\":\"withdraw\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCollationGasLimit\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"deposit\",\"outputs\":[{\"name\":\"\",\"type\":\"int256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"int256\"},{\"name\":\"_period\",\"type\":\"uint256\"}],\"name\":\"getEligibleProposer\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"shardId\",\"type\":\"int256\"},{\"indexed\":false,\"name\":\"receiptId\",\"type\":\"int256\"}],\"name\":\"TxToShard\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"shardId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"collationHeader\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"isNewHead\",\"type\":\"bool\"},{\"indexed\":false,\"name\":\"score\",\"type\":\"uint256\"}],\"name\":\"CollationAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"validator\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"index\",\"type\":\"int256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"validatorIndex\",\"type\":\"int256\"}],\"name\":\"Withdraw\",\"type\":\"event\"}]" // VMCBin is the compiled bytecode used for deploying new contracts. -const VMCBin = `0x6060604052341561000f57600080fd5b61092f8061001e6000396000f30060606040526004361061008d5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630341518d811461009257806304e9c77a146100de5780632213138914610103578063372a9e2a146101115780637e62eab81461013b578063934586ec14610153578063d0e30db014610166578063e29de3ad1461016e575b600080fd5b341561009d57600080fd5b6100ca600435602435604435606435608435600160a060020a0360a4351660c43560e435610104356101a3565b604051901515815260200160405180910390f35b34156100e957600080fd5b6100f16103f6565b60405190815260200160405180910390f35b6100ca6004356024356103fb565b6100f1600160a060020a0360043516602435604435606435600160a060020a031960843516610440565b341561014657600080fd5b610151600435610563565b005b341561015e57600080fd5b6100f1610666565b6100f161066e565b341561017957600080fd5b610187600435602435610793565b604051600160a060020a03909116815260200160405180910390f35b60006101ad6108dc565b60008b121580156101be575060648b125b15156101c957600080fd5b60054310156101d757600080fd5b600543048a146101e657600080fd5b60001960058b02014089146101fa57600080fd5b8a8a8a8a8a600160a060020a038b168a8a8a60405198895260208901979097526040808901969096526060880194909452608087019290925260a086015260c085015260e08401526101008301919091526101209091019051908190039020815260008b815260016020526040812090825181526020810191909152604001600020600101541561028757fe5b87156102af5760008b81526001602081815260408084208c855290915282200154136102af57fe5b60008b8152600960205260409020548a90126102c757fe5b6102d48b60054304610793565b600160a060020a03166040820190815251600160a060020a031615156102f957600080fd5b8060400151600160a060020a031633600160a060020a031614151561031d57600080fd5b60008b81526001602081815260408084208c855282529092208101540190820190815251831461034c57600080fd5b60408051908101604052888152602080820190830151905260008c81526001602052604081209083518152602081019190915260400160002081518155602082015160019182015560008d81526009602090815260408083208f905583825280832060038352818420548452825290912090910154915082015113156103e557805160008c815260036020526040902055600160608201525b5060019a9950505050505050505050565b606481565b60008281526002602052604081206005015433600160a060020a0390811691161461042557600080fd5b50600091825260026020819052604090922090910155600190565b60008060e060405190810160409081528782526020808301889052818301879052346060840152600160a060020a031986166080840152600160a060020a0333811660a08501528a1660c08401526005546000908152600290915220815181556020820151816001015560408201518160020155606082015181600301556080820151600482015560a0820151600582018054600160a060020a031916600160a060020a039290921691909117905560c08201516006919091018054600160a060020a031916600160a060020a039283161790556005805460018101909155925087915088167ffc322e0c42ee41e0d74b940ceeee9cd5971acdd6ace8ff8010ee7134c31d9ea58360405190815260200160405180910390a39695505050505050565b60008181526020819052604090206001015433600160a060020a0390811691161461058d57600080fd5b6000818152602081905260409081902060018101549054600160a060020a039091169181156108fc02919051600060405180830381858888f1935050505015156105d657600080fd5b600081815260208181526040808320600181018054600160a060020a0316855260088452918420805460ff19169055848452918390529190558054600160a060020a031916905561062681610821565b600480546000190190557fe13f360aa18d414ccdb598da6c447faa89d0477ffc7549dab5678fca76910b8c8160405190815260200160405180910390a150565b629896805b90565b600160a060020a033316600090815260086020526040812054819060ff161561069657600080fd5b3468056bc75e2d63100000146106ab57600080fd5b6106b3610840565b15156106c8576106c1610847565b90506106cd565b506004545b604080519081016040908152348252600160a060020a0333166020808401919091526000848152908190522081518155602082015160019182018054600160a060020a031916600160a060020a0392831617905560048054830190553390811660009081526008602052604090819020805460ff19169093179092557fd8a6d38df847dcba70dfdeb4948fb1457d61a81d132801f40dc9c00d52dfd478925090839051600160a060020a03909216825260208201526040908101905180910390a1919050565b600060048210156107a357600080fd5b436003198301600502106107b657600080fd5b600454600090136107c657600080fd5b6000806107d161087e565b600319850140600502866040519182526020820152604090810190519081900390208115156107fc57fe5b068152602081019190915260400160002060010154600160a060020a03169392505050565b6007805460009081526006602052604090209190915580546001019055565b6007541590565b6000610851610840565b1561085f575060001961066b565b5060078054600019019081905560009081526006602052604090205490565b600754600454600091829101815b6104008112156108d1578181126108a2576108d1565b600081815260208190526040902060010154600160a060020a0316156108c9576001830192505b60010161088c565b505060075401919050565b608060405190810160409081526000808352602083018190529082018190526060820152905600a165627a7a7230582080291cd26024cdcd5c217feece7715d40f91360d0ce69131b2042e64a710397a0029` +const VMCBin = `0x6060604052341561000f57600080fd5b61092f8061001e6000396000f30060606040526004361061008d5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630341518d811461009257806304e9c77a146100de5780632213138914610103578063372a9e2a146101115780637e62eab81461013b578063934586ec14610153578063d0e30db014610166578063e29de3ad1461016e575b600080fd5b341561009d57600080fd5b6100ca600435602435604435606435608435600160a060020a0360a4351660c43560e435610104356101a3565b604051901515815260200160405180910390f35b34156100e957600080fd5b6100f16103f6565b60405190815260200160405180910390f35b6100ca6004356024356103fb565b6100f1600160a060020a0360043516602435604435606435600160a060020a031960843516610440565b341561014657600080fd5b610151600435610563565b005b341561015e57600080fd5b6100f1610666565b6100f161066e565b341561017957600080fd5b610187600435602435610793565b604051600160a060020a03909116815260200160405180910390f35b60006101ad6108dc565b60008b121580156101be575060648b125b15156101c957600080fd5b60054310156101d757600080fd5b600543048a146101e657600080fd5b60001960058b02014089146101fa57600080fd5b8a8a8a8a8a600160a060020a038b168a8a8a60405198895260208901979097526040808901969096526060880194909452608087019290925260a086015260c085015260e08401526101008301919091526101209091019051908190039020815260008b815260016020526040812090825181526020810191909152604001600020600101541561028757fe5b87156102af5760008b81526001602081815260408084208c855290915282200154136102af57fe5b60008b8152600960205260409020548a90126102c757fe5b6102d48b60054304610793565b600160a060020a03166040820190815251600160a060020a031615156102f957600080fd5b8060400151600160a060020a031633600160a060020a031614151561031d57600080fd5b60008b81526001602081815260408084208c855282529092208101540190820190815251831461034c57600080fd5b60408051908101604052888152602080820190830151905260008c81526001602052604081209083518152602081019190915260400160002081518155602082015160019182015560008d81526009602090815260408083208f905583825280832060038352818420548452825290912090910154915082015113156103e557805160008c815260036020526040902055600160608201525b5060019a9950505050505050505050565b606481565b60008281526002602052604081206005015433600160a060020a0390811691161461042557600080fd5b50600091825260026020819052604090922090910155600190565b60008060e060405190810160409081528782526020808301889052818301879052346060840152600160a060020a031986166080840152600160a060020a0333811660a08501528a1660c08401526005546000908152600290915220815181556020820151816001015560408201518160020155606082015181600301556080820151600482015560a0820151600582018054600160a060020a031916600160a060020a039290921691909117905560c08201516006919091018054600160a060020a031916600160a060020a039283161790556005805460018101909155925087915088167ffc322e0c42ee41e0d74b940ceeee9cd5971acdd6ace8ff8010ee7134c31d9ea58360405190815260200160405180910390a39695505050505050565b60008181526020819052604090206001015433600160a060020a0390811691161461058d57600080fd5b6000818152602081905260409081902060018101549054600160a060020a039091169181156108fc02919051600060405180830381858888f1935050505015156105d657600080fd5b600081815260208181526040808320600181018054600160a060020a0316855260088452918420805460ff19169055848452918390529190558054600160a060020a031916905561062681610821565b600480546000190190557fe13f360aa18d414ccdb598da6c447faa89d0477ffc7549dab5678fca76910b8c8160405190815260200160405180910390a150565b629896805b90565b600160a060020a033316600090815260086020526040812054819060ff161561069657600080fd5b3468056bc75e2d63100000146106ab57600080fd5b6106b3610840565b15156106c8576106c1610847565b90506106cd565b506004545b604080519081016040908152348252600160a060020a0333166020808401919091526000848152908190522081518155602082015160019182018054600160a060020a031916600160a060020a0392831617905560048054830190553390811660009081526008602052604090819020805460ff19169093179092557fd8a6d38df847dcba70dfdeb4948fb1457d61a81d132801f40dc9c00d52dfd478925090839051600160a060020a03909216825260208201526040908101905180910390a1919050565b600060048210156107a357600080fd5b436003198301600502106107b657600080fd5b600454600090136107c657600080fd5b6000806107d161087e565b600319850140600502866040519182526020820152604090810190519081900390208115156107fc57fe5b068152602081019190915260400160002060010154600160a060020a03169392505050565b6007805460009081526006602052604090209190915580546001019055565b6007541590565b6000610851610840565b1561085f575060001961066b565b5060078054600019019081905560009081526006602052604090205490565b600754600454600091829101815b6104008112156108d1578181126108a2576108d1565b600081815260208190526040902060010154600160a060020a0316156108c9576001830192505b60010161088c565b505060075401919050565b608060405190810160409081526000808352602083018190529082018190526060820152905600a165627a7a723058208fd1b0a9ffd9648b87c2a364000cfb827f1e0521b8664c8c4a706a5a5f1035c30029` // DeployVMC deploys a new Ethereum contract, binding an instance of VMC to it. func DeployVMC(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *VMC, error) { @@ -29,13 +31,14 @@ func DeployVMC(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Ad if err != nil { return common.Address{}, nil, nil, err } - return address, tx, &VMC{VMCCaller: VMCCaller{contract: contract}, VMCTransactor: VMCTransactor{contract: contract}}, nil + return address, tx, &VMC{VMCCaller: VMCCaller{contract: contract}, VMCTransactor: VMCTransactor{contract: contract}, VMCFilterer: VMCFilterer{contract: contract}}, nil } // VMC is an auto generated Go binding around an Ethereum contract. type VMC struct { VMCCaller // Read-only binding to the contract VMCTransactor // Write-only binding to the contract + VMCFilterer // Log filterer for contract events } // VMCCaller is an auto generated read-only Go binding around an Ethereum contract. @@ -48,6 +51,11 @@ type VMCTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } +// VMCFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type VMCFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + // VMCSession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. type VMCSession struct { @@ -87,16 +95,16 @@ type VMCTransactorRaw struct { // NewVMC creates a new instance of VMC, bound to a specific deployed contract. func NewVMC(address common.Address, backend bind.ContractBackend) (*VMC, error) { - contract, err := bindVMC(address, backend, backend) + contract, err := bindVMC(address, backend, backend, backend) if err != nil { return nil, err } - return &VMC{VMCCaller: VMCCaller{contract: contract}, VMCTransactor: VMCTransactor{contract: contract}}, nil + return &VMC{VMCCaller: VMCCaller{contract: contract}, VMCTransactor: VMCTransactor{contract: contract}, VMCFilterer: VMCFilterer{contract: contract}}, nil } // NewVMCCaller creates a new read-only instance of VMC, bound to a specific deployed contract. func NewVMCCaller(address common.Address, caller bind.ContractCaller) (*VMCCaller, error) { - contract, err := bindVMC(address, caller, nil) + contract, err := bindVMC(address, caller, nil, nil) if err != nil { return nil, err } @@ -105,20 +113,29 @@ func NewVMCCaller(address common.Address, caller bind.ContractCaller) (*VMCCalle // NewVMCTransactor creates a new write-only instance of VMC, bound to a specific deployed contract. func NewVMCTransactor(address common.Address, transactor bind.ContractTransactor) (*VMCTransactor, error) { - contract, err := bindVMC(address, nil, transactor) + contract, err := bindVMC(address, nil, transactor, nil) if err != nil { return nil, err } return &VMCTransactor{contract: contract}, nil } +// NewVMCFilterer creates a new log filterer instance of VMC, bound to a specific deployed contract. +func NewVMCFilterer(address common.Address, filterer bind.ContractFilterer) (*VMCFilterer, error) { + contract, err := bindVMC(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &VMCFilterer{contract: contract}, nil +} + // bindVMC binds a generic wrapper to an already deployed contract. -func bindVMC(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) { +func bindVMC(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { parsed, err := abi.JSON(strings.NewReader(VMCABI)) if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor), nil + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and @@ -341,3 +358,525 @@ func (_VMC *VMCSession) Withdraw(_validatorIndex *big.Int) (*types.Transaction, func (_VMC *VMCTransactorSession) Withdraw(_validatorIndex *big.Int) (*types.Transaction, error) { return _VMC.Contract.Withdraw(&_VMC.TransactOpts, _validatorIndex) } + +// VMCCollationAddedIterator is returned from FilterCollationAdded and is used to iterate over the raw logs and unpacked data for CollationAdded events raised by the VMC contract. +type VMCCollationAddedIterator struct { + Event *VMCCollationAdded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *VMCCollationAddedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(VMCCollationAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(VMCCollationAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *VMCCollationAddedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VMCCollationAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VMCCollationAdded represents a CollationAdded event raised by the VMC contract. +type VMCCollationAdded struct { + ShardId *big.Int + CollationHeader []byte + IsNewHead bool + Score *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterCollationAdded is a free log retrieval operation binding the contract event 0x431eecd13a3a04d2fdec84f4cb3ec783d0a6b1d7e92500bdd8d8de0dca7b2510. +// +// Solidity: event CollationAdded(shardId indexed uint256, collationHeader bytes, isNewHead bool, score uint256) +func (_VMC *VMCFilterer) FilterCollationAdded(opts *bind.FilterOpts, shardId []*big.Int) (*VMCCollationAddedIterator, error) { + + var shardIdRule []interface{} + for _, shardIdItem := range shardId { + shardIdRule = append(shardIdRule, shardIdItem) + } + + logs, sub, err := _VMC.contract.FilterLogs(opts, "CollationAdded", shardIdRule) + if err != nil { + return nil, err + } + return &VMCCollationAddedIterator{contract: _VMC.contract, event: "CollationAdded", logs: logs, sub: sub}, nil +} + +// WatchCollationAdded is a free log subscription operation binding the contract event 0x431eecd13a3a04d2fdec84f4cb3ec783d0a6b1d7e92500bdd8d8de0dca7b2510. +// +// Solidity: event CollationAdded(shardId indexed uint256, collationHeader bytes, isNewHead bool, score uint256) +func (_VMC *VMCFilterer) WatchCollationAdded(opts *bind.WatchOpts, sink chan<- *VMCCollationAdded, shardId []*big.Int) (event.Subscription, error) { + + var shardIdRule []interface{} + for _, shardIdItem := range shardId { + shardIdRule = append(shardIdRule, shardIdItem) + } + + logs, sub, err := _VMC.contract.WatchLogs(opts, "CollationAdded", shardIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(VMCCollationAdded) + if err := _VMC.contract.UnpackLog(event, "CollationAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// VMCDepositIterator is returned from FilterDeposit and is used to iterate over the raw logs and unpacked data for Deposit events raised by the VMC contract. +type VMCDepositIterator struct { + Event *VMCDeposit // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *VMCDepositIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(VMCDeposit) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(VMCDeposit) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *VMCDepositIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VMCDepositIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VMCDeposit represents a Deposit event raised by the VMC contract. +type VMCDeposit struct { + Validator common.Address + Index *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDeposit is a free log retrieval operation binding the contract event 0xd8a6d38df847dcba70dfdeb4948fb1457d61a81d132801f40dc9c00d52dfd478. +// +// Solidity: event Deposit(validator address, index int256) +func (_VMC *VMCFilterer) FilterDeposit(opts *bind.FilterOpts) (*VMCDepositIterator, error) { + + logs, sub, err := _VMC.contract.FilterLogs(opts, "Deposit") + if err != nil { + return nil, err + } + return &VMCDepositIterator{contract: _VMC.contract, event: "Deposit", logs: logs, sub: sub}, nil +} + +// WatchDeposit is a free log subscription operation binding the contract event 0xd8a6d38df847dcba70dfdeb4948fb1457d61a81d132801f40dc9c00d52dfd478. +// +// Solidity: event Deposit(validator address, index int256) +func (_VMC *VMCFilterer) WatchDeposit(opts *bind.WatchOpts, sink chan<- *VMCDeposit) (event.Subscription, error) { + + logs, sub, err := _VMC.contract.WatchLogs(opts, "Deposit") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(VMCDeposit) + if err := _VMC.contract.UnpackLog(event, "Deposit", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// VMCTxToShardIterator is returned from FilterTxToShard and is used to iterate over the raw logs and unpacked data for TxToShard events raised by the VMC contract. +type VMCTxToShardIterator struct { + Event *VMCTxToShard // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *VMCTxToShardIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(VMCTxToShard) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(VMCTxToShard) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *VMCTxToShardIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VMCTxToShardIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VMCTxToShard represents a TxToShard event raised by the VMC contract. +type VMCTxToShard struct { + To common.Address + ShardId *big.Int + ReceiptId *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTxToShard is a free log retrieval operation binding the contract event 0xfc322e0c42ee41e0d74b940ceeee9cd5971acdd6ace8ff8010ee7134c31d9ea5. +// +// Solidity: event TxToShard(to indexed address, shardId indexed int256, receiptId int256) +func (_VMC *VMCFilterer) FilterTxToShard(opts *bind.FilterOpts, to []common.Address, shardId []*big.Int) (*VMCTxToShardIterator, error) { + + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + var shardIdRule []interface{} + for _, shardIdItem := range shardId { + shardIdRule = append(shardIdRule, shardIdItem) + } + + logs, sub, err := _VMC.contract.FilterLogs(opts, "TxToShard", toRule, shardIdRule) + if err != nil { + return nil, err + } + return &VMCTxToShardIterator{contract: _VMC.contract, event: "TxToShard", logs: logs, sub: sub}, nil +} + +// WatchTxToShard is a free log subscription operation binding the contract event 0xfc322e0c42ee41e0d74b940ceeee9cd5971acdd6ace8ff8010ee7134c31d9ea5. +// +// Solidity: event TxToShard(to indexed address, shardId indexed int256, receiptId int256) +func (_VMC *VMCFilterer) WatchTxToShard(opts *bind.WatchOpts, sink chan<- *VMCTxToShard, to []common.Address, shardId []*big.Int) (event.Subscription, error) { + + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + var shardIdRule []interface{} + for _, shardIdItem := range shardId { + shardIdRule = append(shardIdRule, shardIdItem) + } + + logs, sub, err := _VMC.contract.WatchLogs(opts, "TxToShard", toRule, shardIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(VMCTxToShard) + if err := _VMC.contract.UnpackLog(event, "TxToShard", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// VMCWithdrawIterator is returned from FilterWithdraw and is used to iterate over the raw logs and unpacked data for Withdraw events raised by the VMC contract. +type VMCWithdrawIterator struct { + Event *VMCWithdraw // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *VMCWithdrawIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(VMCWithdraw) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(VMCWithdraw) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *VMCWithdrawIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VMCWithdrawIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VMCWithdraw represents a Withdraw event raised by the VMC contract. +type VMCWithdraw struct { + ValidatorIndex *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWithdraw is a free log retrieval operation binding the contract event 0xe13f360aa18d414ccdb598da6c447faa89d0477ffc7549dab5678fca76910b8c. +// +// Solidity: event Withdraw(validatorIndex int256) +func (_VMC *VMCFilterer) FilterWithdraw(opts *bind.FilterOpts) (*VMCWithdrawIterator, error) { + + logs, sub, err := _VMC.contract.FilterLogs(opts, "Withdraw") + if err != nil { + return nil, err + } + return &VMCWithdrawIterator{contract: _VMC.contract, event: "Withdraw", logs: logs, sub: sub}, nil +} + +// WatchWithdraw is a free log subscription operation binding the contract event 0xe13f360aa18d414ccdb598da6c447faa89d0477ffc7549dab5678fca76910b8c. +// +// Solidity: event Withdraw(validatorIndex int256) +func (_VMC *VMCFilterer) WatchWithdraw(opts *bind.WatchOpts, sink chan<- *VMCWithdraw) (event.Subscription, error) { + + logs, sub, err := _VMC.contract.WatchLogs(opts, "Withdraw") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(VMCWithdraw) + if err := _VMC.contract.UnpackLog(event, "Withdraw", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +}