diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index fa8828f61b..336c59e5b9 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -405,6 +405,28 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
return nil
}
+// ShiftBlocks inserts a batch of empty blocks to blockchain.
+func (b *SimulatedBackend) ShiftBlocks(number int) error {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ // Insert a batch of empty blocks and commit to the database
+ blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, number, func(i int, block *core.BlockGen) {})
+ if _, err := b.blockchain.InsertChain(blocks); err != nil {
+ panic(err) // This cannot happen unless the simulator is wrong, fail in that case
+ }
+ // Apply all pending transactions to new pending blocks.
+ blocks, _ = core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
+ for _, tx := range b.pendingBlock.Transactions() {
+ block.AddTx(tx)
+ }
+ })
+
+ statedb, _ := b.blockchain.State()
+ b.pendingBlock = blocks[0]
+ b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database())
+ return nil
+}
+
// callmsg implements core.Message to allow passing it as a transaction simulator.
type callmsg struct {
ethereum.CallMsg
diff --git a/contracts/registrar/contract/registrar.go b/contracts/registrar/contract/registrar.go
index c8db5de473..ebb292e9ef 100644
--- a/contracts/registrar/contract/registrar.go
+++ b/contracts/registrar/contract/registrar.go
@@ -19,7 +19,7 @@ import (
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\":\"bytes32\"},{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_sectionIndex\",\"type\":\"uint256\"},{\"name\":\"_sectionHead\",\"type\":\"bytes32\"},{\"name\":\"_chtRoot\",\"type\":\"bytes32\"},{\"name\":\"_bloomTrieRoot\",\"type\":\"bytes32\"}],\"name\":\"SetCheckpoint\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_sectionIndex\",\"type\":\"uint256\"}],\"name\":\"GetCheckpoint\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"RemoveAdmin\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"AddAdmin\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_adminlist\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"index\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"sectionHead\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"chtRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"bloomTrieRoot\",\"type\":\"bytes32\"}],\"name\":\"NewCheckpointEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"AddAdminEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"RemoveAdminEvent\",\"type\":\"event\"}]"
// ContractBin is the compiled bytecode used for deploying new contracts.
-const ContractBin = `608060405234801561001057600080fd5b50604051610c3f380380610c3f8339810180604052810190808051820192919050505060008090505b8151811015610127576001600080848481518110151561005557fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600182828151811015156100ad57fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508080600101915050610039565b5050610b07806101386000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806345848dfc1461007d5780634d6a304c146100e9578063651c7f4914610141578063710aeac8146101b0578063753f40ca14610217578063ad6de44514610272575b600080fd5b34801561008957600080fd5b506100926102cd565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156100d55780820151818401526020810190506100ba565b505050509050019250505060405180910390f35b3480156100f557600080fd5b506100fe6103b4565b6040518085815260200184600019166000191681526020018360001916600019168152602001826000191660001916815260200194505050505060405180910390f35b34801561014d57600080fd5b50610196600480360381019080803590602001909291908035600019169060200190929190803560001916906020019092919080356000191690602001909291905050506103e7565b604051808215151515815260200191505060405180910390f35b3480156101bc57600080fd5b506101db60048036038101908080359060200190929190505050610539565b60405180846000191660001916815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390f35b34801561022357600080fd5b50610258600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506105ba565b604051808215151515815260200191505060405180910390f35b34801561027e57600080fd5b506102b3600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108aa565b604051808215151515815260200191505060405180910390f35b60608060006001805490506040519080825280602002602001820160405280156103065781602001602082028038833980820191505090505b509150600090505b6001805490508110156103ac5760018181548110151561032a57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828281518110151561036357fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808060010191505061030e565b819250505090565b60008060008060008060006103ca600354610539565b925092509250600354838383965096509650965050505090919293565b6000806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411151561043557600080fd5b600160035401851415801561044d5750600060035414155b1561045b5760009050610531565b606060405190810160405280856000191681526020018460001916815260200183600019168152506002600087815260200190815260200160002060008201518160000190600019169055602082015181600101906000191690556040820151816002019060001916905590505084600381905550847fa9b81895520c1feeea26e91ca03e455eb4be8dc9ecb34071c362e67835a6fd4285858560405180846000191660001916815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390a25b949350505050565b6000806000610546610a5f565b600260008681526020019081526020016000206060604051908101604052908160008201546000191660001916815260200160018201546000191660001916815260200160028201546000191660001916815250509050806000015181602001518260400151935093509350509193909250565b6000806000806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411151561060b57600080fd5b60008060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141561065b57600092506108a3565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009055600091505b60018054905082101561083b578373ffffffffffffffffffffffffffffffffffffffff166001838154811015156106d557fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561082e578190505b60018080549050038110156107cf57600180820181548110151561074057fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660018281548110151561077a57fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508080600101915050610720565b6001808080549050038154811015156107e457fe5b9060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600180818180549050039150816108289190610a8a565b5061083b565b81806001019250506106a2565b7f16f0165239516629af323911340c1c906029142cb0dc3c32c93ce6808d98a4ee84604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1600192505b5050919050565b6000806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115156108f857600080fd5b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411156109485760009050610a5a565b60016000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060018290806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550507f68377f3d45858cbcc9e95998fb55b9c0f9e16b6ebf5f3602a40e2fcd0d7b8c0082604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1600190505b919050565b6060604051908101604052806000801916815260200160008019168152602001600080191681525090565b815481835581811115610ab157818360005260206000209182019101610ab09190610ab6565b5b505050565b610ad891905b80821115610ad4576000816000905550600101610abc565b5090565b905600a165627a7a72305820cbcd53f37f129054d200a6fe33ecd6996d1ac9fda6f8f3f481f7f6fdcac623260029`
+const ContractBin = `608060405234801561001057600080fd5b50604051610d06380380610d0683398101806040528101908080518201929190505050600060016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060013390806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600090505b81518110156101d2576001600080848481518110151561010057fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001828281518110151561015857fe5b9060200190602002015190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505080806001019150506100e4565b5050610b23806101e36000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806345848dfc1461007d5780634d6a304c146100e9578063651c7f4914610141578063710aeac8146101b0578063753f40ca14610217578063ad6de44514610272575b600080fd5b34801561008957600080fd5b506100926102cd565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156100d55780820151818401526020810190506100ba565b505050509050019250505060405180910390f35b3480156100f557600080fd5b506100fe6103b4565b6040518085815260200184600019166000191681526020018360001916600019168152602001826000191660001916815260200194505050505060405180910390f35b34801561014d57600080fd5b50610196600480360381019080803590602001909291908035600019169060200190929190803560001916906020019092919080356000191690602001909291905050506103e7565b604051808215151515815260200191505060405180910390f35b3480156101bc57600080fd5b506101db60048036038101908080359060200190929190505050610555565b60405180846000191660001916815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390f35b34801561022357600080fd5b50610258600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506105d6565b604051808215151515815260200191505060405180910390f35b34801561027e57600080fd5b506102b3600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108c6565b604051808215151515815260200191505060405180910390f35b60608060006001805490506040519080825280602002602001820160405280156103065781602001602082028038833980820191505090505b509150600090505b6001805490508110156103ac5760018181548110151561032a57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828281518110151561036357fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808060010191505061030e565b819250505090565b60008060008060008060006103ca600354610555565b925092509250600354838383965096509650965050505090919293565b6000806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411151561043557600080fd5b600160035401851415801561044d5750600060035414155b1561045b576000905061054d565b612710618000600187010201431015610477576000905061054d565b606060405190810160405280856000191681526020018460001916815260200183600019168152506002600087815260200190815260200160002060008201518160000190600019169055602082015181600101906000191690556040820151816002019060001916905590505084600381905550847fa9b81895520c1feeea26e91ca03e455eb4be8dc9ecb34071c362e67835a6fd4285858560405180846000191660001916815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390a25b949350505050565b6000806000610562610a7b565b600260008681526020019081526020016000206060604051908101604052908160008201546000191660001916815260200160018201546000191660001916815260200160028201546000191660001916815250509050806000015181602001518260400151935093509350509193909250565b6000806000806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411151561062757600080fd5b60008060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141561067757600092506108bf565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009055600091505b600180549050821015610857578373ffffffffffffffffffffffffffffffffffffffff166001838154811015156106f157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561084a578190505b60018080549050038110156107eb57600180820181548110151561075c57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660018281548110151561079657fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808060010191505061073c565b60018080805490500381548110151561080057fe5b9060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600180818180549050039150816108449190610aa6565b50610857565b81806001019250506106be565b7f16f0165239516629af323911340c1c906029142cb0dc3c32c93ce6808d98a4ee84604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1600192505b5050919050565b6000806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411151561091457600080fd5b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411156109645760009050610a76565b60016000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060018290806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550507f68377f3d45858cbcc9e95998fb55b9c0f9e16b6ebf5f3602a40e2fcd0d7b8c0082604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1600190505b919050565b6060604051908101604052806000801916815260200160008019168152602001600080191681525090565b815481835581811115610acd57818360005260206000209182019101610acc9190610ad2565b5b505050565b610af491905b80821115610af0576000816000905550600101610ad8565b5090565b905600a165627a7a72305820de9e3481e0a4d931d0b0a0a34b53b4315479499d7deb6724e5de6d1f439d44e70029`
// DeployContract deploys a new Ethereum contract, binding an instance of Contract to it.
func DeployContract(auth *bind.TransactOpts, backend bind.ContractBackend, _adminlist []common.Address) (common.Address, *types.Transaction, *Contract, error) {
diff --git a/contracts/registrar/contract/registrar.sol b/contracts/registrar/contract/registrar.sol
index 4f9fd57bcc..cb92b92d39 100644
--- a/contracts/registrar/contract/registrar.sol
+++ b/contracts/registrar/contract/registrar.sol
@@ -51,6 +51,9 @@ contract Registrar {
Public Functions
*/
constructor(address[] _adminlist) public {
+ // regard contract creator as a default admin.
+ admins[msg.sender] = 1;
+ adminList.push(msg.sender);
for (uint i = 0; i < _adminlist.length; i++) {
admins[_adminlist[i]] = 1;
adminList.push(_adminlist[i]);
@@ -113,6 +116,11 @@ contract Registrar {
if (_sectionIndex != latest + 1 && latest != 0) {
return false;
}
+ // Ensure the checkpoint is stable enough to be registered.
+ if (block.number < (_sectionIndex+1)*sectionSize+confirmations) {
+ return false;
+ }
+
checkpoints[_sectionIndex] = Checkpoint({
sectionHead: _sectionHead,
chtRoot: _chtRoot,
@@ -208,5 +216,11 @@ contract Registrar {
// Latest stored section id
// Note all registered checkpoint information should continuous with previous one.
uint latest;
+
+ // The frequency for creating a checkpoint
+ uint constant sectionSize = 32768;
+
+ // The number of confirmations needed before a checkpoint can be registered.
+ uint constant confirmations = 10000;
}
diff --git a/contracts/registrar/registrar.go b/contracts/registrar/registrar.go
new file mode 100644
index 0000000000..6860ef39ce
--- /dev/null
+++ b/contracts/registrar/registrar.go
@@ -0,0 +1,88 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package registrar
+
+import (
+ "errors"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/contracts/registrar/contract"
+ "github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
+)
+
+var (
+ MainNetAddr = common.HexToAddress("")
+ TestNetAddr = common.HexToAddress("0x3b934494985d17bcb49557671e1bc8ec32cccdd5") // Rinkeby
+)
+
+var errEventNotFound = errors.New("contract event not found")
+
+const (
+ sectionSize = 32768 // The frequency for creating a checkpoint
+ checkpointConfirmation = 10000 // The number of confirmations needed before a checkpoint becoming stable.
+)
+
+// Checkpoint represents a set of post-processed trie roots (CHT and BloomTrie) associated with
+// the appropriate section index and head hash.
+//
+// It is used to start light syncing from this checkpoint and avoid downloading the entire header chain
+// while still being able to securely access old headers/logs.
+type Checkpoint struct {
+ SectionIndex uint64
+ SectionHead common.Hash // Block Hash for the last block in the section
+ ChtRoot common.Hash // CHT(Canonical Hash Trie) root associated to the section
+ BloomTrieRoot common.Hash // Bloom Trie root associated to the section
+}
+
+type Registrar struct {
+ contract *contract.Contract
+}
+
+// NewRegistrar binds checkpoint contract and returns a registrar instance.
+func NewRegistrar(contractAddr common.Address, backend ethapi.Backend, lightMode bool) (*Registrar, error) {
+ contract, err := contract.NewContract(contractAddr, eth.NewContractBackend(backend, lightMode))
+ if err != nil {
+ return nil, err
+ }
+
+ return &Registrar{
+ contract: contract,
+ }, nil
+}
+
+// WatchNewCheckpointEvent watches new fired NewCheckpointEvent and delivers all matching events by result channel.
+func (registrar *Registrar) WatchNewCheckpointEvent(sink chan<- *contract.ContractNewCheckpointEvent) (event.Subscription, error) {
+ return registrar.contract.WatchNewCheckpointEvent(nil, sink, nil)
+}
+
+// FilterNewCheckpointEvent filters out NewCheckpointEvent for specific section number.
+func (registrar *Registrar) FilterNewCheckpointEvent(head uint64, section uint64) (*contract.ContractNewCheckpointEventIterator, error) {
+ start := (section + 1) * sectionSize
+ end := head - checkpointConfirmation
+ if end < start {
+ return nil, errEventNotFound
+ }
+ opt := &bind.FilterOpts{
+ Start: start,
+ End: &end,
+ }
+ return registrar.contract.FilterNewCheckpointEvent(opt, []*big.Int{big.NewInt(int64(section))})
+}
diff --git a/contracts/registrar/registrar_test.go b/contracts/registrar/registrar_test.go
new file mode 100644
index 0000000000..98f7dd1355
--- /dev/null
+++ b/contracts/registrar/registrar_test.go
@@ -0,0 +1,142 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package registrar
+
+import (
+ "math/big"
+ "reflect"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/contracts/registrar/contract"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/crypto"
+)
+
+var (
+ key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ addr = crypto.PubkeyToAddress(key.PublicKey)
+ emptyHash = [32]byte{}
+
+ trustedCheckpoint = Checkpoint{
+ SectionIndex: 0,
+ SectionHead: common.HexToHash("14c8639dfc32812ed20839f5a11993cd59b22e5226cb2179640ba5c1f0c08f87"),
+ ChtRoot: common.HexToHash("cf92fd2a79464354e8dae4d589ae92acdf90a3a4f8f7d8a3ec5fb9c114ae81cd"),
+ BloomTrieRoot: common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
+ }
+)
+
+func TestAdminManagement(t *testing.T) {
+ var (
+ adminCandidate = common.HexToAddress("0x123")
+ adminCandidate2 = common.HexToAddress("0x456")
+ )
+
+ // Deploy registrar contract
+ transactOpts := bind.NewKeyedTransactor(key)
+ contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}})
+ _, _, contract, err := contract.DeployContract(transactOpts, contractBackend, nil)
+ if err != nil {
+ t.Error("deploy registrar contract failed", err)
+ }
+ contractBackend.Commit()
+
+ // Test AddAdmin function
+ contract.AddAdmin(transactOpts, addr) // Contract should ignore the duplicate registration
+ contract.AddAdmin(transactOpts, adminCandidate)
+ contract.AddAdmin(transactOpts, adminCandidate2)
+ contractBackend.Commit()
+ adminList, err := contract.GetAllAdmin(nil)
+ if err != nil {
+ t.Error("fetch admin list failed", err)
+ }
+ if !reflect.DeepEqual(adminList, []common.Address{addr, adminCandidate, adminCandidate2}) {
+ t.Error("expect the returned admin list contain 3 address")
+ }
+
+ // Test RemoveAdmin function (remove at the middle)
+ contract.RemoveAdmin(transactOpts, adminCandidate)
+ contractBackend.Commit()
+ adminList, err = contract.GetAllAdmin(nil)
+ if err != nil {
+ t.Error("fetch admin list failed", err)
+ }
+ if !reflect.DeepEqual(adminList, []common.Address{addr, adminCandidate2}) {
+ t.Error("expect the returned admin list contain 3 address")
+ }
+
+ // Test RemoveAdmin function (remove at the head)
+ contract.RemoveAdmin(transactOpts, addr)
+ contractBackend.Commit()
+ adminList, err = contract.GetAllAdmin(nil)
+ if err != nil {
+ t.Error("fetch admin list failed", err)
+ }
+ if !reflect.DeepEqual(adminList, []common.Address{adminCandidate2}) {
+ t.Error("expect the returned admin list contain 3 address")
+ }
+
+ // Test unauthorized operation
+ contract.AddAdmin(transactOpts, adminCandidate)
+ contractBackend.Commit()
+ adminList, err = contract.GetAllAdmin(nil)
+ if err != nil {
+ t.Error("fetch admin list failed", err)
+ }
+ if !reflect.DeepEqual(adminList, []common.Address{adminCandidate2}) {
+ t.Error("expect the returned admin list contain 3 address")
+ }
+}
+
+func TestCheckpointRegister(t *testing.T) {
+ // Deploy registrar contract
+ transactOpts := bind.NewKeyedTransactor(key)
+ contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}})
+ _, _, contract, err := contract.DeployContract(transactOpts, contractBackend, []common.Address{addr})
+ if err != nil {
+ t.Error("deploy registrar contract failed", err)
+ }
+ contractBackend.Commit()
+
+ // Register an unstable checkpoint
+ contract.SetCheckpoint(transactOpts, big.NewInt(int64(trustedCheckpoint.SectionIndex)), trustedCheckpoint.SectionHead,
+ trustedCheckpoint.ChtRoot, trustedCheckpoint.BloomTrieRoot)
+ contractBackend.Commit()
+ head, chtRoot, bloomTrieRoot, err := contract.GetCheckpoint(nil, big.NewInt(int64(trustedCheckpoint.SectionIndex)))
+ if err != nil {
+ t.Error("fetch checkpoint failed", err)
+ }
+ if head != emptyHash || chtRoot != emptyHash || bloomTrieRoot != emptyHash {
+ t.Error("the unstable checkpoint is not allowed to be registered")
+ }
+
+ // Register a stable checkpoint
+ contractBackend.ShiftBlocks(sectionSize + checkpointConfirmation)
+ contract.SetCheckpoint(transactOpts, big.NewInt(int64(trustedCheckpoint.SectionIndex)), trustedCheckpoint.SectionHead,
+ trustedCheckpoint.ChtRoot, trustedCheckpoint.BloomTrieRoot)
+ contractBackend.Commit()
+ head, chtRoot, bloomTrieRoot, err = contract.GetCheckpoint(nil, big.NewInt(int64(trustedCheckpoint.SectionIndex)))
+ if err != nil {
+ t.Error("fetch checkpoint failed", err)
+ }
+ if !reflect.DeepEqual(head[:], trustedCheckpoint.SectionHead.Bytes()) || !reflect.DeepEqual(chtRoot[:], trustedCheckpoint.ChtRoot.Bytes()) ||
+ !reflect.DeepEqual(bloomTrieRoot[:], trustedCheckpoint.BloomTrieRoot.Bytes()) {
+ t.Error("expect the returned checkpoint should be same with the given one")
+ }
+}