mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
cmd, contracts, les: discard stale checkpoint
This commit is contained in:
parent
8d1972d793
commit
ad66858ac1
4 changed files with 39 additions and 94 deletions
|
|
@ -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
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue