diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 9ad40364e0..10df3530f8 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -55,7 +55,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/netutil" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/sharding" + shardparams "github.com/ethereum/go-ethereum/sharding/params" whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" "gopkg.in/urfave/cli.v1" ) @@ -536,7 +536,7 @@ var ( // Sharding Settings DepositFlag = cli.BoolFlag{ Name: "deposit", - Usage: "To become a notary in a sharding node, " + new(big.Int).Div(sharding.NotaryDeposit, new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)).String() + " ETH will be deposited into SMC", + Usage: "To become a notary in a sharding node, " + new(big.Int).Div(shardparams.DefaultShardConfig.NotaryDeposit, new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)).String() + " ETH will be deposited into SMC", } ActorFlag = cli.StringFlag{ Name: "actor", diff --git a/sharding/config.go b/sharding/config.go deleted file mode 100644 index 2f9046a3ca..0000000000 --- a/sharding/config.go +++ /dev/null @@ -1,39 +0,0 @@ -package sharding - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" -) - -var ( - // ShardCount is the number of network shards. - ShardCount = int64(100) - // ShardingManagerAddress is the address of the sharding manager contract. - ShardingManagerAddress = common.HexToAddress("0x0") // TODO - // SigGasLimit for verifying signatures. - SigGasLimit = 40000 - // PeriodLength is num of blocks in period. - PeriodLength = int64(5) - // LookaheadPeriods is the number of periods ahead of current period - // which the contract is able to return the notary of that period. - LookaheadPeriods = 4 - // NotaryDeposit is a required deposit size in wei. - NotaryDeposit = new(big.Int).Exp(big.NewInt(10), big.NewInt(21), nil) // 1000 ETH - // ProposerDeposit is a required deposit size in wei. - ProposerDeposit = new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) // 1 ETH - // MinProposerBalance of proposer where bids are deducted. - MinProposerBalance = new(big.Int).Exp(big.NewInt(10), big.NewInt(17), nil) // 0.1 ETH - // ContractGasLimit to create contract. - ContractGasLimit = uint64(4700000) // Max is 4712388. - // NotaryLockupLength to lockup notary deposit from time of deregistration. - NotaryLockupLength = int64(16128) - // ProposerLockupLength to lockup proposer deposit from time of deregistration. - ProposerLockupLength = int64(48) - // NotarySubsidy is ETH awarded to notary after collation included in canonical chain. - NotarySubsidy = new(big.Int).Exp(big.NewInt(10), big.NewInt(15), nil) // 0.001 ETH. - // NotaryCommitSize sampled per block from the notaries pool per period per shard. - NotaryCommitSize = int64(135) - // NotaryQuorumSize votes the collation needs to get accepted to the canonical chain. - NotaryQuorumSize = int64(90) -) diff --git a/sharding/config_test.go b/sharding/config_test.go deleted file mode 100644 index 0b3a028c91..0000000000 --- a/sharding/config_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package sharding - -import ( - "math/big" - "testing" -) - -func TestNotaryDeposit(t *testing.T) { - want, err := new(big.Int).SetString("1000000000000000000000", 10) // 1000 ETH - if !err { - t.Fatalf("Failed to setup test") - } - if NotaryDeposit.Cmp(want) != 0 { - t.Errorf("Notary deposit size incorrect. Wanted %d, got %d", want, NotaryDeposit) - } -} - -func TestProposerDeposit(t *testing.T) { - want, err := new(big.Int).SetString("1000000000000000000", 10) // 1 ETH - if !err { - t.Fatalf("Failed to setup test") - } - if ProposerDeposit.Cmp(want) != 0 { - t.Errorf("Proposer deposit size incorrect. Wanted %d, got %d", want, ProposerDeposit) - } -} - -func TestMinProposerBalance(t *testing.T) { - want, err := new(big.Int).SetString("100000000000000000", 10) // 0.1 ETH - if !err { - t.Fatalf("Failed to setup test") - } - if MinProposerBalance.Cmp(want) != 0 { - t.Errorf("Min proposer balance incorrect. Wanted %d, got %d", want, MinProposerBalance) - } -} - -func TestNotarySubsidy(t *testing.T) { - want, err := new(big.Int).SetString("1000000000000000", 10) // 0.001 ETH - if !err { - t.Fatalf("Failed to setup test") - } - if NotarySubsidy.Cmp(want) != 0 { - t.Errorf("Notary subsidy size incorrect. Wanted %d, got %d", want, NotarySubsidy) - } -} diff --git a/sharding/contracts/sharding_manager.go b/sharding/contracts/sharding_manager.go index a5e2024963..4142607d19 100644 --- a/sharding/contracts/sharding_manager.go +++ b/sharding/contracts/sharding_manager.go @@ -16,10 +16,10 @@ import ( ) // SMCABI is the input ABI used to generate the binding from. -const SMCABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"currentVote\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"uint256\"},{\"name\":\"_period\",\"type\":\"uint256\"},{\"name\":\"_index\",\"type\":\"uint256\"},{\"name\":\"_chunkRoot\",\"type\":\"bytes32\"}],\"name\":\"submitVote\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"deregisterNotary\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"uint256\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"hasVoted\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"uint256\"}],\"name\":\"getNotaryInCommittee\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"registerNotary\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"notaryRegistry\",\"outputs\":[{\"name\":\"deregisteredPeriod\",\"type\":\"uint256\"},{\"name\":\"poolIndex\",\"type\":\"uint256\"},{\"name\":\"balance\",\"type\":\"uint256\"},{\"name\":\"deposited\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"uint256\"},{\"name\":\"_period\",\"type\":\"uint256\"},{\"name\":\"_chunkRoot\",\"type\":\"bytes32\"}],\"name\":\"addHeader\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastSubmittedCollation\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastApprovedCollation\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"releaseNotary\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"notaryPool\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"uint256\"}],\"name\":\"getVoteCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"CHALLENGE_PERIOD\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"collationRecords\",\"outputs\":[{\"name\":\"chunkRoot\",\"type\":\"bytes32\"},{\"name\":\"proposer\",\"type\":\"address\"},{\"name\":\"isElected\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"notaryPoolLength\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"shardId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"chunkRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"period\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"proposerAddress\",\"type\":\"address\"}],\"name\":\"HeaderAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"notary\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"poolIndex\",\"type\":\"uint256\"}],\"name\":\"NotaryRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"notary\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"poolIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"deregisteredPeriod\",\"type\":\"uint256\"}],\"name\":\"NotaryDeregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"notary\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"poolIndex\",\"type\":\"uint256\"}],\"name\":\"NotaryReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"shardId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"chunkRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"period\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"notaryAddress\",\"type\":\"address\"}],\"name\":\"VoteSubmitted\",\"type\":\"event\"}]" +const SMCABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"shardCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"currentVote\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"uint256\"},{\"name\":\"_period\",\"type\":\"uint256\"},{\"name\":\"_index\",\"type\":\"uint256\"},{\"name\":\"_chunkRoot\",\"type\":\"bytes32\"}],\"name\":\"submitVote\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"deregisterNotary\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"uint256\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"hasVoted\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"uint256\"}],\"name\":\"getNotaryInCommittee\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"registerNotary\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"notaryRegistry\",\"outputs\":[{\"name\":\"deregisteredPeriod\",\"type\":\"uint256\"},{\"name\":\"poolIndex\",\"type\":\"uint256\"},{\"name\":\"balance\",\"type\":\"uint256\"},{\"name\":\"deposited\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"uint256\"},{\"name\":\"_period\",\"type\":\"uint256\"},{\"name\":\"_chunkRoot\",\"type\":\"bytes32\"}],\"name\":\"addHeader\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastSubmittedCollation\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lastApprovedCollation\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"releaseNotary\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"notaryPool\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_shardId\",\"type\":\"uint256\"}],\"name\":\"getVoteCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"CHALLENGE_PERIOD\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"collationRecords\",\"outputs\":[{\"name\":\"chunkRoot\",\"type\":\"bytes32\"},{\"name\":\"proposer\",\"type\":\"address\"},{\"name\":\"isElected\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"notaryPoolLength\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"shardId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"chunkRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"period\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"proposerAddress\",\"type\":\"address\"}],\"name\":\"HeaderAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"notary\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"poolIndex\",\"type\":\"uint256\"}],\"name\":\"NotaryRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"notary\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"poolIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"deregisteredPeriod\",\"type\":\"uint256\"}],\"name\":\"NotaryDeregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"notary\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"poolIndex\",\"type\":\"uint256\"}],\"name\":\"NotaryReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"shardId\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"chunkRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"period\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"notaryAddress\",\"type\":\"address\"}],\"name\":\"VoteSubmitted\",\"type\":\"event\"}]" // SMCBin is the compiled bytecode used for deploying new contracts. -const SMCBin = `0x608060405234801561001057600080fd5b50610d12806100206000396000f3006080604052600436106100e55763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630c8da4cc81146100ea5780634f33ffa01461011457806358377bd11461013757806364390ff11461014c578063673221af1461017b57806368e9513e146101af5780636bdd3271146101b757806375bd99121461020057806383ceeabe1461021e57806397d369a2146102365780639910851d1461024e578063a81f451014610263578063b2c2f2e81461027b578063c3a079ed14610293578063e9e0b683146102a8578063f6f67d36146102eb575b600080fd5b3480156100f657600080fd5b50610102600435610300565b60408051918252519081900360200190f35b34801561012057600080fd5b50610135600435602435604435606435610312565b005b34801561014357600080fd5b506101356104b7565b34801561015857600080fd5b506101676004356024356105e2565b604080519115158252519081900360200190f35b34801561018757600080fd5b50610193600435610605565b60408051600160a060020a039092168252519081900360200190f35b6101356106be565b3480156101c357600080fd5b506101d8600160a060020a0360043516610881565b6040805194855260208501939093528383019190915215156060830152519081900360800190f35b34801561020c57600080fd5b506101356004356024356044356108ac565b34801561022a57600080fd5b506101026004356109fe565b34801561024257600080fd5b50610102600435610a10565b34801561025a57600080fd5b50610135610a22565b34801561026f57600080fd5b50610193600435610b57565b34801561028757600080fd5b50610102600435610b7f565b34801561029f57600080fd5b50610102610b94565b3480156102b457600080fd5b506102c3600435602435610b99565b60408051938452600160a060020a039092166020840152151582820152519081900360600190f35b3480156102f757600080fd5b50610102610be3565b60036020526000908152604090205481565b60008085101580156103245750606485105b151561032f57600080fd5b60054304841461033e57600080fd5b600085815260056020526040902054841461035857600080fd5b6087831061036557600080fd5b6000858152600460209081526040808320878452909152902054821461038a57600080fd5b600160a060020a03331660009081526001602052604090206003015460ff1615156103b457600080fd5b6103be85846105e2565b156103c857600080fd5b33600160a060020a03166103db86610605565b600160a060020a0316146103ee57600080fd5b6103f88584610be9565b61040185610b7f565b9050605a8110610465576000858152600660209081526040808320879055600482528083208784529091529020600101805474ff00000000000000000000000000000000000000001916740100000000000000000000000000000000000000001790555b6040805183815260208101869052600160a060020a03331681830152905186917fc99370212b708f699fb6945a17eb34d0fc1ccd5b45d88f4d9682593a45d6e833919081900360600190a25050505050565b33600160a060020a038116600090815260016020819052604082209081015460039091015490919060ff1615156104ed57600080fd5b82600160a060020a031660008381548110151561050657fe5b600091825260209091200154600160a060020a03161461052557600080fd5b61052d610c0d565b50600160a060020a0382166000908152600160205260409020600543049081905561055782610c30565b600080548390811061056557fe5b600091825260209182902001805473ffffffffffffffffffffffffffffffffffffffff191690556002805460001901905560408051600160a060020a0386168152918201849052818101839052517f90e5afdc8fd31453dcf6e37154fa117ddf3b0324c96c65015563df9d5e4b5a759181900360600190a1505050565b60009182526003602052604090912054600160ff9290920360020a900481161490565b6000600543048180808080610618610c0d565b600b5486111561062c57600a549450610632565b60095494505b600160a060020a03331660009081526001602081815260409283902090910154825160001960058b020180408083529382018390528185018d905293519081900360600190209096509194509250859081151561068b57fe5b06905060008181548110151561069d57fe5b600091825260209091200154600160a060020a031698975050505050505050565b33600160a060020a03811660009081526001602052604081206003015460ff16156106e857600080fd5b34683635c9adc5dea00000146106fd57600080fd5b610705610c0d565b61070d610ca1565b156107705750600254600080546001810182559080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0384161790556107b9565b610778610ca8565b90508160008281548110151561078a57fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a031602179055505b600280546001908101825560408051608081018252600080825260208083018781523484860190815260608501878152600160a060020a038b168552928790529490922092518355905193820193909355905192810192909255516003909101805460ff1916911515919091179055600a5481106108395760018101600a555b60408051600160a060020a03841681526020810183905281517fa4fe15c53db34d35a5117acc26c27a2653dc68e2dadfc21ed211e38b7864d7a7929181900390910190a15050565b6001602081905260009182526040909120805491810154600282015460039092015490919060ff1684565b600083101580156108bd5750606483105b15156108c857600080fd5b6005430482146108d757600080fd5b60008381526005602052604090205482116108f157600080fd5b6108f9610c0d565b604080516060808201835283825233600160a060020a03908116602080850182815260008688018181528b8252600484528882208b8352845288822097518855915160019097018054925173ffffffffffffffffffffffffffffffffffffffff19909316979095169690961774ff000000000000000000000000000000000000000019167401000000000000000000000000000000000000000091151591909102179092558784526005808352858520439190910490556003825284842093909355835185815290810186905280840192909252915185927f2d0a86178d2fd307b47be157a766e6bee19bc26161c32f9781ee0e818636f09c928290030190a2505050565b60056020526000908152604090205481565b60066020526000908152604090205481565b33600160a060020a038116600090815260016020819052604082208082015460039091015490929160ff909116151514610a5b57600080fd5b600160a060020a0383166000908152600160205260409020541515610a7f57600080fd5b600160a060020a038316600090815260016020526040902054613f00016005430411610aaa57600080fd5b50600160a060020a0382166000818152600160208190526040808320600281018054858355938201859055849055600301805460ff191690555190929183156108fc02918491818181858888f19350505050158015610b0d573d6000803e3d6000fd5b5060408051600160a060020a03851681526020810184905281517faee20171b64b7f3360a142659094ce929970d6963dcea8c34a9bf1ece8033680929181900390910190a1505050565b6000805482908110610b6557fe5b600091825260209091200154600160a060020a0316905081565b60009081526003602052604090205460ff1690565b601981565b600460209081526000928352604080842090915290825290208054600190910154600160a060020a0381169074010000000000000000000000000000000000000000900460ff1683565b60025481565b600091825260036020526040909120805460ff9290920360020a9091176001019055565b600b546005430490811015610c2157610c2d565b600a54600955600b8190555b50565b6008546007541415610c7657600780546001810182556000919091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68801819055610c95565b806007600854815481101515610c8857fe5b6000918252602090912001555b50600880546001019055565b6008541590565b60006001600854111515610cbb57600080fd5b600880546000190190819055600780549091908110610cd657fe5b90600052602060002001549050905600a165627a7a723058206d9de811e0ed635326925823d02336844248df0e3fbe87b2758b695a8762d76b0029` +const SMCBin = `0x60806040526064600c5534801561001557600080fd5b50610d3a806100256000396000f3006080604052600436106100f05763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166304e9c77a81146100f55780630c8da4cc1461011c5780634f33ffa01461013457806358377bd11461015757806364390ff11461016c578063673221af1461019b57806368e9513e146101cf5780636bdd3271146101d757806375bd99121461022057806383ceeabe1461023e57806397d369a2146102565780639910851d1461026e578063a81f451014610283578063b2c2f2e81461029b578063c3a079ed146102b3578063e9e0b683146102c8578063f6f67d361461030b575b600080fd5b34801561010157600080fd5b5061010a610320565b60408051918252519081900360200190f35b34801561012857600080fd5b5061010a600435610326565b34801561014057600080fd5b50610155600435602435604435606435610338565b005b34801561016357600080fd5b506101556104de565b34801561017857600080fd5b50610187600435602435610609565b604080519115158252519081900360200190f35b3480156101a757600080fd5b506101b360043561062c565b60408051600160a060020a039092168252519081900360200190f35b6101556106e5565b3480156101e357600080fd5b506101f8600160a060020a03600435166108a8565b6040805194855260208501939093528383019190915215156060830152519081900360800190f35b34801561022c57600080fd5b506101556004356024356044356108d3565b34801561024a57600080fd5b5061010a600435610a26565b34801561026257600080fd5b5061010a600435610a38565b34801561027a57600080fd5b50610155610a4a565b34801561028f57600080fd5b506101b3600435610b7f565b3480156102a757600080fd5b5061010a600435610ba7565b3480156102bf57600080fd5b5061010a610bbc565b3480156102d457600080fd5b506102e3600435602435610bc1565b60408051938452600160a060020a039092166020840152151582820152519081900360600190f35b34801561031757600080fd5b5061010a610c0b565b600c5481565b60036020526000908152604090205481565b600080851015801561034b5750600c5485105b151561035657600080fd5b60054304841461036557600080fd5b600085815260056020526040902054841461037f57600080fd5b6087831061038c57600080fd5b600085815260046020908152604080832087845290915290205482146103b157600080fd5b600160a060020a03331660009081526001602052604090206003015460ff1615156103db57600080fd5b6103e58584610609565b156103ef57600080fd5b33600160a060020a03166104028661062c565b600160a060020a03161461041557600080fd5b61041f8584610c11565b61042885610ba7565b9050605a811061048c576000858152600660209081526040808320879055600482528083208784529091529020600101805474ff00000000000000000000000000000000000000001916740100000000000000000000000000000000000000001790555b6040805183815260208101869052600160a060020a03331681830152905186917fc99370212b708f699fb6945a17eb34d0fc1ccd5b45d88f4d9682593a45d6e833919081900360600190a25050505050565b33600160a060020a038116600090815260016020819052604082209081015460039091015490919060ff16151561051457600080fd5b82600160a060020a031660008381548110151561052d57fe5b600091825260209091200154600160a060020a03161461054c57600080fd5b610554610c35565b50600160a060020a0382166000908152600160205260409020600543049081905561057e82610c58565b600080548390811061058c57fe5b600091825260209182902001805473ffffffffffffffffffffffffffffffffffffffff191690556002805460001901905560408051600160a060020a0386168152918201849052818101839052517f90e5afdc8fd31453dcf6e37154fa117ddf3b0324c96c65015563df9d5e4b5a759181900360600190a1505050565b60009182526003602052604090912054600160ff9290920360020a900481161490565b600060054304818080808061063f610c35565b600b5486111561065357600a549450610659565b60095494505b600160a060020a03331660009081526001602081815260409283902090910154825160001960058b020180408083529382018390528185018d90529351908190036060019020909650919450925085908115156106b257fe5b0690506000818154811015156106c457fe5b600091825260209091200154600160a060020a031698975050505050505050565b33600160a060020a03811660009081526001602052604081206003015460ff161561070f57600080fd5b34683635c9adc5dea000001461072457600080fd5b61072c610c35565b610734610cc9565b156107975750600254600080546001810182559080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0384161790556107e0565b61079f610cd0565b9050816000828154811015156107b157fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a031602179055505b600280546001908101825560408051608081018252600080825260208083018781523484860190815260608501878152600160a060020a038b168552928790529490922092518355905193820193909355905192810192909255516003909101805460ff1916911515919091179055600a5481106108605760018101600a555b60408051600160a060020a03841681526020810183905281517fa4fe15c53db34d35a5117acc26c27a2653dc68e2dadfc21ed211e38b7864d7a7929181900390910190a15050565b6001602081905260009182526040909120805491810154600282015460039092015490919060ff1684565b600083101580156108e55750600c5483105b15156108f057600080fd5b6005430482146108ff57600080fd5b600083815260056020526040902054821161091957600080fd5b610921610c35565b604080516060808201835283825233600160a060020a03908116602080850182815260008688018181528b8252600484528882208b8352845288822097518855915160019097018054925173ffffffffffffffffffffffffffffffffffffffff19909316979095169690961774ff000000000000000000000000000000000000000019167401000000000000000000000000000000000000000091151591909102179092558784526005808352858520439190910490556003825284842093909355835185815290810186905280840192909252915185927f2d0a86178d2fd307b47be157a766e6bee19bc26161c32f9781ee0e818636f09c928290030190a2505050565b60056020526000908152604090205481565b60066020526000908152604090205481565b33600160a060020a038116600090815260016020819052604082208082015460039091015490929160ff909116151514610a8357600080fd5b600160a060020a0383166000908152600160205260409020541515610aa757600080fd5b600160a060020a038316600090815260016020526040902054613f00016005430411610ad257600080fd5b50600160a060020a0382166000818152600160208190526040808320600281018054858355938201859055849055600301805460ff191690555190929183156108fc02918491818181858888f19350505050158015610b35573d6000803e3d6000fd5b5060408051600160a060020a03851681526020810184905281517faee20171b64b7f3360a142659094ce929970d6963dcea8c34a9bf1ece8033680929181900390910190a1505050565b6000805482908110610b8d57fe5b600091825260209091200154600160a060020a0316905081565b60009081526003602052604090205460ff1690565b601981565b600460209081526000928352604080842090915290825290208054600190910154600160a060020a0381169074010000000000000000000000000000000000000000900460ff1683565b60025481565b600091825260036020526040909120805460ff9290920360020a9091176001019055565b600b546005430490811015610c4957610c55565b600a54600955600b8190555b50565b6008546007541415610c9e57600780546001810182556000919091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68801819055610cbd565b806007600854815481101515610cb057fe5b6000918252602090912001555b50600880546001019055565b6008541590565b60006001600854111515610ce357600080fd5b600880546000190190819055600780549091908110610cfe57fe5b90600052602060002001549050905600a165627a7a72305820637e3cb0143a9d0efab2139cbc9625b0ae7ce3ac8a9c89cb2a62c393aaecf5260029` // DeploySMC deploys a new Ethereum contract, binding an instance of SMC to it. func DeploySMC(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SMC, error) { @@ -494,6 +494,32 @@ func (_SMC *SMCCallerSession) NotaryRegistry(arg0 common.Address) (struct { return _SMC.Contract.NotaryRegistry(&_SMC.CallOpts, arg0) } +// ShardCount is a free data retrieval call binding the contract method 0x04e9c77a. +// +// Solidity: function shardCount() constant returns(uint256) +func (_SMC *SMCCaller) ShardCount(opts *bind.CallOpts) (*big.Int, error) { + var ( + ret0 = new(*big.Int) + ) + out := ret0 + err := _SMC.contract.Call(opts, out, "shardCount") + return *ret0, err +} + +// ShardCount is a free data retrieval call binding the contract method 0x04e9c77a. +// +// Solidity: function shardCount() constant returns(uint256) +func (_SMC *SMCSession) ShardCount() (*big.Int, error) { + return _SMC.Contract.ShardCount(&_SMC.CallOpts) +} + +// ShardCount is a free data retrieval call binding the contract method 0x04e9c77a. +// +// Solidity: function shardCount() constant returns(uint256) +func (_SMC *SMCCallerSession) ShardCount() (*big.Int, error) { + return _SMC.Contract.ShardCount(&_SMC.CallOpts) +} + // AddHeader is a paid mutator transaction binding the contract method 0x75bd9912. // // Solidity: function addHeader(_shardId uint256, _period uint256, _chunkRoot bytes32) returns() diff --git a/sharding/contracts/sharding_manager.sol b/sharding/contracts/sharding_manager.sol index b52f1f3da3..6dcc843df3 100644 --- a/sharding/contracts/sharding_manager.sol +++ b/sharding/contracts/sharding_manager.sol @@ -50,26 +50,26 @@ contract SMC { uint nextPeriodNotarySampleSize; uint sampleSizeLastUpdatedPeriod; + // Number of shards + // TODO: Setting default as 100. This will be a dynamic when we introduce random beacon + uint public shardCount = 100; + // Constant values // Length of challenge period for notary's proof of custody uint public constant CHALLENGE_PERIOD = 25; // Number of blocks per period uint constant PERIOD_LENGTH = 5; - // Number of shards - uint constant SHARD_COUNT = 100; // The minimum deposit size for a notary uint constant NOTARY_DEPOSIT = 1000 ether; - // The reward for notary on voting for a collation - uint constant NOTARY_REWARD = 0.001 ether; // Time the ether is locked by notaries uint constant NOTARY_LOCKUP_LENGTH = 16128; - // Number of periods ahead of current period, which the contract - // is able to return the notary of that period - uint constant LOOKAHEAD_LENGTH = 4; // Number of notaries to select from notary pool for each shard in each period uint constant COMMITTEE_SIZE = 135; // Threshold(number of notaries in committee) for a proposal to be accepted uint constant QUORUM_SIZE = 90; + // Number of periods ahead of current period, which the contract + // is able to return the notary of that period + uint constant LOOKAHEAD_LENGTH = 4; /// Checks if a notary with given shard id and period has been chosen as /// a committee member to vote for header added on to the main chain @@ -172,7 +172,7 @@ contract SMC { uint _period, bytes32 _chunkRoot ) public { - require((_shardId >= 0) && (_shardId < SHARD_COUNT)); + require((_shardId >= 0) && (_shardId < shardCount)); require(_period == block.number / PERIOD_LENGTH); require(_period > lastSubmittedCollation[_shardId]); @@ -198,7 +198,7 @@ contract SMC { uint _index, bytes32 _chunkRoot ) public { - require((_shardId >= 0) && (_shardId < SHARD_COUNT)); + require((_shardId >= 0) && (_shardId < shardCount)); require(_period == block.number / PERIOD_LENGTH); require(_period == lastSubmittedCollation[_shardId]); require(_index < COMMITTEE_SIZE); diff --git a/sharding/contracts/sharding_manager_test.go b/sharding/contracts/sharding_manager_test.go index ed94bf954e..a75a62c908 100644 --- a/sharding/contracts/sharding_manager_test.go +++ b/sharding/contracts/sharding_manager_test.go @@ -13,7 +13,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/sharding" + "github.com/ethereum/go-ethereum/sharding/params" ) type smcTestHelper struct { @@ -68,7 +68,7 @@ func deploySMCContract(backend *backends.SimulatedBackend, key *ecdsa.PrivateKey // fastForward is a helper function to skip through n period. func (s *smcTestHelper) fastForward(p int) { - for i := 0; i < p*int(sharding.PeriodLength); i++ { + for i := 0; i < p*int(params.DefaultShardConfig.PeriodLength); i++ { s.backend.Commit() } } @@ -168,7 +168,7 @@ func (s *smcTestHelper) addHeader(a *testAccount, shard *big.Int, period *big.In // Filter SMC logs by headerAdded. shardIndex := []*big.Int{shard} - logPeriod := uint64(period.Int64() * sharding.PeriodLength) + logPeriod := uint64(period.Int64() * params.DefaultShardConfig.PeriodLength) log, err := s.smc.FilterHeaderAdded(&bind.FilterOpts{Start: logPeriod}, shardIndex) if err != nil { return err @@ -200,7 +200,7 @@ func (s *smcTestHelper) submitVote(a *testAccount, shard *big.Int, period *big.I } // Filter SMC logs by submitVote. shardIndex := []*big.Int{shard} - logPeriod := uint64(period.Int64() * sharding.PeriodLength) + logPeriod := uint64(period.Int64() * params.DefaultShardConfig.PeriodLength) log, err := s.smc.FilterVoteSubmitted(&bind.FilterOpts{Start: logPeriod}, shardIndex) if err != nil { return err @@ -377,7 +377,7 @@ func TestNotaryRelease(t *testing.T) { } // Fast forward until lockup ends. - s.fastForward(int(sharding.NotaryLockupLength + 1)) + s.fastForward(int(params.DefaultShardConfig.NotaryLockupLength + 1)) // Notary 0 releases. _, err = s.smc.ReleaseNotary(s.testAccounts[0].txOpts) diff --git a/sharding/mainchain/smc_client.go b/sharding/mainchain/smc_client.go index 1010750f09..cd16dc7ed1 100644 --- a/sharding/mainchain/smc_client.go +++ b/sharding/mainchain/smc_client.go @@ -43,6 +43,7 @@ type Client interface { SetDepositFlag(deposit bool) DataDirPath() string Sign(hash common.Hash) ([]byte, error) + GetShardCount() (int64, error) } // SMCClient defines a struct that interacts with a @@ -225,3 +226,13 @@ func (s *SMCClient) Sign(hash common.Hash) ([]byte, error) { account := s.Account() return s.keystore.SignHash(*account, hash.Bytes()) } + +// GetShardCount gets the count of the total shards +// currently operating in the sharded universe. +func (s *SMCClient) GetShardCount() (int64, error) { + shardCount, err := s.SMCCaller().ShardCount(&bind.CallOpts{}) + if err != nil { + return 0, err + } + return shardCount.Int64(), nil +} diff --git a/sharding/mainchain/utils.go b/sharding/mainchain/utils.go index de9ae98e11..33467a95c5 100644 --- a/sharding/mainchain/utils.go +++ b/sharding/mainchain/utils.go @@ -9,8 +9,8 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/sharding" "github.com/ethereum/go-ethereum/sharding/contracts" + "github.com/ethereum/go-ethereum/sharding/params" ) // dialRPC endpoint to node. @@ -24,16 +24,16 @@ func dialRPC(endpoint string) (*rpc.Client, error) { // initSMC initializes the sharding manager contract bindings. // If the SMC does not exist, it will be deployed. func initSMC(s *SMCClient) (*contracts.SMC, error) { - b, err := s.client.CodeAt(context.Background(), sharding.ShardingManagerAddress, nil) + b, err := s.client.CodeAt(context.Background(), params.DefaultShardConfig.SMCAddress, nil) if err != nil { - return nil, fmt.Errorf("unable to get contract code at %s: %v", sharding.ShardingManagerAddress.Hex(), err) + return nil, fmt.Errorf("unable to get contract code at %s: %v", params.DefaultShardConfig.SMCAddress.Hex(), err) } // Deploy SMC for development only. // TODO: Separate contract deployment from the sharding node. It would only need to be deployed // once on the mainnet, so this code would not need to ship with the node. if len(b) == 0 { - log.Info(fmt.Sprintf("No sharding manager contract found at %s. Deploying new contract.", sharding.ShardingManagerAddress.Hex())) + log.Info(fmt.Sprintf("No sharding manager contract found at %s. Deploying new contract.", params.DefaultShardConfig.SMCAddress.Hex())) txOps, err := s.CreateTXOpts(big.NewInt(0)) if err != nil { @@ -56,5 +56,5 @@ func initSMC(s *SMCClient) (*contracts.SMC, error) { return contract, nil } - return contracts.NewSMC(sharding.ShardingManagerAddress, s.client) + return contracts.NewSMC(params.DefaultShardConfig.SMCAddress, s.client) } diff --git a/sharding/node/backend.go b/sharding/node/backend.go index 819e886d68..7ebd7dccf8 100644 --- a/sharding/node/backend.go +++ b/sharding/node/backend.go @@ -29,7 +29,7 @@ import ( "github.com/ethereum/go-ethereum/sharding/database" "github.com/ethereum/go-ethereum/sharding/params" "github.com/ethereum/go-ethereum/sharding/txpool" - cli "gopkg.in/urfave/cli.v1" + "gopkg.in/urfave/cli.v1" ) const shardChainDbName = "shardchaindata" @@ -38,7 +38,7 @@ const shardChainDbName = "shardchaindata" // it contains APIs and fields that handle the different components of the sharded // Ethereum network. type ShardEthereum struct { - shardConfig *params.ShardConfig // Holds necessary information to configure shards. + shardConfig *params.ShardConfig // Holds necessary information to configure shard node. txPool *txpool.ShardTXPool // Defines the sharding-specific txpool. To be designed. actor sharding.Actor // Either notary, proposer, or observer. shardChainDb ethdb.Database // Access to the persistent db to store shard data. @@ -89,6 +89,9 @@ func New(ctx *cli.Context) (*ShardEthereum, error) { // Adds the initialized SMCClient to the ShardEthereum instance. shardEthereum.smcClient = smcClient + // Configure shardConfig by loading the default. + shardEthereum.shardConfig = params.DefaultShardConfig + // Adds the initialized shardChainDb to the ShardEthereum instance. shardEthereum.shardChainDb = shardChainDb @@ -100,7 +103,7 @@ func New(ctx *cli.Context) (*ShardEthereum, error) { return nil, err } - if err := shardEthereum.registerActorService(actorFlag, shardIDFlag); err != nil { + if err := shardEthereum.registerActorService(shardEthereum.shardConfig, actorFlag, shardIDFlag); err != nil { return nil, err } @@ -210,18 +213,18 @@ func (s *ShardEthereum) registerTXPool(actor string) error { } // Registers the actor according to CLI flags. Either notary/proposer/observer. -func (s *ShardEthereum) registerActorService(actor string, shardID int) error { +func (s *ShardEthereum) registerActorService(config *params.ShardConfig, actor string, shardID int) error { return s.Register(func(ctx *sharding.ServiceContext) (sharding.Service, error) { var p2p *shardp2p.Server ctx.RetrieveService(&p2p) if actor == "notary" { - return notary.NewNotary(s.smcClient, p2p, s.shardChainDb) + return notary.NewNotary(config, s.smcClient, p2p, s.shardChainDb) } else if actor == "proposer" { var txPool *txpool.ShardTXPool ctx.RetrieveService(&txPool) - return proposer.NewProposer(s.smcClient, p2p, txPool, s.shardChainDb, shardID) + return proposer.NewProposer(config, s.smcClient, p2p, txPool, s.shardChainDb, shardID) } return observer.NewObserver(p2p, s.shardChainDb, shardID) }) diff --git a/sharding/notary/notary.go b/sharding/notary/notary.go index 3b1a2c30a4..012f8f82d9 100644 --- a/sharding/notary/notary.go +++ b/sharding/notary/notary.go @@ -10,8 +10,8 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/sharding" "github.com/ethereum/go-ethereum/sharding/mainchain" + sparams "github.com/ethereum/go-ethereum/sharding/params" ) // SubscribeBlockHeaders checks incoming block headers and determines if @@ -55,7 +55,11 @@ func subscribeBlockHeaders(client mainchain.Client) error { // conditions are met. func checkSMCForNotary(client mainchain.Client, head *types.Header) error { log.Info("Checking if we are an eligible collation notary for a shard...") - for s := int64(0); s < sharding.ShardCount; s++ { + shardCount, err := client.GetShardCount() + if err != nil { + return fmt.Errorf("can't get shard count from smc: %v", err) + } + for s := int64(0); s < shardCount; s++ { // Checks if we are an eligible notary according to the SMC. addr, err := client.SMCCaller().GetNotaryInCommittee(&bind.CallOpts{}, big.NewInt(s)) @@ -132,7 +136,7 @@ func submitCollation(shardID int64) error { // joinNotaryPool checks if the deposit flag is true and the account is a // notary in the SMC. If the account is not in the set, it will deposit ETH // into contract. -func joinNotaryPool(client mainchain.Client) error { +func joinNotaryPool(config *sparams.ShardConfig, client mainchain.Client) error { if !client.DepositFlag() { return errors.New("joinNotaryPool called when deposit flag was not set") } @@ -142,7 +146,7 @@ func joinNotaryPool(client mainchain.Client) error { } log.Info("Joining notary pool") - txOps, err := client.CreateTXOpts(sharding.NotaryDeposit) + txOps, err := client.CreateTXOpts(config.NotaryDeposit) if err != nil { return fmt.Errorf("unable to initiate the deposit transaction: %v", err) } @@ -151,7 +155,7 @@ func joinNotaryPool(client mainchain.Client) error { if err != nil { return fmt.Errorf("unable to deposit eth and become a notary: %v", err) } - log.Info(fmt.Sprintf("Deposited %dETH into contract with transaction hash: %s", new(big.Int).Div(sharding.NotaryDeposit, big.NewInt(params.Ether)), tx.Hash().String())) + log.Info(fmt.Sprintf("Deposited %dETH into contract with transaction hash: %s", new(big.Int).Div(config.NotaryDeposit, big.NewInt(params.Ether)), tx.Hash().String())) return nil } diff --git a/sharding/notary/service.go b/sharding/notary/service.go index 68185fd5cc..c9d471c6d5 100644 --- a/sharding/notary/service.go +++ b/sharding/notary/service.go @@ -9,20 +9,22 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/sharding" "github.com/ethereum/go-ethereum/sharding/mainchain" + "github.com/ethereum/go-ethereum/sharding/params" ) // Notary holds functionality required to run a collation notary // in a sharded system. Must satisfy the Service interface defined in // sharding/service.go. type Notary struct { + config *params.ShardConfig smcClient *mainchain.SMCClient shardp2p sharding.ShardP2P shardChainDb ethdb.Database } // NewNotary creates a new notary instance. -func NewNotary(smcClient *mainchain.SMCClient, shardp2p sharding.ShardP2P, shardChainDb ethdb.Database) (*Notary, error) { - return &Notary{smcClient, shardp2p, shardChainDb}, nil +func NewNotary(config *params.ShardConfig, smcClient *mainchain.SMCClient, shardp2p sharding.ShardP2P, shardChainDb ethdb.Database) (*Notary, error) { + return &Notary{config, smcClient, shardp2p, shardChainDb}, nil } // Start the main routine for a notary. @@ -41,7 +43,7 @@ func (n *Notary) notarizeCollations() { // TODO: handle this better through goroutines. Right now, these methods // are blocking. if n.smcClient.DepositFlag() { - if err := joinNotaryPool(n.smcClient); err != nil { + if err := joinNotaryPool(n.config, n.smcClient); err != nil { log.Error(fmt.Sprintf("Could not fetch current block number: %v", err)) return } diff --git a/sharding/notary/service_test.go b/sharding/notary/service_test.go index 4b15ecb886..da48c7aa38 100644 --- a/sharding/notary/service_test.go +++ b/sharding/notary/service_test.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/sharding" "github.com/ethereum/go-ethereum/sharding/contracts" + "github.com/ethereum/go-ethereum/sharding/params" cli "gopkg.in/urfave/cli.v1" ) @@ -93,6 +94,10 @@ func (s *smcClient) DataDirPath() string { return "/tmp/datadir" } +func (s *smcClient) GetShardCount() (int64, error) { + return 100, nil +} + // Helper/setup methods. // TODO: consider moving these to common sharding testing package as the notary and smc tests // use them. @@ -122,7 +127,7 @@ func TestIsAccountInNotaryPool(t *testing.T) { txOpts := transactOpts() // deposit in notary pool, then it should return true. - txOpts.Value = sharding.NotaryDeposit + txOpts.Value = params.DefaultShardConfig.NotaryDeposit if _, err := smc.RegisterNotary(txOpts); err != nil { t.Fatalf("Failed to deposit: %v", err) } @@ -138,7 +143,7 @@ func TestIsAccountInNotaryPool(t *testing.T) { func TestJoinNotaryPool(t *testing.T) { backend, smc := setup() - client := &smcClient{smc: smc, depositFlag: false, t: t} + client := &smcClient{smc: smc, t: t} // There should be no notary initially. numNotaries, err := smc.NotaryPoolLength(&bind.CallOpts{}) if err != nil { @@ -149,13 +154,13 @@ func TestJoinNotaryPool(t *testing.T) { } client.SetDepositFlag(false) - err = joinNotaryPool(client) + err = joinNotaryPool(params.DefaultShardConfig, client) if err == nil { t.Error("Joined notary pool while --deposit was not present") } client.SetDepositFlag(true) - err = joinNotaryPool(client) + err = joinNotaryPool(params.DefaultShardConfig, client) if err != nil { t.Fatal(err) } @@ -171,7 +176,7 @@ func TestJoinNotaryPool(t *testing.T) { } // Trying to join while deposited should do nothing - err = joinNotaryPool(client) + err = joinNotaryPool(params.DefaultShardConfig, client) if err != nil { t.Error(err) } diff --git a/sharding/p2p/feed.go b/sharding/p2p/feed.go new file mode 100644 index 0000000000..66e27ca97a --- /dev/null +++ b/sharding/p2p/feed.go @@ -0,0 +1,33 @@ +package p2p + +import ( + "reflect" + + "github.com/ethereum/go-ethereum/event" +) + +// P2P feed is a one to many subscription feed of the argument type. +// +// Messages received via p2p protocol are sent to subscribers by these event +// feeds. Message consumers should not use event feeds to reply to or broadcast +// messages. The p2p server will not relay them to peers. Rather, use the +// Send() or Broadcast() method on p2p.Server. +// +// Event feeds from p2p will always be of type p2p.Message. The message +// contains information about the sender, aka the peer, and the message payload +// itself. +// +// feed, err := ps.Feed(MyMessage{}) +// ch := make(chan p2p.Message, 100) // Choose a reasonable buffer size! +// sub := feed.Subscribe(ch) +// +// // Wait until my message comes from a peer. +// msg := <- ch +// fmt.Printf("Message received: %v", msg.Data) +func (s *Server) Feed(msg interface{}) (*event.Feed, error) { + t := reflect.TypeOf(msg) + if s.feeds[t] == nil { + s.feeds[t] = new(event.Feed) + } + return s.feeds[t], nil +} diff --git a/sharding/p2p/feed_example_test.go b/sharding/p2p/feed_example_test.go new file mode 100644 index 0000000000..c0eca05363 --- /dev/null +++ b/sharding/p2p/feed_example_test.go @@ -0,0 +1,46 @@ +package p2p + +import "fmt" + +// Feeds can be use to subscribe to any type of message. +func ExampleServer_Feed() { + s, err := NewServer() + if err != nil { + panic(err) + } + + // Let's wait for a puzzle from our peers then try to solve it. + type Puzzle struct { + Challenge string + Answer string + } + + feed, err := s.Feed(Puzzle{}) + if err != nil { + // This shouldn't happen, but we should handle it anyway. + panic(err) + } + + ch := make(chan Message, 5) // Small buffer size. I don't expect many puzzles. + sub := feed.Subscribe(ch) + + // Always close these resources. + defer sub.Unsubscribe() + defer close(ch) + + // Wait until we have a puzzle to solve. + msg := <-ch + puzzle, ok := msg.Data.(Puzzle) + + if !ok { + panic("Received a message that wasn't a puzzle!") + } + + fmt.Printf("Received puzzle %s from peer %v\n", puzzle, msg.Peer) + + if puzzle.Answer == "fourteen" { + fmt.Println("I solved the puzzle!") + } else { + fmt.Println("The answer isn't \"fourteen\"... giving up") + } +} diff --git a/sharding/p2p/feed_test.go b/sharding/p2p/feed_test.go new file mode 100644 index 0000000000..1917b83250 --- /dev/null +++ b/sharding/p2p/feed_test.go @@ -0,0 +1,33 @@ +package p2p + +import "testing" + +func TestFeed_ReturnsSameFeed(t *testing.T) { + tests := []struct { + a interface{} + b interface{} + want bool + }{ + // Equality tests + {a: 1, b: 2, want: true}, + {a: 'a', b: 'b', want: true}, + {a: struct{ c int }{c: 1}, b: struct{ c int }{c: 2}, want: true}, + {a: struct{ c string }{c: "a"}, b: struct{ c string }{c: "b"}, want: true}, + // Inequality tests + {a: 1, b: '2', want: false}, + {a: 'a', b: 1, want: false}, + {a: struct{ c int }{c: 1}, b: struct{ c int64 }{c: 2}, want: false}, + {a: struct{ c string }{c: "a"}, b: struct{ c float64 }{c: 3.4}, want: false}, + } + + s, _ := NewServer() + + for _, tt := range tests { + feed1, _ := s.Feed(tt.a) + feed2, _ := s.Feed(tt.b) + + if (feed1 == feed2) != tt.want { + t.Errorf("Expected %v == %v to be %t", feed1, feed2, tt.want) + } + } +} diff --git a/sharding/p2p/message.go b/sharding/p2p/message.go new file mode 100644 index 0000000000..aea4e1a86a --- /dev/null +++ b/sharding/p2p/message.go @@ -0,0 +1,9 @@ +package p2p + +// Message represents a message received from an external peer. +type Message struct { + // Peer represents the sender of the message. + Peer Peer + // Data can be any type of message found in sharding/p2p/messages package. + Data interface{} +} diff --git a/sharding/p2p/peer.go b/sharding/p2p/peer.go new file mode 100644 index 0000000000..c089e82ded --- /dev/null +++ b/sharding/p2p/peer.go @@ -0,0 +1,7 @@ +package p2p + +// Peer +// TODO - Design and implement. +// See design doc: https://docs.google.com/document/d/1cthKuGPreOSQH96Ujt7sArcT-IRICk6b-QcdD0EnLsI/edit +// https://github.com/prysmaticlabs/geth-sharding/issues/175 +type Peer struct{} diff --git a/sharding/p2p/service.go b/sharding/p2p/service.go index e9bc0505ca..b73b7580b8 100644 --- a/sharding/p2p/service.go +++ b/sharding/p2p/service.go @@ -2,24 +2,43 @@ package p2p import ( + "reflect" + + "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" ) -// Server is a placeholder for a shardp2p service. To be designed. -type Server struct{} - -// NewServer creates a new shardp2p service instance. -func NewServer() (*Server, error) { - return &Server{}, nil +// Server is a placeholder for a p2p service. To be designed. +type Server struct { + feeds map[reflect.Type]*event.Feed } -// Start the main routine for an shardp2p server. +// NewServer creates a new p2p server instance. +func NewServer() (*Server, error) { + return &Server{ + feeds: make(map[reflect.Type]*event.Feed), + }, nil +} + +// Start the main routine for an p2p server. func (s *Server) Start() { log.Info("Starting shardp2p server") } -// Stop the main shardp2p loop.. +// Stop the main p2p loop. func (s *Server) Stop() error { log.Info("Stopping shardp2p server") return nil } + +// Send a message to a specific peer. +func (s *Server) Send(msg interface{}, peer Peer) { + // TODO + // https://github.com/prysmaticlabs/geth-sharding/issues/175 +} + +// Broadcast a message to the world. +func (s *Server) Broadcast(msg interface{}) { + // TODO + // https://github.com/prysmaticlabs/geth-sharding/issues/176 +} diff --git a/sharding/p2p/service_test.go b/sharding/p2p/service_test.go index 87d8695a9a..af60b61caf 100644 --- a/sharding/p2p/service_test.go +++ b/sharding/p2p/service_test.go @@ -1,6 +1,8 @@ package p2p -import "github.com/ethereum/go-ethereum/sharding" +import ( + "github.com/ethereum/go-ethereum/sharding" +) // Verifies that Server implements the ShardP2P interface. var _ = sharding.ShardP2P(&Server{}) diff --git a/sharding/params/chainConfig.go b/sharding/params/chainConfig.go deleted file mode 100644 index 7f84b4f7bd..0000000000 --- a/sharding/params/chainConfig.go +++ /dev/null @@ -1,10 +0,0 @@ -// Package params defines important configuration options to be used when instantiating -// objects within the sharding package. For example, it defines objects such as a -// ShardConfig that will be useful when creating new shard instances. -package params - -import "github.com/ethereum/go-ethereum/common" - -type ShardConfig struct { - SMCAddress common.Address -} diff --git a/sharding/params/config.go b/sharding/params/config.go new file mode 100644 index 0000000000..748f93d444 --- /dev/null +++ b/sharding/params/config.go @@ -0,0 +1,40 @@ +// Package params defines important configuration options to be used when instantiating +// objects within the sharding package. For example, it defines objects such as a +// ShardConfig that will be useful when creating new shard instances. +package params + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +// DefaultShardConfig contains default configs for node to use in the sharded universe +var DefaultShardConfig = &ShardConfig{ + SMCAddress: common.HexToAddress("0x0"), + PeriodLength: 5, + NotaryDeposit: new(big.Int).Exp(big.NewInt(10), big.NewInt(21), nil), // 1000 ETH + NotaryLockupLength: 16128, + ProposerLockupLength: 48, + NotaryCommitteeSize: 135, + NotaryQuorumSize: 90, + NotaryChallengePeriod: 25, +} + +// DefaultShardChainConfig contains default chain configs of an individual shard. +var DefaultShardChainConfig = &ShardChainConfig{} + +// ShardConfig contains configs for node to participate in the sharded universe. +type ShardConfig struct { + SMCAddress common.Address // SMCAddress is the address of SMC in mainchain. + PeriodLength int64 // PeriodLength is num of blocks in period. + NotaryDeposit *big.Int // NotaryDeposit is a required deposit size in wei. + NotaryLockupLength int64 // NotaryLockupLength to lockup notary deposit from time of deregistration. + ProposerLockupLength int64 // ProposerLockupLength to lockup proposer deposit from time of deregistration. + NotaryCommitteeSize int64 // NotaryCommitSize sampled per block from the notaries pool per period per shard. + NotaryQuorumSize int64 // NotaryQuorumSize votes the collation needs to get accepted to the canonical chain. + NotaryChallengePeriod int64 // NotaryChallengePeriod is the duration a notary has to store collations for. +} + +// ShardChainConfig contains chain config of an individual shard. Still to be designed. +type ShardChainConfig struct{} diff --git a/sharding/params/config_test.go b/sharding/params/config_test.go new file mode 100644 index 0000000000..b83fccd508 --- /dev/null +++ b/sharding/params/config_test.go @@ -0,0 +1,52 @@ +package params + +import ( + "math/big" + "testing" +) + +func TestNotaryDeposit(t *testing.T) { + want, err := new(big.Int).SetString("1000000000000000000000", 10) // 1000 ETH + if !err { + t.Fatalf("Failed to setup test") + } + if DefaultShardConfig.NotaryDeposit.Cmp(want) != 0 { + t.Errorf("Notary deposit size incorrect. Wanted %d, got %d", want, DefaultShardConfig.NotaryDeposit) + } +} + +func TestPeriodLength(t *testing.T) { + if DefaultShardConfig.PeriodLength != 5 { + t.Errorf("Shard count incorrect. Wanted %d, got %d", 5, DefaultShardConfig.PeriodLength) + } +} + +func TestNotaryLockupLength(t *testing.T) { + if DefaultShardConfig.NotaryLockupLength != 16128 { + t.Errorf("Shard count incorrect. Wanted %d, got %d", 16128, DefaultShardConfig.NotaryLockupLength) + } +} + +func TestProposerLockupLength(t *testing.T) { + if DefaultShardConfig.ProposerLockupLength != 48 { + t.Errorf("Shard count incorrect. Wanted %d, got %d", 48, DefaultShardConfig.ProposerLockupLength) + } +} + +func TestNotaryCommitteeSize(t *testing.T) { + if DefaultShardConfig.NotaryCommitteeSize != 135 { + t.Errorf("Shard count incorrect. Wanted %d, got %d", 135, DefaultShardConfig.NotaryCommitteeSize) + } +} + +func TestNotaryQuorumSize(t *testing.T) { + if DefaultShardConfig.NotaryQuorumSize != 90 { + t.Errorf("Shard count incorrect. Wanted %d, got %d", 90, DefaultShardConfig.NotaryQuorumSize) + } +} + +func TestNotaryChallengePeriod(t *testing.T) { + if DefaultShardConfig.NotaryChallengePeriod != 25 { + t.Errorf("Shard count incorrect. Wanted %d, got %d", 25, DefaultShardConfig.NotaryChallengePeriod) + } +} diff --git a/sharding/proposer/proposer.go b/sharding/proposer/proposer.go index f87335bc38..aaf56df4b5 100644 --- a/sharding/proposer/proposer.go +++ b/sharding/proposer/proposer.go @@ -15,14 +15,18 @@ import ( // and body. Header consists of shardID, ChunkRoot, period, // proposer addr and signatures. Body contains serialized blob // of a collations transactions. -func createCollation(client mainchain.Client, shardId *big.Int, period *big.Int, txs []*types.Transaction) (*sharding.Collation, error) { +func createCollation(client mainchain.Client, shardID *big.Int, period *big.Int, txs []*types.Transaction) (*sharding.Collation, error) { // shardId has to be within range - if shardId.Cmp(big.NewInt(0)) < 0 || shardId.Cmp(big.NewInt(sharding.ShardCount)) > 0 { - return nil, fmt.Errorf("can't create collation for shard %v. Must be between 0 and %v", shardId, sharding.ShardCount) + shardCount, err := client.GetShardCount() + if err != nil { + return nil, fmt.Errorf("can't get shard count from smc: %v", err) + } + if shardID.Cmp(big.NewInt(0)) < 0 || shardID.Cmp(big.NewInt(shardCount)) > 0 { + return nil, fmt.Errorf("can't create collation for shard %v. Must be between 0 and %v", shardID, shardCount) } // check with SMC to see if we can add the header. - if a, _ := checkHeaderAdded(client, shardId, period); !a { + if a, _ := checkHeaderAdded(client, shardID, period); !a { return nil, fmt.Errorf("can't create collation, collation with same period has already been added") } @@ -34,7 +38,7 @@ func createCollation(client mainchain.Client, shardId *big.Int, period *big.Int, // construct the header, leave chunkRoot and signature fields empty, to be filled later. addr := client.Account().Address - header := sharding.NewCollationHeader(shardId, nil, period, &addr, nil) + header := sharding.NewCollationHeader(shardID, nil, period, &addr, nil) // construct the body with header, blobs(serialized txs) and txs. collation := sharding.NewCollation(header, blobs, txs) @@ -78,9 +82,9 @@ func addHeader(client mainchain.Client, collation *sharding.Collation) error { // submitted to the main chain. There can only be one header per shard // per period, proposer should check if a header's already submitted, // checkHeaderAdded returns true if it's available, false if it's unavailable. -func checkHeaderAdded(client mainchain.Client, shardId *big.Int, period *big.Int) (bool, error) { +func checkHeaderAdded(client mainchain.Client, shardID *big.Int, period *big.Int) (bool, error) { // Get the period of the last header. - lastPeriod, err := client.SMCCaller().LastSubmittedCollation(&bind.CallOpts{}, shardId) + lastPeriod, err := client.SMCCaller().LastSubmittedCollation(&bind.CallOpts{}, shardID) if err != nil { return false, fmt.Errorf("unable to get the period of last submitted collation: %v", err) } diff --git a/sharding/proposer/service.go b/sharding/proposer/service.go index f8af2252b9..0a3da4adf4 100644 --- a/sharding/proposer/service.go +++ b/sharding/proposer/service.go @@ -14,12 +14,14 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/sharding" "github.com/ethereum/go-ethereum/sharding/mainchain" + "github.com/ethereum/go-ethereum/sharding/params" ) // Proposer holds functionality required to run a collation proposer // in a sharded system. Must satisfy the Service interface defined in // sharding/service.go. type Proposer struct { + config *params.ShardConfig client *mainchain.SMCClient shardp2p sharding.ShardP2P txpool sharding.TXPool @@ -30,8 +32,8 @@ type Proposer struct { // NewProposer creates a struct instance of a proposer service. // It will have access to a mainchain client, a shardp2p network, // and a shard transaction pool. -func NewProposer(client *mainchain.SMCClient, shardp2p sharding.ShardP2P, txpool sharding.TXPool, shardChainDb ethdb.Database, shardID int) (*Proposer, error) { - return &Proposer{client, shardp2p, txpool, shardChainDb, shardID}, nil +func NewProposer(config *params.ShardConfig, client *mainchain.SMCClient, shardp2p sharding.ShardP2P, txpool sharding.TXPool, shardChainDb ethdb.Database, shardID int) (*Proposer, error) { + return &Proposer{config, client, shardp2p, txpool, shardChainDb, shardID}, nil } // Start the main loop for proposing collations. @@ -63,7 +65,7 @@ func (p *Proposer) proposeCollations() { log.Error(fmt.Sprintf("Could not fetch current block number: %v", err)) return } - period := new(big.Int).Div(blockNumber.Number(), big.NewInt(sharding.PeriodLength)) + period := new(big.Int).Div(blockNumber.Number(), big.NewInt(p.config.PeriodLength)) // Create collation. collation, err := createCollation(p.client, big.NewInt(int64(p.shardID)), period, txs) diff --git a/sharding/proposer/service_test.go b/sharding/proposer/service_test.go index 045a7d067d..22b5526f17 100644 --- a/sharding/proposer/service_test.go +++ b/sharding/proposer/service_test.go @@ -14,8 +14,8 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/sharding" "github.com/ethereum/go-ethereum/sharding/contracts" + "github.com/ethereum/go-ethereum/sharding/params" "gopkg.in/urfave/cli.v1" ) @@ -89,10 +89,14 @@ func (m *mockNode) Close() { m.t.Fatal("Close called") } -func (s *mockNode) DataDirPath() string { +func (m *mockNode) DataDirPath() string { return "/tmp/datadir" } +func (m *mockNode) GetShardCount() (int64, error) { + return 100, nil +} + func transactOpts() *bind.TransactOpts { return bind.NewKeyedTransactor(key) } @@ -124,7 +128,7 @@ func TestCreateCollation(t *testing.T) { } // fast forward to 2nd period. - for i := 0; i < 2*int(sharding.PeriodLength); i++ { + for i := 0; i < 2*int(params.DefaultShardConfig.PeriodLength); i++ { backend.Commit() } @@ -182,7 +186,7 @@ func TestAddCollation(t *testing.T) { } // fast forward to next period. - for i := 0; i < int(sharding.PeriodLength); i++ { + for i := 0; i < int(params.DefaultShardConfig.PeriodLength); i++ { backend.Commit() } @@ -229,7 +233,7 @@ func TestCheckCollation(t *testing.T) { t.Errorf("Create collation failed: %v", err) } - for i := 0; i < int(sharding.PeriodLength); i++ { + for i := 0; i < int(params.DefaultShardConfig.PeriodLength); i++ { backend.Commit() }