Skip to content

Commit c6e8652

Browse files
committed
implement trust protocol and verify node
1 parent 359906c commit c6e8652

19 files changed

+785
-13
lines changed

common/types.go

+15
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,21 @@ func (a *Address) UnmarshalGraphQL(input interface{}) error {
354354
return err
355355
}
356356

357+
// AddressSlice is used for sort
358+
type AddressSlice []Address
359+
360+
func (s AddressSlice) Len() int {
361+
return len(s)
362+
}
363+
364+
func (s AddressSlice) Less(i, j int) bool {
365+
return s[i].Hex() < s[j].Hex()
366+
}
367+
368+
func (s AddressSlice) Swap(i, j int) {
369+
s[i], s[j] = s[j], s[i]
370+
}
371+
357372
// UnprefixedAddress allows marshaling an Address without 0x prefix.
358373
type UnprefixedAddress Address
359374

core/blockchain.go

+114
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import (
2828
"sync/atomic"
2929
"time"
3030

31+
"golang.org/x/crypto/sha3"
32+
3133
lru "github.com/hashicorp/golang-lru"
3234

3335
"github.com/ethereum/go-ethereum/common"
@@ -1798,6 +1800,12 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
17981800
diffLayer.Receipts = receipts
17991801
diffLayer.BlockHash = block.Hash()
18001802
diffLayer.Number = block.NumberU64()
1803+
1804+
sort.Sort(types.DiffCodeSlice(diffLayer.Codes))
1805+
sort.Sort(common.AddressSlice(diffLayer.Destructs))
1806+
sort.Sort(types.DiffAccountSlice(diffLayer.Accounts))
1807+
sort.Sort(types.DiffStorageSlice(diffLayer.Storages))
1808+
18011809
bc.cacheDiffLayer(diffLayer)
18021810
}
18031811

@@ -3111,3 +3119,109 @@ func EnablePersistDiff(limit uint64) BlockChainOption {
31113119
return chain
31123120
}
31133121
}
3122+
3123+
func (bc *BlockChain) GetRootByDiffHash(blockNumber uint64, blockHash common.Hash, diffHash common.Hash) (*types.VerifyResult, error) {
3124+
var res types.VerifyResult
3125+
res.BlockNumber = blockNumber
3126+
res.BlockHash = blockHash
3127+
3128+
if blockNumber > bc.CurrentHeader().Number.Uint64()+11 {
3129+
res.Status = types.StatusBlockTooNew
3130+
return &res, nil
3131+
} else if blockNumber > bc.CurrentHeader().Number.Uint64() {
3132+
res.Status = types.StatusBlockNewer
3133+
return &res, nil
3134+
}
3135+
3136+
diff := bc.GetTrustedDiffLayer(blockHash)
3137+
if diff != nil {
3138+
if diff.DiffHash == (common.Hash{}) {
3139+
hash, err := GetTrustedDiffHash(diff)
3140+
if err != nil {
3141+
res.Status = types.StatusUnexpectedError
3142+
return &res, err
3143+
}
3144+
3145+
diff.DiffHash = hash
3146+
}
3147+
3148+
if diffHash != diff.DiffHash {
3149+
res.Status = types.StatusDiffHashMismatch
3150+
return &res, nil
3151+
}
3152+
3153+
header := bc.GetHeaderByHash(blockHash)
3154+
if header == nil {
3155+
res.Status = types.StatusUnexpectedError
3156+
return &res, fmt.Errorf("unexpected error, header not found")
3157+
}
3158+
res.Status = types.StatusFullVerified
3159+
res.Root = header.Root
3160+
return &res, nil
3161+
}
3162+
3163+
header := bc.GetHeaderByHash(blockHash)
3164+
if header == nil {
3165+
if blockNumber > bc.CurrentHeader().Number.Uint64()-11 {
3166+
res.Status = types.StatusPossibleFork
3167+
return &res, nil
3168+
}
3169+
3170+
res.Status = types.StatusImpossibleFork
3171+
return &res, nil
3172+
}
3173+
3174+
res.Status = types.StatusUntrustedVerified
3175+
res.Root = header.Root
3176+
return &res, nil
3177+
}
3178+
3179+
func (bc *BlockChain) GetTrustedDiffLayer(blockHash common.Hash) *types.DiffLayer {
3180+
var diff *types.DiffLayer
3181+
if cached, ok := bc.diffLayerCache.Get(blockHash); ok {
3182+
diff = cached.(*types.DiffLayer)
3183+
return diff
3184+
}
3185+
3186+
diffStore := bc.db.DiffStore()
3187+
if diffStore != nil {
3188+
diff = rawdb.ReadDiffLayer(diffStore, blockHash)
3189+
}
3190+
return diff
3191+
}
3192+
3193+
func GetTrustedDiffHash(d *types.DiffLayer) (common.Hash, error) {
3194+
diff := &types.ExtDiffLayer{
3195+
BlockHash: d.BlockHash,
3196+
Receipts: make([]*types.ReceiptForStorage, 0),
3197+
Number: d.Number,
3198+
Codes: d.Codes,
3199+
Destructs: d.Destructs,
3200+
Accounts: d.Accounts,
3201+
Storages: d.Storages,
3202+
}
3203+
3204+
for index, account := range diff.Accounts {
3205+
full, err := snapshot.FullAccount(account.Blob)
3206+
if err != nil {
3207+
return common.Hash{}, fmt.Errorf("decode full account error: %v", err)
3208+
}
3209+
// set account root to empty root
3210+
diff.Accounts[index].Blob = snapshot.SlimAccountRLP(full.Nonce, full.Balance, common.Hash{}, full.CodeHash)
3211+
}
3212+
3213+
rawData, err := rlp.EncodeToBytes(diff)
3214+
if err != nil {
3215+
return common.Hash{}, fmt.Errorf("encode new diff error: %v", err)
3216+
}
3217+
3218+
hasher := sha3.NewLegacyKeccak256()
3219+
_, err = hasher.Write(rawData)
3220+
if err != nil {
3221+
return common.Hash{}, fmt.Errorf("hasher write error: %v", err)
3222+
}
3223+
3224+
var hash common.Hash
3225+
hasher.Sum(hash[:0])
3226+
return hash, nil
3227+
}

core/state/state_object.go

+7
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,13 @@ func (s *StateObject) updateTrie(db Database) Trie {
391391

392392
// UpdateRoot sets the trie root to the current root hash of
393393
func (s *StateObject) updateRoot(db Database) {
394+
// If node runs in no trie mode, set root to empty.
395+
defer func() {
396+
if db.NoTries() {
397+
s.data.Root = common.Hash{}
398+
}
399+
}()
400+
394401
// If nothing changed, don't bother with hashing anything
395402
if s.updateTrie(db) == nil {
396403
return

core/state/statedb.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -1575,8 +1575,12 @@ func (s *StateDB) SnapToDiffLayer() ([]common.Address, []types.DiffAccount, []ty
15751575
for accountHash, storage := range s.snapStorage {
15761576
keys := make([]string, 0, len(storage))
15771577
values := make([][]byte, 0, len(storage))
1578-
for k, v := range storage {
1578+
for k, _ := range storage {
15791579
keys = append(keys, k)
1580+
}
1581+
sort.Strings(keys)
1582+
for _, k := range keys {
1583+
v := storage[k]
15801584
values = append(values, v)
15811585
}
15821586
storages = append(storages, types.DiffStorage{

core/types/block.go

+86-3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,40 @@ var (
4040
EmptyUncleHash = rlpHash([]*Header(nil))
4141
)
4242

43+
type VerifyStatus struct {
44+
Code uint16
45+
Msg string
46+
}
47+
48+
var (
49+
// StatusVerified means the processing of request going as expected and found the root correctly.
50+
StatusVerified = VerifyStatus{Code: 0x100}
51+
StatusFullVerified = VerifyStatus{Code: 0x101, Msg: "state root full verified"}
52+
StatusUntrustedVerified = VerifyStatus{Code: 0x102, Msg: "state root untrusted verified, because of difflayer not found"}
53+
54+
// StatusFailed means the request has something wrong.
55+
StatusFailed = VerifyStatus{Code: 0x200}
56+
StatusDiffHashMismatch = VerifyStatus{Code: 0x201, Msg: "verify failed because of blockhash mismatch with diffhash"}
57+
StatusImpossibleFork = VerifyStatus{Code: 0x202, Msg: "verify failed because of impossible fork detected"}
58+
59+
// StatusUncertain means verify node can't give a certain result of the request.
60+
StatusUncertain = VerifyStatus{Code: 0x300}
61+
StatusBlockTooNew = VerifyStatus{Code: 0x301, Msg: "can’t verify because of block number larger than current height more than 11"}
62+
StatusBlockNewer = VerifyStatus{Code: 0x302, Msg: "can’t verify because of block number larger than current height"}
63+
StatusPossibleFork = VerifyStatus{Code: 0x303, Msg: "can’t verify because of possible fork detected"}
64+
StatusRequestTooBusy = VerifyStatus{Code: 0x304, Msg: "can’t verify because of request too busy"}
65+
66+
// StatusUnexpectedError is unexpected internal error.
67+
StatusUnexpectedError = VerifyStatus{Code: 0x400, Msg: "can’t verify because of unexpected internal error"}
68+
)
69+
70+
type VerifyResult struct {
71+
Status VerifyStatus
72+
BlockNumber uint64
73+
BlockHash common.Hash
74+
Root common.Hash
75+
}
76+
4377
// A BlockNonce is a 64-bit hash which proves (combined with the
4478
// mix-hash) that a sufficient amount of computation has been carried
4579
// out on a block.
@@ -383,7 +417,7 @@ type DiffLayer struct {
383417
DiffHash common.Hash
384418
}
385419

386-
type extDiffLayer struct {
420+
type ExtDiffLayer struct {
387421
BlockHash common.Hash
388422
Number uint64
389423
Receipts []*ReceiptForStorage // Receipts are duplicated stored to simplify the logic
@@ -395,7 +429,7 @@ type extDiffLayer struct {
395429

396430
// DecodeRLP decodes the Ethereum
397431
func (d *DiffLayer) DecodeRLP(s *rlp.Stream) error {
398-
var ed extDiffLayer
432+
var ed ExtDiffLayer
399433
if err := s.Decode(&ed); err != nil {
400434
return err
401435
}
@@ -415,7 +449,7 @@ func (d *DiffLayer) EncodeRLP(w io.Writer) error {
415449
for i, receipt := range d.Receipts {
416450
storageReceipts[i] = (*ReceiptForStorage)(receipt)
417451
}
418-
return rlp.Encode(w, extDiffLayer{
452+
return rlp.Encode(w, ExtDiffLayer{
419453
BlockHash: d.BlockHash,
420454
Number: d.Number,
421455
Receipts: storageReceipts,
@@ -443,17 +477,66 @@ type DiffCode struct {
443477
Code []byte
444478
}
445479

480+
// DiffCodeSlice is used for sort
481+
type DiffCodeSlice []DiffCode
482+
483+
func (s DiffCodeSlice) Len() int {
484+
return len(s)
485+
}
486+
487+
func (s DiffCodeSlice) Less(i, j int) bool {
488+
return s[i].Hash.Hex() < s[j].Hash.Hex()
489+
}
490+
491+
func (s DiffCodeSlice) Swap(i, j int) {
492+
s[i].Hash, s[j].Hash = s[j].Hash, s[i].Hash
493+
s[i].Code, s[j].Code = s[j].Code, s[i].Code
494+
}
495+
446496
type DiffAccount struct {
447497
Account common.Address
448498
Blob []byte
449499
}
450500

501+
// DiffAccountSlice is used for sort
502+
type DiffAccountSlice []DiffAccount
503+
504+
func (s DiffAccountSlice) Len() int {
505+
return len(s)
506+
}
507+
508+
func (s DiffAccountSlice) Less(i, j int) bool {
509+
return s[i].Account.Hex() < s[j].Account.Hex()
510+
}
511+
512+
func (s DiffAccountSlice) Swap(i, j int) {
513+
s[i].Account, s[j].Account = s[j].Account, s[i].Account
514+
s[i].Blob, s[j].Blob = s[j].Blob, s[i].Blob
515+
}
516+
451517
type DiffStorage struct {
452518
Account common.Address
453519
Keys []string
454520
Vals [][]byte
455521
}
456522

523+
// DiffStorageSlice is used for sort
524+
type DiffStorageSlice []DiffStorage
525+
526+
func (s DiffStorageSlice) Len() int {
527+
return len(s)
528+
}
529+
530+
func (s DiffStorageSlice) Less(i, j int) bool {
531+
return s[i].Account.Hex() < s[j].Account.Hex()
532+
}
533+
534+
func (s DiffStorageSlice) Swap(i, j int) {
535+
s[i].Account, s[j].Account = s[j].Account, s[i].Account
536+
s[i].Keys, s[j].Keys = s[j].Keys, s[i].Keys
537+
s[i].Vals, s[j].Vals = s[j].Vals, s[i].Vals
538+
}
539+
457540
type DiffAccountsInTx struct {
458541
TxHash common.Hash
459542
Accounts map[common.Address]*big.Int

eth/backend.go

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"sync/atomic"
2727
"time"
2828

29+
"github.com/ethereum/go-ethereum/eth/protocols/trust"
30+
2931
"github.com/ethereum/go-ethereum/accounts"
3032
"github.com/ethereum/go-ethereum/common"
3133
"github.com/ethereum/go-ethereum/common/hexutil"
@@ -554,6 +556,7 @@ func (s *Ethereum) Protocols() []p2p.Protocol {
554556
}
555557
// diff protocol can still open without snap protocol
556558
protos = append(protos, diff.MakeProtocols((*diffHandler)(s.handler), s.snapDialCandidates)...)
559+
protos = append(protos, trust.MakeProtocols((*trustHandler)(s.handler), s.snapDialCandidates)...)
557560
return protos
558561
}
559562

eth/handler.go

+23-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424
"sync/atomic"
2525
"time"
2626

27+
"github.com/ethereum/go-ethereum/eth/protocols/trust"
28+
2729
"github.com/ethereum/go-ethereum/common"
2830
"github.com/ethereum/go-ethereum/core"
2931
"github.com/ethereum/go-ethereum/core/forkid"
@@ -269,6 +271,11 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
269271
peer.Log().Error("Diff extension barrier failed", "err", err)
270272
return err
271273
}
274+
trust, err := h.peers.waitTrustExtension(peer)
275+
if err != nil {
276+
peer.Log().Error("Trust extension barrier failed", "err", err)
277+
return err
278+
}
272279
// TODO(karalabe): Not sure why this is needed
273280
if !h.chainSync.handlePeerEvent(peer) {
274281
return p2p.DiscQuitting
@@ -309,7 +316,7 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
309316
peer.Log().Debug("Ethereum peer connected", "name", peer.Name())
310317

311318
// Register the peer locally
312-
if err := h.peers.registerPeer(peer, snap, diff); err != nil {
319+
if err := h.peers.registerPeer(peer, snap, diff, trust); err != nil {
313320
peer.Log().Error("Ethereum peer registration failed", "err", err)
314321
return err
315322
}
@@ -395,6 +402,21 @@ func (h *handler) runDiffExtension(peer *diff.Peer, handler diff.Handler) error
395402
return handler(peer)
396403
}
397404

405+
// runTrustExtension registers a `trust` peer into the joint eth/trust peerset and
406+
// starts handling inbound messages. As `trust` is only a satellite protocol to
407+
// `eth`, all subsystem registrations and lifecycle management will be done by
408+
// the main `eth` handler to prevent strange races.
409+
func (h *handler) runTrustExtension(peer *trust.Peer, handler trust.Handler) error {
410+
h.peerWG.Add(1)
411+
defer h.peerWG.Done()
412+
413+
if err := h.peers.registerTrustExtension(peer); err != nil {
414+
peer.Log().Error("Trust extension registration failed", "err", err)
415+
return err
416+
}
417+
return handler(peer)
418+
}
419+
398420
// removePeer unregisters a peer from the downloader and fetchers, removes it from
399421
// the set of tracked peers and closes the network connection to it.
400422
func (h *handler) removePeer(id string) {

0 commit comments

Comments
 (0)