diff --git a/cmd/registrar/exec.go b/cmd/registrar/exec.go index 0ec0441b84..1fc05d6947 100644 --- a/cmd/registrar/exec.go +++ b/cmd/registrar/exec.go @@ -21,6 +21,7 @@ import ( "math/big" "strconv" "strings" + "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/cmd/utils" @@ -102,7 +103,7 @@ func registerCheckpoint(ctx *cli.Context) error { var result [3]string index := ctx.GlobalInt64(checkpointIndexFlag.Name) if err := rpcClient.Call(&result, "les_getCheckpoint", index); err != nil { - utils.Fatalf("Failed to get local checkpoint %v", err) + utils.Fatalf("Failed to get local checkpoint %v, please ensure the les API is exposed", err) } checkpoint = ¶ms.TrustedCheckpoint{ SectionIndex: uint64(index), @@ -116,7 +117,7 @@ func registerCheckpoint(ctx *cli.Context) error { var result [4]string err := rpcClient.Call(&result, "les_latestCheckpoint") if err != nil { - utils.Fatalf("Failed to get local checkpoint %v", err) + utils.Fatalf("Failed to get local checkpoint %v, please ensure the les API is exposed", err) } index, err := strconv.ParseUint(result[0], 0, 64) if err != nil { @@ -132,12 +133,15 @@ func registerCheckpoint(ctx *cli.Context) error { "chtroot", checkpoint.CHTRoot, "bloomroot", checkpoint.BloomRoot, "hash", checkpoint.Hash()) } contract := setupContract(rpcClient) - // Filter out stale checkpoint announcement + + // Ensure the validness of the checkpoint. latest, _, h, err := contract.Contract().GetLatestCheckpoint(nil) if err != nil { return err } - head, err := ethclient.NewClient(rpcClient).HeaderByNumber(context.Background(), nil) + reqCtx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second) + defer cancelFn() + head, err := ethclient.NewClient(rpcClient).HeaderByNumber(reqCtx, nil) if err != nil { return err } @@ -151,7 +155,8 @@ func registerCheckpoint(ctx *cli.Context) error { if checkpoint.SectionIndex == latest.Uint64() && (latest.Uint64() != 0 || h.Uint64() != 0) { utils.Fatalf("Stale checkpoint, latest registered %d, given %d", latest.Uint64(), checkpoint.SectionIndex) } - // Ensure the invoker is a trusted signer. + + // Ensure the caller is a trusted signer. signers, err := contract.Contract().GetAllAdmin(nil) if err != nil { return err @@ -166,8 +171,15 @@ func registerCheckpoint(ctx *cli.Context) error { if !trusted { utils.Fatalf("Address %s is not a trusted signer", key.Address) } + + // Fetch identity information + identity, err := ethclient.NewClient(rpcClient).HeaderByNumber(reqCtx, big.NewInt(int64(headNumber-128))) + if err != nil { + return err + } + // Register the checkpoint - tx, err := contract.SetCheckpoint(key.PrivateKey, big.NewInt(int64(checkpoint.SectionIndex)), checkpoint.Hash().Bytes()) + tx, err := contract.SetCheckpoint(key.PrivateKey, big.NewInt(int64(checkpoint.SectionIndex)), checkpoint.Hash().Bytes(), identity.Number.Uint64(), identity.Hash()) if err != nil { return err } diff --git a/contracts/registrar/contract/registrar.go b/contracts/registrar/contract/registrar.go index c39d37eb70..3f4ed472b7 100644 --- a/contracts/registrar/contract/registrar.go +++ b/contracts/registrar/contract/registrar.go @@ -28,10 +28,10 @@ var ( ) // ContractABI is the input ABI used to generate the binding from. -const ContractABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"GetAllAdmin\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetLatestCheckpoint\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_sectionIndex\",\"type\":\"uint256\"},{\"name\":\"_hash\",\"type\":\"bytes32\"},{\"name\":\"_sig\",\"type\":\"bytes\"}],\"name\":\"SetCheckpoint\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetPending\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"address[]\"},{\"name\":\"\",\"type\":\"bytes32[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_adminlist\",\"type\":\"address[]\"},{\"name\":\"_sectionSize\",\"type\":\"uint256\"},{\"name\":\"_processConfirms\",\"type\":\"uint256\"},{\"name\":\"_threshold\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"index\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"checkpointHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"NewCheckpointEvent\",\"type\":\"event\"}]" +const ContractABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"GetAllAdmin\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetLatestCheckpoint\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_sectionIndex\",\"type\":\"uint256\"},{\"name\":\"_hash\",\"type\":\"bytes32\"},{\"name\":\"_identityNumber\",\"type\":\"uint64\"},{\"name\":\"_identityHash\",\"type\":\"bytes32\"},{\"name\":\"_sig\",\"type\":\"bytes\"}],\"name\":\"SetCheckpoint\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetPending\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"address[]\"},{\"name\":\"\",\"type\":\"bytes32[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_adminlist\",\"type\":\"address[]\"},{\"name\":\"_sectionSize\",\"type\":\"uint256\"},{\"name\":\"_processConfirms\",\"type\":\"uint256\"},{\"name\":\"_threshold\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"index\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"checkpointHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"NewCheckpointEvent\",\"type\":\"event\"}]" // ContractBin is the compiled bytecode used for deploying new contracts. -const ContractBin = `608060405234801561001057600080fd5b506040516112703803806112708339810180604052608081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185602082028301116401000000008211171561007e57600080fd5b505092919060200180519060200190929190805190602001909291908051906020019092919050505060008090505b84518110156101af5760016004600087848151811015156100ca57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506005858281518110151561013557fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505080806001019150506100ad565b508260098190555081600a8190555080600b8190555050505050611098806101d86000396000f3fe608060405234801561001057600080fd5b5060043610610069576000357c01000000000000000000000000000000000000000000000000000000009004806345848dfc1461006e5780634d6a304c146100cd5780639475a2b9146100f9578063fff5f367146101e0575b600080fd5b61007661028e565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156100b957808201518184015260208101905061009e565b505050509050019250505060405180910390f35b6100d5610374565b60405180848152602001838152602001828152602001935050505060405180910390f35b6101c66004803603606081101561010f57600080fd5b8101908080359060200190929190803590602001909291908035906020019064010000000081111561014057600080fd5b82018360208201111561015257600080fd5b8035906020019184600183028401116401000000008311171561017457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061038d565b604051808215151515815260200191505060405180910390f35b6101e8610b04565b604051808481526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561023557808201518184015260208101905061021a565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561027757808201518184015260208101905061025c565b505050509050019550505050505060405180910390f35b6060806005805490506040519080825280602002602001820160405280156102c55781602001602082028038833980820191505090505b50905060008090505b60058054905081101561036c576005818154811015156102ea57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828281518110151561032357fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080806001019150506102ce565b508091505090565b6000806000600654600854600754925092509250909192565b6000600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615156103e757600080fd5b600a546009546001860102014310156104035760009050610afd565b6006548410156104165760009050610afd565b6006548414801561043657506000841415806104355750600060075414155b5b156104445760009050610afd565b6000831480610454575060008251145b156104625760009050610afd565b83600080015414151561047857610477610ce8565b5b60008060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050838114156104d0576000915050610afd565b6000808214905084600060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080156106195760016000600101600082825401925050819055508560008001819055506000600301600086815260200190815260200160002060408051908101604052803373ffffffffffffffffffffffffffffffffffffffff168152602001868152509080600181540180825580915050906001820390600052602060002090600202016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001019080519060200190610610929190610e4c565b505050506108e8565b6000806003016000848152602001908152602001600020905060008090505b600182805490500381101561079d573373ffffffffffffffffffffffffffffffffffffffff16828281548110151561066c57fe5b906000526020600020906002020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610790578160018380549050038154811015156106cf57fe5b906000526020600020906002020182828154811015156106eb57fe5b90600052602060002090600202016000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060018201816001019080546001816001161561010002031660029004610787929190610ecc565b5090505061079d565b8080600101915050610638565b508060018280549050038154811015156107b357fe5b9060005260206000209060020201600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160006107f99190610f53565b5050600181818180549050039150816108129190610f9b565b506000600301600087815260200190815260200160002060408051908101604052803373ffffffffffffffffffffffffffffffffffffffff168152602001878152509080600181540180825580915050906001820390600052602060002090600202016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010190805190602001906108e2929190610e4c565b50505050505b600b546000600301600087815260200190815260200160002080549050101561091657600192505050610afd565b846008819055504360078190555085600681905550606060008090505b600b54811015610a475781600060030160008981526020019081526020016000208281548110151561096157fe5b90600052602060002090600202016001016040516020018083805190602001908083835b6020831015156109aa5780518252602082019150602081019050602083039250610985565b6001836020036101000a03801982511681845116808217855250505050505090500182805460018160011615610100020316600290048015610a235780601f10610a01576101008083540402835291820191610a23565b820191906000526020600020905b815481529060010190602001808311610a0f575b50509250505060405160208183030381529060405291508080600101915050610933565b50867ff7aa4ddabff125da62b8692942a8dee5c673822157f230e5520a5b4e92d6929f87836040518083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610ab2578082015181840152602081019050610a97565b50505050905090810190601f168015610adf5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a2610af5610ce8565b600193505050505b9392505050565b600060608060008090506060600060010154604051908082528060200260200182016040528015610b445781602001602082028038833980820191505090505b5090506060600060010154604051908082528060200260200182016040528015610b7d5781602001602082028038833980820191505090505b50905060008090505b600580549050811015610cd2576000806002016000600584815481101515610baa57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600081141515610cc457600582815481101515610c2b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168486815181101515610c6457fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808386815181101515610caf57fe5b90602001906020020181815250506001850194505b508080600101915050610b86565b5060008001548282955095509550505050909192565b60008090505b600580549050811015610e34576000806002016000600584815481101515610d1257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600081141515610e2657600060030160008281526020019081526020016000206000610da69190610fcd565b60006002016000600584815481101515610dbc57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090555b508080600101915050610cee565b50600080600082016000905560018201600090555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610e8d57805160ff1916838001178555610ebb565b82800160010185558215610ebb579182015b82811115610eba578251825591602001919060010190610e9f565b5b509050610ec89190610ff1565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610f055780548555610f42565b82800160010185558215610f4257600052602060002091601f016020900482015b82811115610f41578254825591600101919060010190610f26565b5b509050610f4f9190610ff1565b5090565b50805460018160011615610100020316600290046000825580601f10610f795750610f98565b601f016020900490600052602060002090810190610f979190610ff1565b5b50565b815481835581811115610fc857600202816002028360005260206000209182019101610fc79190611016565b5b505050565b5080546000825560020290600052602060002090810190610fee9190611016565b50565b61101391905b8082111561100f576000816000905550600101610ff7565b5090565b90565b61106991905b8082111561106557600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560018201600061105c9190610f53565b5060020161101c565b5090565b9056fea165627a7a723058208826dffaf11789f2fcaf8f64020329e9b49e58917077307c1b668880fd557d500029` +const ContractBin = `608060405234801561001057600080fd5b506040516112ad3803806112ad8339810180604052608081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185602082028301116401000000008211171561007e57600080fd5b505092919060200180519060200190929190805190602001909291908051906020019092919050505060008090505b84518110156101af5760016004600087848151811015156100ca57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506005858281518110151561013557fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505080806001019150506100ad565b508260098190555081600a8190555080600b81905550505050506110d5806101d86000396000f3fe608060405234801561001057600080fd5b5060043610610069576000357c01000000000000000000000000000000000000000000000000000000009004806345848dfc1461006e5780634d6a304c146100cd578063c0499776146100f9578063fff5f367146101fe575b600080fd5b6100766102ac565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156100b957808201518184015260208101905061009e565b505050509050019250505060405180910390f35b6100d5610392565b60405180848152602001838152602001828152602001935050505060405180910390f35b6101e4600480360360a081101561010f57600080fd5b810190808035906020019092919080359060200190929190803567ffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561015e57600080fd5b82018360208201111561017057600080fd5b8035906020019184600183028401116401000000008311171561019257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506103ab565b604051808215151515815260200191505060405180910390f35b610206610b41565b604051808481526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610253578082015181840152602081019050610238565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561029557808201518184015260208101905061027a565b505050509050019550505050505060405180910390f35b6060806005805490506040519080825280602002602001820160405280156102e35781602001602082028038833980820191505090505b50905060008090505b60058054905081101561038a5760058181548110151561030857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828281518110151561034157fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080806001019150506102ec565b508091505090565b6000806000600654600854600754925092509250909192565b60008383808267ffffffffffffffff16401415156103c857600080fd5b600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561042057600080fd5b600a5460095460018a01020143101561043c5760009250610b36565b60065488101561044f5760009250610b36565b6006548814801561046f575060008814158061046e5750600060075414155b5b1561047d5760009250610b36565b600087148061048d575060008451145b1561049b5760009250610b36565b8760008001541415156104b1576104b0610d25565b5b60008060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905087811415610509576000935050610b36565b6000808214905088600060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508015610652576001600060010160008282540192505081905550896000800181905550600060030160008a815260200190815260200160002060408051908101604052803373ffffffffffffffffffffffffffffffffffffffff168152602001888152509080600181540180825580915050906001820390600052602060002090600202016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001019080519060200190610649929190610e89565b50505050610921565b6000806003016000848152602001908152602001600020905060008090505b60018280549050038110156107d6573373ffffffffffffffffffffffffffffffffffffffff1682828154811015156106a557fe5b906000526020600020906002020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156107c95781600183805490500381548110151561070857fe5b9060005260206000209060020201828281548110151561072457fe5b90600052602060002090600202016000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600182018160010190805460018160011615610100020316600290046107c0929190610f09565b509050506107d6565b8080600101915050610671565b508060018280549050038154811015156107ec57fe5b9060005260206000209060020201600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160006108329190610f90565b50506001818181805490500391508161084b9190610fd8565b50600060030160008b815260200190815260200160002060408051908101604052803373ffffffffffffffffffffffffffffffffffffffff168152602001898152509080600181540180825580915050906001820390600052602060002090600202016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101908051906020019061091b929190610e89565b50505050505b600b54600060030160008b815260200190815260200160002080549050101561094f57600194505050610b36565b886008819055504360078190555089600681905550606060008090505b600b54811015610a805781600060030160008d81526020019081526020016000208281548110151561099a57fe5b90600052602060002090600202016001016040516020018083805190602001908083835b6020831015156109e357805182526020820191506020810190506020830392506109be565b6001836020036101000a03801982511681845116808217855250505050505090500182805460018160011615610100020316600290048015610a5c5780601f10610a3a576101008083540402835291820191610a5c565b820191906000526020600020905b815481529060010190602001808311610a48575b5050925050506040516020818303038152906040529150808060010191505061096c565b508a7ff7aa4ddabff125da62b8692942a8dee5c673822157f230e5520a5b4e92d6929f8b836040518083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610aeb578082015181840152602081019050610ad0565b50505050905090810190601f168015610b185780820380516001836020036101000a031916815260200191505b50935050505060405180910390a2610b2e610d25565b600195505050505b505095945050505050565b600060608060008090506060600060010154604051908082528060200260200182016040528015610b815781602001602082028038833980820191505090505b5090506060600060010154604051908082528060200260200182016040528015610bba5781602001602082028038833980820191505090505b50905060008090505b600580549050811015610d0f576000806002016000600584815481101515610be757fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600081141515610d0157600582815481101515610c6857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168486815181101515610ca157fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808386815181101515610cec57fe5b90602001906020020181815250506001850194505b508080600101915050610bc3565b5060008001548282955095509550505050909192565b60008090505b600580549050811015610e71576000806002016000600584815481101515610d4f57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600081141515610e6357600060030160008281526020019081526020016000206000610de3919061100a565b60006002016000600584815481101515610df957fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090555b508080600101915050610d2b565b50600080600082016000905560018201600090555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610eca57805160ff1916838001178555610ef8565b82800160010185558215610ef8579182015b82811115610ef7578251825591602001919060010190610edc565b5b509050610f05919061102e565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610f425780548555610f7f565b82800160010185558215610f7f57600052602060002091601f016020900482015b82811115610f7e578254825591600101919060010190610f63565b5b509050610f8c919061102e565b5090565b50805460018160011615610100020316600290046000825580601f10610fb65750610fd5565b601f016020900490600052602060002090810190610fd4919061102e565b5b50565b815481835581811115611005576002028160020283600052602060002091820191016110049190611053565b5b505050565b508054600082556002029060005260206000209081019061102b9190611053565b50565b61105091905b8082111561104c576000816000905550600101611034565b5090565b90565b6110a691905b808211156110a257600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160006110999190610f90565b50600201611059565b5090565b9056fea165627a7a72305820bdef8c9f30d83f31d7ac8ed79eb6d656f4ece6bf05bee292cbb7a99d7cb2746a0029` // DeployContract deploys a new Ethereum contract, binding an instance of Contract to it. func DeployContract(auth *bind.TransactOpts, backend bind.ContractBackend, _adminlist []common.Address, _sectionSize *big.Int, _processConfirms *big.Int, _threshold *big.Int) (common.Address, *types.Transaction, *Contract, error) { @@ -278,25 +278,25 @@ func (_Contract *ContractCallerSession) GetPending() (*big.Int, []common.Address return _Contract.Contract.GetPending(&_Contract.CallOpts) } -// SetCheckpoint is a paid mutator transaction binding the contract method 0x9475a2b9. +// SetCheckpoint is a paid mutator transaction binding the contract method 0xc0499776. // -// Solidity: function SetCheckpoint(uint256 _sectionIndex, bytes32 _hash, bytes _sig) returns(bool) -func (_Contract *ContractTransactor) SetCheckpoint(opts *bind.TransactOpts, _sectionIndex *big.Int, _hash [32]byte, _sig []byte) (*types.Transaction, error) { - return _Contract.contract.Transact(opts, "SetCheckpoint", _sectionIndex, _hash, _sig) +// Solidity: function SetCheckpoint(uint256 _sectionIndex, bytes32 _hash, uint64 _identityNumber, bytes32 _identityHash, bytes _sig) returns(bool) +func (_Contract *ContractTransactor) SetCheckpoint(opts *bind.TransactOpts, _sectionIndex *big.Int, _hash [32]byte, _identityNumber uint64, _identityHash [32]byte, _sig []byte) (*types.Transaction, error) { + return _Contract.contract.Transact(opts, "SetCheckpoint", _sectionIndex, _hash, _identityNumber, _identityHash, _sig) } -// SetCheckpoint is a paid mutator transaction binding the contract method 0x9475a2b9. +// SetCheckpoint is a paid mutator transaction binding the contract method 0xc0499776. // -// Solidity: function SetCheckpoint(uint256 _sectionIndex, bytes32 _hash, bytes _sig) returns(bool) -func (_Contract *ContractSession) SetCheckpoint(_sectionIndex *big.Int, _hash [32]byte, _sig []byte) (*types.Transaction, error) { - return _Contract.Contract.SetCheckpoint(&_Contract.TransactOpts, _sectionIndex, _hash, _sig) +// Solidity: function SetCheckpoint(uint256 _sectionIndex, bytes32 _hash, uint64 _identityNumber, bytes32 _identityHash, bytes _sig) returns(bool) +func (_Contract *ContractSession) SetCheckpoint(_sectionIndex *big.Int, _hash [32]byte, _identityNumber uint64, _identityHash [32]byte, _sig []byte) (*types.Transaction, error) { + return _Contract.Contract.SetCheckpoint(&_Contract.TransactOpts, _sectionIndex, _hash, _identityNumber, _identityHash, _sig) } -// SetCheckpoint is a paid mutator transaction binding the contract method 0x9475a2b9. +// SetCheckpoint is a paid mutator transaction binding the contract method 0xc0499776. // -// Solidity: function SetCheckpoint(uint256 _sectionIndex, bytes32 _hash, bytes _sig) returns(bool) -func (_Contract *ContractTransactorSession) SetCheckpoint(_sectionIndex *big.Int, _hash [32]byte, _sig []byte) (*types.Transaction, error) { - return _Contract.Contract.SetCheckpoint(&_Contract.TransactOpts, _sectionIndex, _hash, _sig) +// Solidity: function SetCheckpoint(uint256 _sectionIndex, bytes32 _hash, uint64 _identityNumber, bytes32 _identityHash, bytes _sig) returns(bool) +func (_Contract *ContractTransactorSession) SetCheckpoint(_sectionIndex *big.Int, _hash [32]byte, _identityNumber uint64, _identityHash [32]byte, _sig []byte) (*types.Transaction, error) { + return _Contract.Contract.SetCheckpoint(&_Contract.TransactOpts, _sectionIndex, _hash, _identityNumber, _identityHash, _sig) } // ContractNewCheckpointEventIterator is returned from FilterNewCheckpointEvent and is used to iterate over the raw logs and unpacked data for NewCheckpointEvent events raised by the Contract contract. diff --git a/contracts/registrar/contract/registrar.sol b/contracts/registrar/contract/registrar.sol index dd2ad57bc0..950e2d608a 100644 --- a/contracts/registrar/contract/registrar.sol +++ b/contracts/registrar/contract/registrar.sol @@ -37,6 +37,14 @@ contract Registrar { _; } + /** + * @dev Check whether the vote truly belongs to local chain. + */ + modifier replayProtection(uint64 _number, bytes32 _hash) { + require(blockhash(_number) == _hash); + _; + } + /* Events */ @@ -81,6 +89,8 @@ contract Registrar { * * @param _sectionIndex section index * @param _hash checkpoint hash calculated in the client side + * @param _identityNumber block number used to protect transaction replay. + * @param _identityHash corresponding block hash used to protect transaction replay. * @param _sig admin's signature for checkpoint hash * `checkpoint_hash = Hash(index, sectionHead, chtRoot, bloomRoot)` * `_sig = Sign(privateKey, checkpoint_hash)` @@ -89,8 +99,11 @@ contract Registrar { function SetCheckpoint( uint _sectionIndex, bytes32 _hash, + uint64 _identityNumber, + bytes32 _identityHash, bytes memory _sig ) + replayProtection(_identityNumber, _identityHash) OnlyAuthorized public returns(bool) @@ -234,7 +247,6 @@ contract Registrar { address[] adminList; // Latest stored section id - // Note all registered checkpoint information should continuous with previous one. uint sectionIndex; // The block height associated with latest registered checkpoint. diff --git a/contracts/registrar/registrar.go b/contracts/registrar/registrar.go index 54579a39e5..6430afde2a 100644 --- a/contracts/registrar/registrar.go +++ b/contracts/registrar/registrar.go @@ -66,12 +66,12 @@ func (registrar *Registrar) LookupCheckpointEvent(blockLogs [][]*types.Log, sect } // SetCheckpoint creates a signature for given checkpoint with specified private key and registers into contract. -func (registrar *Registrar) SetCheckpoint(key *ecdsa.PrivateKey, sectionIndex *big.Int, hash []byte) (*types.Transaction, error) { +func (registrar *Registrar) SetCheckpoint(key *ecdsa.PrivateKey, sectionIndex *big.Int, hash []byte, identityNumber uint64, identityHash [32]byte) (*types.Transaction, error) { sig, err := crypto.Sign(hash, key) if err != nil { return nil, err } var h [32]byte copy(h[:], hash) - return registrar.contract.SetCheckpoint(bind.NewKeyedTransactor(key), sectionIndex, h, sig) + return registrar.contract.SetCheckpoint(bind.NewKeyedTransactor(key), sectionIndex, h, identityNumber, identityHash, sig) } diff --git a/contracts/registrar/registrar_test.go b/contracts/registrar/registrar_test.go index 809aadecb7..74bdbb4d3b 100644 --- a/contracts/registrar/registrar_test.go +++ b/contracts/registrar/registrar_test.go @@ -174,9 +174,26 @@ func TestCheckpointRegister(t *testing.T) { } contractBackend.Commit() + // getIdentity returns block height and hash of the head parent. + getIdentity := func() (uint64, common.Hash) { + parentNumber := contractBackend.Blockchain().CurrentHeader().Number.Uint64() - 1 + parentHash := contractBackend.Blockchain().CurrentHeader().ParentHash + return parentNumber, parentHash + } + // Register unstable checkpoint validateOperation(t, c, contractBackend, func() { - c.SetCheckpoint(transactOpts, big.NewInt(0), checkpoint0.Hash(), signCheckpoint(accounts[0].key, checkpoint0.Hash())) + number, hash := getIdentity() + c.SetCheckpoint(transactOpts, big.NewInt(0), checkpoint0.Hash(), number, hash, signCheckpoint(accounts[0].key, checkpoint0.Hash())) + }, func(events <-chan *contract.ContractNewCheckpointEvent) error { + return assert(c, 0, nil, nil) + }, "register unstable checkpoint") + + // Test transaction replay + validateOperation(t, c, contractBackend, func() { + number, hash := getIdentity() + hash = common.HexToHash("deadbeef") + c.SetCheckpoint(transactOpts, big.NewInt(0), checkpoint0.Hash(), number, hash, signCheckpoint(accounts[0].key, checkpoint0.Hash())) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { return assert(c, 0, nil, nil) }, "register unstable checkpoint") @@ -185,51 +202,58 @@ func TestCheckpointRegister(t *testing.T) { // Register by unauthorized user validateOperation(t, c, contractBackend, func() { + number, hash := getIdentity() u, _ := crypto.GenerateKey() unauthorized := bind.NewKeyedTransactor(u) - c.SetCheckpoint(unauthorized, big.NewInt(0), checkpoint0.Hash(), signCheckpoint(u, checkpoint0.Hash())) + c.SetCheckpoint(unauthorized, big.NewInt(0), checkpoint0.Hash(), number, hash, signCheckpoint(u, checkpoint0.Hash())) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { return assert(c, 0, nil, nil) }, "register by unauthorized user") // Submit a new checkpoint announcement validateOperation(t, c, contractBackend, func() { - c.SetCheckpoint(transactOpts, big.NewInt(0), checkpoint0.Hash(), signCheckpoint(accounts[0].key, checkpoint0.Hash())) + number, hash := getIdentity() + c.SetCheckpoint(transactOpts, big.NewInt(0), checkpoint0.Hash(), number, hash, signCheckpoint(accounts[0].key, checkpoint0.Hash())) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { return assert(c, 0, []common.Address{accounts[0].addr}, []common.Hash{checkpoint0.Hash()}) }, "single checkpoint announcement") // Submit a duplicate checkpoint announcement validateOperation(t, c, contractBackend, func() { - c.SetCheckpoint(transactOpts, big.NewInt(0), checkpoint0.Hash(), signCheckpoint(accounts[0].key, checkpoint0.Hash())) + number, hash := getIdentity() + c.SetCheckpoint(transactOpts, big.NewInt(0), checkpoint0.Hash(), number, hash, signCheckpoint(accounts[0].key, checkpoint0.Hash())) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { return assert(c, 0, []common.Address{accounts[0].addr}, []common.Hash{checkpoint0.Hash()}) }, "duplicate checkpoint announcement") // Modification validateOperation(t, c, contractBackend, func() { - c.SetCheckpoint(transactOpts, big.NewInt(0), common.HexToHash("deadbeef"), signCheckpoint(accounts[0].key, common.HexToHash("deadbeef"))) + number, hash := getIdentity() + c.SetCheckpoint(transactOpts, big.NewInt(0), common.HexToHash("deadbeef"), number, hash, signCheckpoint(accounts[0].key, common.HexToHash("deadbeef"))) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { return assert(c, 0, []common.Address{accounts[0].addr}, []common.Hash{common.HexToHash("deadbeef")}) }, "checkpoint modification") // Modification validateOperation(t, c, contractBackend, func() { - c.SetCheckpoint(transactOpts, big.NewInt(0), common.HexToHash("deadbeef2"), signCheckpoint(accounts[0].key, common.HexToHash("deadbeef2"))) + number, hash := getIdentity() + c.SetCheckpoint(transactOpts, big.NewInt(0), common.HexToHash("deadbeef2"), number, hash, signCheckpoint(accounts[0].key, common.HexToHash("deadbeef2"))) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { return assert(c, 0, []common.Address{accounts[0].addr}, []common.Hash{common.HexToHash("deadbeef2")}) }, "checkpoint modification") // Another correct checkpoint announcement validateOperation(t, c, contractBackend, func() { - c.SetCheckpoint(bind.NewKeyedTransactor(accounts[1].key), big.NewInt(0), checkpoint0.Hash(), signCheckpoint(accounts[1].key, checkpoint0.Hash())) + number, hash := getIdentity() + c.SetCheckpoint(bind.NewKeyedTransactor(accounts[1].key), big.NewInt(0), checkpoint0.Hash(), number, hash, signCheckpoint(accounts[1].key, checkpoint0.Hash())) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { return assert(c, 0, []common.Address{accounts[0].addr, accounts[1].addr}, []common.Hash{common.HexToHash("deadbeef2"), checkpoint0.Hash()}) }, "another checkpoint announcement") // enough checkpoint announcement validateOperation(t, c, contractBackend, func() { - c.SetCheckpoint(bind.NewKeyedTransactor(accounts[2].key), big.NewInt(0), checkpoint0.Hash(), signCheckpoint(accounts[2].key, checkpoint0.Hash())) + number, hash := getIdentity() + c.SetCheckpoint(bind.NewKeyedTransactor(accounts[2].key), big.NewInt(0), checkpoint0.Hash(), number, hash, signCheckpoint(accounts[2].key, checkpoint0.Hash())) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { if valid, recv := validateEvents(1, events); !valid { return errors.New("receive incorrect number of events") @@ -249,14 +273,16 @@ func TestCheckpointRegister(t *testing.T) { // submit a stale checkpoint announcement validateOperation(t, c, contractBackend, func() { - c.SetCheckpoint(transactOpts, big.NewInt(0), checkpoint0.Hash(), signCheckpoint(accounts[0].key, checkpoint0.Hash())) + number, hash := getIdentity() + c.SetCheckpoint(transactOpts, big.NewInt(0), checkpoint0.Hash(), number, hash, signCheckpoint(accounts[0].key, checkpoint0.Hash())) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { return assert(c, 0, nil, nil) }, "submit stale checkpoint announcement") // submit a future checkpoint announcement validateOperation(t, c, contractBackend, func() { - c.SetCheckpoint(transactOpts, big.NewInt(1), checkpoint1.Hash(), signCheckpoint(accounts[0].key, checkpoint1.Hash())) + number, hash := getIdentity() + c.SetCheckpoint(transactOpts, big.NewInt(1), checkpoint1.Hash(), number, hash, signCheckpoint(accounts[0].key, checkpoint1.Hash())) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { return assert(c, 0, nil, nil) }, "submit future checkpoint announcement") @@ -265,8 +291,9 @@ func TestCheckpointRegister(t *testing.T) { distance := 3*sectionSize.Uint64() + processConfirms.Uint64() - contractBackend.Blockchain().CurrentHeader().Number.Uint64() contractBackend.InsertEmptyBlocks(int(distance)) validateOperation(t, c, contractBackend, func() { - c.SetCheckpoint(transactOpts, big.NewInt(2), checkpoint2.Hash(), signCheckpoint(accounts[0].key, checkpoint2.Hash())) - c.SetCheckpoint(bind.NewKeyedTransactor(accounts[1].key), big.NewInt(2), checkpoint2.Hash(), signCheckpoint(accounts[1].key, checkpoint2.Hash())) + number, hash := getIdentity() + c.SetCheckpoint(transactOpts, big.NewInt(2), checkpoint2.Hash(), number, hash, signCheckpoint(accounts[0].key, checkpoint2.Hash())) + c.SetCheckpoint(bind.NewKeyedTransactor(accounts[1].key), big.NewInt(2), checkpoint2.Hash(), number, hash, signCheckpoint(accounts[1].key, checkpoint2.Hash())) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { if valid, recv := validateEvents(1, events); !valid { return errors.New("receive incorrect number of events") @@ -286,7 +313,8 @@ func TestCheckpointRegister(t *testing.T) { // submit a stale checkpoint announcement validateOperation(t, c, contractBackend, func() { - c.SetCheckpoint(transactOpts, big.NewInt(2), checkpoint2.Hash(), signCheckpoint(accounts[0].key, checkpoint2.Hash())) + number, hash := getIdentity() + c.SetCheckpoint(transactOpts, big.NewInt(2), checkpoint2.Hash(), number, hash, signCheckpoint(accounts[0].key, checkpoint2.Hash())) }, func(events <-chan *contract.ContractNewCheckpointEvent) error { return assert(c, 0, nil, nil) }, "submit stale checkpoint announcement") diff --git a/les/helper_test.go b/les/helper_test.go index 3b6a51e6e2..10eff36def 100644 --- a/les/helper_test.go +++ b/les/helper_test.go @@ -202,10 +202,10 @@ func newTestProtocolManager(lightSync bool, blocks int, odr *LesOdr, indexers [] } var reg *checkpointRegistrar if indexers != nil { - getLocal := func(index uint64) light.TrustedCheckpoint { + getLocal := func(index uint64) params.TrustedCheckpoint { chtIndexer := indexers[0] sectionHead := chtIndexer.SectionHead(index) - return light.TrustedCheckpoint{ + return params.TrustedCheckpoint{ SectionIndex: index, SectionHead: sectionHead, CHTRoot: light.GetChtRoot(db, index, sectionHead), diff --git a/les/sync_test.go b/les/sync_test.go index 285edf8ebe..8d97017449 100644 --- a/les/sync_test.go +++ b/les/sync_test.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/light" + "github.com/ethereum/go-ethereum/params" ) func TestCheckpointSyncingLes2(t *testing.T) { testCheckpointSyncing(t, 2) } @@ -49,13 +50,14 @@ func testCheckpointSyncing(t *testing.T, protocol int) { chtRoot := light.GetChtRoot(server.db, 7, head) btRoot := light.GetBloomTrieRoot(server.db, bts-1, head) - cp := &light.TrustedCheckpoint{ + cp := ¶ms.TrustedCheckpoint{ SectionIndex: 0, SectionHead: head, CHTRoot: chtRoot, BloomRoot: btRoot, } - if _, err := server.pm.reg.contract.SetCheckpoint(signerKey, big.NewInt(int64(cp.SectionIndex)), cp.Hash().Bytes()); err != nil { + header := server.backend.Blockchain().CurrentHeader() + if _, err := server.pm.reg.contract.SetCheckpoint(signerKey, big.NewInt(int64(cp.SectionIndex)), cp.Hash().Bytes(), header.Number.Uint64(), header.Hash()); err != nil { t.Error("register checkpoint failed", err) } server.backend.Commit() @@ -63,7 +65,7 @@ func testCheckpointSyncing(t *testing.T, protocol int) { // Wait for the checkpoint registration for { - hash, _, err := server.pm.reg.contract.Contract().GetCheckpoint(nil, big.NewInt(0)) + _, hash, _, err := server.pm.reg.contract.Contract().GetLatestCheckpoint(nil) if err != nil || hash == [32]byte{} { time.Sleep(100 * time.Millisecond) continue