diff --git a/cmd/geth/shardingcmd.go b/cmd/geth/shardingcmd.go index 9eca9a907..36400263d 100644 --- a/cmd/geth/shardingcmd.go +++ b/cmd/geth/shardingcmd.go @@ -13,6 +13,7 @@ var ( Name: "shard", Usage: "Start a sharding client", ArgsUsage: "[endpoint]", + Flags: append(consoleFlags, utils.DataDirFlag), Category: "SHARDING COMMANDS", Description: "TODO(prestonvanloon)- Add sharding client description", } diff --git a/sharding/client.go b/sharding/client.go index d73ab25d9..5fc919a7b 100644 --- a/sharding/client.go +++ b/sharding/client.go @@ -1,7 +1,9 @@ package sharding import ( + "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" @@ -15,7 +17,8 @@ const ( type Client struct { endpoint string - client *rpc.Client + client *ethclient.Client + keystore *keystore.KeyStore // Keystore containing the single signer } func MakeShardingClient(ctx *cli.Context) *Client { @@ -24,8 +27,19 @@ func MakeShardingClient(ctx *cli.Context) *Client { endpoint = ctx.GlobalString(utils.DataDirFlag.Name) } + config := &node.Config{ + DataDir: "/tmp/ethereum", + } + scryptN, scryptP, keydir, err := config.AccountConfig() + if err != nil { + panic(err) // TODO: handle this + } + + ks := keystore.NewKeyStore(keydir, scryptN, scryptP) + return &Client{ endpoint: endpoint, + keystore: ks, } } @@ -35,8 +49,8 @@ func (c *Client) Start() error { if err != nil { return err } - c.client = rpcClient - defer c.client.Close() + c.client = ethclient.NewClient(rpcClient) + defer rpcClient.Close() if err := c.verifyVMC(); err != nil { return err } diff --git a/sharding/config.go b/sharding/config.go index cc04c3cd8..9c4dc61c0 100644 --- a/sharding/config.go +++ b/sharding/config.go @@ -1,12 +1,16 @@ package sharding -import "math/big" +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) var ( // Number of network shards shardCount = 100 // Address of the validator management contract - validatorManagerAddress = "" // TODO + validatorManagerAddress = common.StringToAddress("0x315e4c3c34e27Dd28c7dCC27eC233618e76adcAc") // TODO // Gas limit for verifying signatures sigGasLimit = 40000 // Number of blocks in a period @@ -15,4 +19,8 @@ var ( lookaheadPeriods = 4 // Required deposit size in wei depositSize = new(big.Int).Exp(big.NewInt(10), big.NewInt(20), nil) // 100 ETH + // Gas limit to create contract + contractGasLimit = uint64(4700000) // Max is 4712388 + // Gas price for contract creation + contractGasPrice = new(big.Int).SetInt64(18000000000) ) diff --git a/sharding/vmc.go b/sharding/vmc.go index a40373ad2..660620ef6 100644 --- a/sharding/vmc.go +++ b/sharding/vmc.go @@ -1,8 +1,77 @@ package sharding +import ( + "context" + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" +) + +// TODO: Remove bytecode variable, reference ABI from solidity, compile solidity file. +var ( + // ABI/bytecode from https://github.com/ethereum/py-evm/blob/sharding/evm/vm/forks/sharding/contracts/validator_manager.json + abi = `[{"name": "__init__", "outputs": [], "inputs": [], "constant": false, "payable": false, "type": "constructor"}, {"name": "get_validators_max_index", "outputs": [{"type": "int128", "name": "out"}], "inputs": [], "constant": false, "payable": false, "type": "function"}, {"name": "deposit", "outputs": [{"type": "int128", "name": "out"}], "inputs": [{"type": "address", "name": "validation_code_addr"}, {"type": "address", "name": "return_addr"}], "constant": false, "payable": true, "type": "function"}, {"name": "withdraw", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "int128", "name": "validator_index"}, {"type": "bytes", "name": "sig"}], "constant": false, "payable": false, "type": "function"}, {"name": "sample", "outputs": [{"type": "address", "name": "out"}], "inputs": [{"type": "int128", "name": "shard_id"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_shard_list", "outputs": [{"type": "bool[100]", "name": "out"}], "inputs": [{"type": "address", "name": "valcode_addr"}], "constant": true, "payable": false, "type": "function"}, {"name": "add_header", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "bytes", "name": "header"}], "constant": false, "payable": false, "type": "function"}, {"name": "get_period_start_prevhash", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [{"type": "int128", "name": "expected_period_number"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_ancestor_distance", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [{"type": "bytes32", "name": "hash"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_collation_gas_limit", "outputs": [{"type": "int128", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function"}, {"name": "tx_to_shard", "outputs": [{"type": "int128", "name": "out"}], "inputs": [{"type": "address", "name": "to"}, {"type": "int128", "name": "shard_id"}, {"type": "int128", "name": "tx_startgas"}, {"type": "int128", "name": "tx_gasprice"}, {"type": "bytes", "name": "data"}], "constant": false, "payable": true, "type": "function"}, {"name": "update_gasprice", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "int128", "name": "receipt_id"}, {"type": "int128", "name": "tx_gasprice"}], "constant": false, "payable": true, "type": "function"}, {"name": "get_validators__deposit", "outputs": [{"type": "int128", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_validators__validation_code_addr", "outputs": [{"type": "address", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_validators__return_addr", "outputs": [{"type": "address", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_validators__cycle", "outputs": [{"type": "int128", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_collation_headers__parent_collation_hash", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}, {"type": "bytes32", "name": "arg1"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_collation_headers__score", "outputs": [{"type": "int128", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}, {"type": "bytes32", "name": "arg1"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_receipts__shard_id", "outputs": [{"type": "int128", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_receipts__tx_startgas", "outputs": [{"type": "int128", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_receipts__tx_gasprice", "outputs": [{"type": "int128", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_receipts__value", "outputs": [{"type": "int128", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_receipts__sender", "outputs": [{"type": "address", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_receipts__to", "outputs": [{"type": "address", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_receipts__data", "outputs": [{"type": "bytes", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_shard_head", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_num_validators", "outputs": [{"type": "int128", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function"}, {"name": "get_is_valcode_deposited", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "address", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}, {"name": "get_period_head", "outputs": [{"type": "int128", "name": "out"}], "inputs": [{"type": "int128", "name": "arg0"}], "constant": true, "payable": false, "type": "function"}]` + abiBytecode = []byte("0x600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052341561009e57600080fd5b6000600455600060075568056bc75e2d63100000600855600560095562061a80600a556005600c556064600d556064600e557fcb90a9f6d8adfb4aebc9cd10cca9000bcfa67c79a8dd2c8e47beaace688f6af3600f5573dffd41e18f04ad8810c83b14fd1426a82e625a7d601055611da856600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a05263285d43f860005114156100c85734156100ac57600080fd5b3033146100b857600080fd5b60006007541460005260206000f3005b62f4ff2d600051141561013957602060046101403734156100e857600080fd5b3033146100f457600080fd5b60605160043580604051901358578091901258575061014051600754600660c052602060c0200155600760605160018254018060405190135857809190125857815550005b63f2c5cd5e60005114156101e657341561015257600080fd5b30331461015e57600080fd5b60206101a0600463285d43f86101405261015c6000305af161017f57600080fd5b6101a051156101b2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60005260206000f35b600760605160018254038060405190135857809190125857815550600754600660c052602060c020015460005260206000f3005b632d88b2ee600051141561030b5734156101ff57600080fd5b6000610140526000610160526402540be4006402540be40060605160095480155857430580604051901358578091901258570205610180526060516007546004540180604051901358578091901258576101a0526101c06000610400818352015b6101a0516101c051121515610274576102e6565b610180516101c051600060c052602060c0200160c052602060c0205413156101405160036101c051600060c052602060c0200160c052602060c0200154141516156102d657610160606051600182510180604051901358578091901258578152505b8151600101808352811415610260575b50506060516007546101605101806040519013585780919012585760005260206000f3005b63f9609f0860005114156104c557604060046101403760043560205181101558575060243560205181101558575061014051600b60c052602060c02001541561035357600080fd5b600854341461036157600080fd5b6000610180526020610220600463285d43f86101c0526101dc6000305af161038857600080fd5b6102205115156103c05760206102a0600463f2c5cd5e6102405261025c6000305af16103b357600080fd5b6102a0516101a052610408565b6004546101a05260605160016402540be4006402540be40060605160095480155857430580604051901358578091901258570205018060405190135857809190125857610180525b6101a051600060c052602060c0200160c052602060c02061018051815534600182015561016051600282015561014051600382015550600460605160018254018060405190135857809190125857815550600161014051600b60c052602060c020015560006101a05160208261030001015260208101905080610300526103009050610140517fd0e30db03f2e24c6531d8ae2f6c09d8e7a6ad7f7e87a81cb75dfda61c9d83286825160208401a2506101a05160005260206000f3005b6313859d33600051141561078c57604060046101403734156104e657600080fd5b606051600435806040519013585780919012585750610408602435600401610180376103e860243560040135111561051d57600080fd5b7f855511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c776105c052600160006105c0516020826105e00101526020810190506101806103e8806020846105e001018260208501600060046076f1505080518201915050806105e0526105e090505160200180610a408260006105c0516020826105e00101526020810190506101806103e8806020846105e001018260208501600060046076f1505080518201915050806105e0526105e0905060006004600a8704601201f16105e857600080fd5b506020610ec0610a4051610a606000600361014051600060c052602060c0200160c052602060c0200154600a54f161061f57600080fd5b6020610ea052610ea06020600060208351038113585704602002602001810151905014610f0052610f00511561077e576000600060006000600161014051600060c052602060c0200160c052602060c0200154600261014051600060c052602060c0200160c052602060c02001546000f161069957600080fd5b6000600361014051600060c052602060c0200160c052602060c0200154600b60c052602060c020015561014051600060c052602060c0200160c052602060c020600081556000600182015560006002820155600060038201555060006000602462f4ff2d610f205261014051610f4052610f3c6000305af161071a57600080fd5b600460605160018254038060405190135857809190125857815550600061014051602082610fe001015260208101905080610fe052610fe090507f3ccfd60b2e3ddce51ab210bfb9db13577f03a21684fa35e4bcd739dd5a30bda2815160208301a1505b610f005160005260206000f3005b630b0f90d660005114156109e257602060046101403734156107ad57600080fd5b6060516004358060405190135857809190125857506402540be4006402540be4006060516009548015585743058060405190135857809190125857020561016052606051600160605160095461016051028060405190135857809190125857038060405190135857809190125857610180526000610180511215610832576000610180525b61018051610100430381125857438110155857406101a052600c5443121561085957600080fd5b6060516001606051606051600c54801558574307806040519013585780919012585743038060405190135857809190125857038060405190135857809190125857610100430381125857438110155857406101c052600d5460006101c0516020826101e0010152602081019050610140516020826101e0010152602081019050806101e0526101e09050805160208201209050066102605260206103806004632d88b2ee6103205261033c6000305af161091257600080fd5b6103805160006101a051602082610280010152602081019050610140516020826102800101526020810190506102605160208261028001015260208101905080610280526102809050805160208201209050066103a052610160516060516103a0518060405190135857809190125857600060c052602060c0200160c052602060c0205413156109ab57600060005260206000f36109e0565b60036060516103a0518060405190135857809190125857600060c052602060c0200160c052602060c020015460005260206000f35b005b632266d2246000511415610bce5760206004610140373415610a0357600080fd5b6004356020518110155857506402540be4006402540be40060605160095480155857430580604051901358578091901258570205610de0526060516001606051600954610de051028060405190135857809190125857038060405190135857809190125857610e00526000610e00511215610a7f576000610e00525b610e005161010043038112585743811015585740610e20526020610ea06004632d88b2ee610e4052610e5c6000305af1610ab857600080fd5b610ea051610ec0526000600454141515610bc557610ee060006064818352015b6000610160610ee051606481101558576020020152610f0060006064818352015b610ec0516000610e2051602082610f20010152602081019050610ee051602082610f20010152602081019050610f0051602082610f2001015260208101905080610f2052610f20905080516020820120905006610fc0526003606051610fc0518060405190135857809190125857600060c052602060c0200160c052602060c0200154610140511415610ba0576001610160610ee051606481101558576020020152610bb0565b8151600101808352811415610af9575b50508151600101808352811415610ad8575b50505b610c80610160f3005b63e2015145600051141561135b5760206004610140373415610bef57600080fd5b61102060043560040161016037611000600435600401351115610c1157600080fd5b60006111a0526126006101606114006111c0825160208401600073cb969caaad21a78a24083164ffa81604317ab603611590f150506101606111c05114610c5757600080fd5b6111c0516111c00180602001516000825180602090135857809190125857601f6101000a8204811517610c8957600080fd5b606051816020036101000a8304806040519013585780919012585790509050905081526111e0516111c00180602001516000825180602090135857809190125857601f6101000a8204811517610cde57600080fd5b606051816020036101000a8304806040519013585780919012585790509050905081602001526020611200516111c0015114610d1957600080fd5b611200516111e0015181604001526020611220516111c0015114610d3c57600080fd5b611220516111e0015181606001526020611240516111c0015114610d5f57600080fd5b611240516111e0015181608001526014611260516111c0015114610d8257600080fd5b602051611260516111d40151068160a001526020611280516111c0015114610da957600080fd5b611280516111e001518160c0015260206112a0516111c0015114610dcc57600080fd5b6112a0516111e001518160e001526112c0516111c00180602001516000825180602090135857809190125857601f6101000a8204811517610e0c57600080fd5b606051816020036101000a830480604051901358578091901258579050905090508161010001526112e0516111c00151602001808261012001826112e0516111c00160006004600a8704601201f1610e6357600080fd5b505061260051613760526126205161378052612640516137a052612660516137c052612680516137e0526126a051613800526126c051613820526126e05161384052612700516138605261272051602001806138808261272060006004600a8704601201f1610ed157600080fd5b50600e546137605112600061376051121516610eec57600080fd5b600c54431215610efb57600080fd5b6402540be4006402540be400606051600c54801558574305806040519013585780919012585702056137805114610f3157600080fd5b6060516001606051600c5461378051028060405190135857809190125857038060405190135857809190125857610100430381125857438110155857406137a05114610f7c57600080fd5b6101608051602082012090506148c05260006148c0511415610f9d57600080fd5b600060016148c05161376051600160c052602060c0200160c052602060c0200160c052602060c020015414610fd157600080fd5b60006137c05114151561101b57600060016137c05161376051600160c052602060c0200160c052602060c0200160c052602060c02001541360006137c051141761101a57600080fd5b5b6137805161376051601160c052602060c02001541261103957600080fd5b60206149606024630b0f90d66148e05261376051614900526148fc6000305af161106257600080fd5b61496051614980526111a05161498051141561108357600060005260206000f35b61016051602001806149a08261016060006004600a8704601201f16110a757600080fd5b506020615a006149a0516149c0600060105462030d40f16110c757600080fd5b60206159e0526159e060206000602083510381135857046020026020018101519050615a405260016000615a4051602082615a6001015260208101905061388061100080602084615a6001018260208501600060046101abf150508051820191505080615a6052615a6090505160200180616ac0826000615a4051602082615a6001015260208101905061388061100080602084615a6001018260208501600060046101abf150508051820191505080615a6052615a60905060006004600a8704601201f161119557600080fd5b506020617b40616ac051616ae0600061498051600a54f16111b557600080fd5b6020617b2052617b2060206000602083510381135857046020026020018101519050146111e157600080fd5b606051600160016137c05161376051600160c052602060c0200160c052602060c0200160c052602060c0200154018060405190135857809190125857617b8052617b8051613860511461123357600080fd5b6148c05161376051600160c052602060c0200160c052602060c0200160c052602060c0206137c0518155617b80516001820155506137805161376051601160c052602060c0200155600161376051600360c052602060c020015461376051600160c052602060c0200160c052602060c0200160c052602060c0200154617b805113156113415761376051600360c052602060c0200154617ba0526148c05161376051600360c052602060c02001556137c051617ba051141515611340576000617ba051602082617c0001015260208101905080617c0052617c0090506148c0517feff1a5e6aa022ec934393180ad33122384ae2f963a73502a51e41b599a213629600f54835160208501a3505b5b610160600f54815160208301a150600160005260206000f3005b63c210e6c360005114156113ef576020600461014037341561137c57600080fd5b6060516004358060405190135857809190125857506060516001606051600c5461014051028060405190135857809190125857038060405190135857809190125857610160526101605143136113d157600080fd5b610160516101004303811258574381101558574060005260206000f3005b63c2acdabb6000511415611412576020600461014037341561141057600080fd5b005b63102365b9600051141561143957341561142b57600080fd5b6298968060005260206000f3005b63ae1f858760005114156115db5760a06004610140376004356020518110155857506060516024358060405190135857809190125857506060516044358060405190135857809190125857506060516064358060405190135857809190125857506110206084356004016101e0376110006084356004013511156114bc57600080fd5b600554600260c052602060c0200160c052602060c0206101e0808260c052602060c020602082510161010060006081818352015b8261010051602002111561150357611524565b610100516020028501516101005185015581516001018083528114156114f0575b5050505050503360018201556101605160028201556101405160038201556101a051600482015561018051600582015534600682015550600554611220526005606051600182540180604051901358578091901258578155506000611220516020826112800101526020810190508061128052611280905061016051610140517ff69e76b61f12aaaf42540986e291a26daec8c3e1d6bd33e8ff492dde9998d0e2835160208501a3506112205160005260206000f3005b63f9b489b9600051141561166c57604060046101403760605160043580604051901358578091901258575060605160243580604051901358578091901258575033600161014051600260c052602060c0200160c052602060c02001541461164157600080fd5b61016051600461014051600260c052602060c0200160c052602060c0200155600160005260206000f3005b63e395dc6560005114156116c7576020600461014037341561168d57600080fd5b606051600435806040519013585780919012585750600161014051600060c052602060c0200160c052602060c020015460005260206000f3005b636b979ac1600051141561172257602060046101403734156116e857600080fd5b606051600435806040519013585780919012585750600361014051600060c052602060c0200160c052602060c020015460005260206000f3005b63d11da07e600051141561177d576020600461014037341561174357600080fd5b606051600435806040519013585780919012585750600261014051600060c052602060c0200160c052602060c020015460005260206000f3005b63c96650bf60005114156117d5576020600461014037341561179e57600080fd5b60605160043580604051901358578091901258575061014051600060c052602060c0200160c052602060c0205460005260206000f3005b63316707e1600051141561183a57604060046101403734156117f657600080fd5b6060516004358060405190135857809190125857506101605161014051600160c052602060c0200160c052602060c0200160c052602060c0205460005260206000f3005b6358882c1460005114156118a2576040600461014037341561185b57600080fd5b60605160043580604051901358578091901258575060016101605161014051600160c052602060c0200160c052602060c0200160c052602060c020015460005260206000f3005b636909fe2a60005114156118fd57602060046101403734156118c357600080fd5b606051600435806040519013585780919012585750600261014051600260c052602060c0200160c052602060c020015460005260206000f3005b63ff875bb56000511415611958576020600461014037341561191e57600080fd5b606051600435806040519013585780919012585750600561014051600260c052602060c0200160c052602060c020015460005260206000f3005b6370e896d960005114156119b3576020600461014037341561197957600080fd5b606051600435806040519013585780919012585750600461014051600260c052602060c0200160c052602060c020015460005260206000f3005b63df69a8a66000511415611a0e57602060046101403734156119d457600080fd5b606051600435806040519013585780919012585750600661014051600260c052602060c0200160c052602060c020015460005260206000f3005b638c9e6b456000511415611a695760206004610140373415611a2f57600080fd5b606051600435806040519013585780919012585750600161014051600260c052602060c0200160c052602060c020015460005260206000f3005b633d81a9446000511415611ac45760206004610140373415611a8a57600080fd5b606051600435806040519013585780919012585750600361014051600260c052602060c0200160c052602060c020015460005260206000f3005b6353a530586000511415611b895760206004610140373415611ae557600080fd5b60605160043580604051901358578091901258575061014051600260c052602060c0200160c052602060c0208060c052602060c020610180602082540161010060006081818352015b82610100516020021115611b4157611b62565b61010051850154610100516020028501528151600101808352811415611b2e575b50505050505060206101605260406101805160206001820306601f820103905001610160f3005b633741285e6000511415611bd95760206004610140373415611baa57600080fd5b60605160043580604051901358578091901258575061014051600360c052602060c020015460005260206000f3005b63aeac51cf6000511415611bff573415611bf257600080fd5b60045460005260206000f3005b6319d1861c6000511415611c465760206004610140373415611c2057600080fd5b60043560205181101558575061014051600b60c052602060c020015460005260206000f3005b63b29df8f26000511415611c965760206004610140373415611c6757600080fd5b60605160043580604051901358578091901258575061014051601160c052602060c020015460005260206000f3005b5b610111611da803610111600039610111611da8036000f3") +) + func (c *Client) verifyVMC() error { // TODO: Fetch validator manager contract. - // TODO: Assert that the contract contents/ABI are as expected. - // TODO: Upload VMC if does not exist. + b, err := c.client.CodeAt(context.Background(), validatorManagerAddress, nil) + if err != nil { + return fmt.Errorf("failed to get contract code at %s. %v", validatorManagerAddress, err) + } + + if len(b) == 0 { + log.Info(fmt.Sprintf("No validator management contract found at %s.", validatorManagerAddress.String())) + + accounts := c.keystore.Accounts() + // TODO: get password from file + if err := c.keystore.Unlock(accounts[0], "password"); err != nil { + return err + } + + suggestedGasPrice, err := c.client.SuggestGasPrice(context.Background()) + if err != nil { + return fmt.Errorf("failed to get suggested gas price from node: %v", err) + } + + nonce, err := c.client.NonceAt(context.Background(), accounts[0].Address, nil) + if err != nil { + return fmt.Errorf("failed to get nonce for %s: %v", accounts[0].Address, err) + } + + tx := types.NewContractCreation(nonce, new(big.Int).SetInt64(0), contractGasLimit, suggestedGasPrice, abiBytecode) + signed, err := c.keystore.SignTx(accounts[0], tx, new(big.Int).SetInt64(1000)) + if err != nil { + return fmt.Errorf("failed to sign transaction: %v", err) + } + + log.Info(fmt.Sprintf("Creating validator management contract. Tx: %s", signed.Hash().String())) + + if err := c.client.SendTransaction(context.Background(), signed); err != nil { + return fmt.Errorf("failed to send transaction: %v", err) + } + + log.Info(fmt.Sprintf("Contract creation sent. Waiting for transaction receipt.")) + + for pending := true; pending; _, pending, err = c.client.TransactionByHash(context.Background(), signed.Hash()) { + if err != nil { + return fmt.Errorf("Failed to get transaction by hash: %v", err) + } + time.Sleep(1 * time.Second) + } + + receipt, err := c.client.TransactionReceipt(context.Background(), signed.Hash()) + if err != nil { + return fmt.Errorf("failed to get transaction receipt: %v", err) + } + log.Info(fmt.Sprintf("Created contract at address %s", receipt.ContractAddress.String())) + } else { + // TODO: Check contract bytecode is what we expected, otherwise return error. + } + return nil }