cmd, contracts, les: discard stale checkpoint

This commit is contained in:
rjl493456442 2019-04-25 19:21:21 +08:00
parent 8d1972d793
commit ad66858ac1
4 changed files with 39 additions and 94 deletions

View file

@ -19,7 +19,6 @@ package main
import (
"errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
@ -46,7 +45,6 @@ var commandQueryCheckpoint = cli.Command{
Fetch the registered checkpoint with the specified index.
`,
Flags: []cli.Flag{
checkpointIndexFlag,
clientURLFlag,
},
Action: utils.MigrateFlags(queryCheckpoint),
@ -84,20 +82,11 @@ func queryAdmin(ctx *cli.Context) error {
// registrar contract.
func queryCheckpoint(ctx *cli.Context) error {
contract := setupContract(setupDialContext(ctx))
if ctx.GlobalIsSet(checkpointIndexFlag.Name) {
index := ctx.GlobalInt64(checkpointIndexFlag.Name)
checkpoint, height, err := contract.Contract().GetCheckpoint(nil, big.NewInt(index))
if err != nil {
return err
}
fmt.Printf("Checkpoint(registered at height #%d) %d => %s\n", height, index, common.Hash(checkpoint).Hex())
} else {
index, checkpoint, height, err := contract.Contract().GetLatestCheckpoint(nil)
if err != nil {
return err
}
fmt.Printf("Latest checkpoint(registered at height #%d) %d => %s\n", height, index, common.Hash(checkpoint).Hex())
index, checkpoint, height, err := contract.Contract().GetLatestCheckpoint(nil)
if err != nil {
return err
}
fmt.Printf("Latest checkpoint(registered at height #%d) %d => %s\n", height, index, common.Hash(checkpoint).Hex())
return nil
}

File diff suppressed because one or more lines are too long

View file

@ -68,22 +68,7 @@ contract Registrar {
view
public
returns(uint, bytes32, uint) {
(bytes32 hash, uint height) = GetCheckpoint(latest);
return (latest, hash, height);
}
/**
* @dev Get a stable checkpoint information with specified section index.
* @param _sectionIndex section index
* @return checkpoint hash
* @return the associated register block height
*/
function GetCheckpoint(uint _sectionIndex)
view
public
returns(bytes32, uint)
{
return (checkpoints[_sectionIndex], register_height[_sectionIndex]);
return (sectionIndex, hash, height);
}
/**
@ -115,7 +100,7 @@ contract Registrar {
return false;
}
// Filter out stale announcement
if (_sectionIndex == latest && (latest != 0 || register_height[0] != 0)) {
if (_sectionIndex == sectionIndex && (sectionIndex != 0 || height != 0)) {
return false;
}
// Filter out invalid announcement
@ -134,7 +119,15 @@ contract Registrar {
bool isNew = (old == "");
pending_proposal.usermap[msg.sender] = _hash;
if (!isNew) {
if (isNew) {
// New checkpoint announcement
pending_proposal.count += 1;
pending_proposal.index = _sectionIndex;
pending_proposal.votemap[_hash].push(Vote({
addr: msg.sender,
sig: _sig
}));
} else {
// Checkpoint modification
Vote[] storage votes = pending_proposal.votemap[old];
for (uint i = 0; i < votes.length - 1; i++) {
@ -149,21 +142,14 @@ contract Registrar {
addr: msg.sender,
sig: _sig
}));
} else {
// New checkpoint announcement
pending_proposal.count += 1;
pending_proposal.index = _sectionIndex;
pending_proposal.votemap[_hash].push(Vote({
addr: msg.sender,
sig: _sig
}));
}
if (pending_proposal.votemap[_hash].length < threshold) {
return true;
}
checkpoints[_sectionIndex] = _hash;
register_height[_sectionIndex] = block.number;
latest = _sectionIndex;
// Update latest checkpoint
hash = _hash;
height = block.number;
sectionIndex = _sectionIndex;
bytes memory sigs;
for (uint idx = 0; idx < threshold; idx++) {
@ -243,15 +229,15 @@ contract Registrar {
// A list of admin users so that we can obtain all admin users.
address[] adminList;
// Registered checkpoint information
mapping(uint => bytes32) checkpoints;
// Latest stored section id
// Note all registered checkpoint information should continuous with previous one.
uint latest;
uint sectionIndex;
// The block height associated with latest registered checkpoint.
mapping(uint => uint) register_height;
uint height;
// The hash of latest registered checkpoint.
bytes32 hash;
// The frequency for creating a checkpoint
//

View file

@ -18,7 +18,6 @@
package les
import (
"math/big"
"sync/atomic"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
@ -87,21 +86,22 @@ func (reg *checkpointRegistrar) isRunning() bool {
// stableCheckpoint returns the stable checkpoint which generated by local indexers
// and announced by trusted signers.
func (reg *checkpointRegistrar) stableCheckpoint() (*params.TrustedCheckpoint, uint64) {
latest, hash, _, err := reg.contract.Contract().GetLatestCheckpoint(nil)
latest, hash, height, err := reg.contract.Contract().GetLatestCheckpoint(nil)
// Short circuit if the checkpoint contract is empty.
if err != nil || latest.Uint64() == 0 && hash == [32]byte{} {
return nil, 0
}
index := latest.Uint64()
for {
local := reg.getLocal(index)
hash, height, err := reg.contract.Contract().GetCheckpoint(nil, big.NewInt(int64(index)))
if err == nil && local.HashEqual(common.Hash(hash)) {
return &local, height.Uint64()
}
if index == 0 {
break
}
index -= 1
local := reg.getLocal(latest.Uint64())
// The following scenarios may occur:
//
// * local node is out of sync so that it doesn't have the
// checkpoint which registered in the contract.
// * local checkpoint doesn't match with the registered one.
//
// In both cases, server won't send the **stable** checkpoint
// to the client(no worry, client can use hardcoded one instead).
if local.HashEqual(common.Hash(hash)) {
return &local, height.Uint64()
}
return nil, 0
}