diff --git a/eth/backend.go b/eth/backend.go index 5f7fc7066b..8b17d927ec 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -189,8 +189,8 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if eth.chainConfig.Posv != nil { c := eth.engine.(*posv.Posv) - // Hook sends tx sign to smartcontract after inserting block to chain. - importedHook := func(block *types.Block) error { + // Hook double validation + doubleValidateHook := func(block *types.Block) error { snap, err := c.GetSnapshot(eth.blockchain, block.Header()) if err != nil { if err == consensus.ErrUnknownAncestor { @@ -199,7 +199,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { return fmt.Errorf("Fail to get snapshot for sign tx validator: %v", err) } if _, authorized := snap.Signers[eth.etherbase]; authorized { - // double validation m2, err := getM2(snap, eth, block) if err != nil { return fmt.Errorf("Fail to validate M2 condition for importing block: %v", err) @@ -216,9 +215,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if len(txsSentFromM2) > 0 { for _, tx := range txsSentFromM2 { if tx.To().String() == common.BlockSigners { - if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil { - return fmt.Errorf("Fail to create tx sign for importing block: %v", err) - } return nil } } @@ -226,29 +222,32 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { //then wait until signTx from m2 comes into txPool txCh := make(chan core.TxPreEvent, txChanSize) subEvent := eth.txPool.SubscribeTxPreEvent(txCh) - G: select { case event := <-txCh: from, err := eth.txPool.GetSender(event.Tx) if (err == nil) && (event.Tx.To().String() == common.BlockSigners) && (from == m2) { - if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil { - return fmt.Errorf("Fail to create tx sign for importing block: %v", err) - } return nil } //timeout 10s case <-time.After(time.Duration(10) * time.Second): - break G + return fmt.Errorf("Time out waiting for confirmation from m2") } subEvent.Unsubscribe() - } else if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil { - return fmt.Errorf("Fail to create tx sign for importing block: %v", err) } - // end of double validation + return nil + } + return fmt.Errorf("This address is not authorized to validate block") + } + + signHook := func(block *types.Block) error { + if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil { + return fmt.Errorf("Fail to create tx sign for importing block: %v", err) } return nil } - eth.protocolManager.fetcher.SetImportedHook(importedHook) + + eth.protocolManager.fetcher.SetDoubleValidateHook(doubleValidateHook) + eth.protocolManager.fetcher.SetSignHook(signHook) // Hook prepares validators M2 for the current epoch c.HookValidator = func(header *types.Header, signers []common.Address) error { diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go index 94ac16e405..e75ecdbfa5 100644 --- a/eth/fetcher/fetcher.go +++ b/eth/fetcher/fetcher.go @@ -138,11 +138,12 @@ type Fetcher struct { dropPeer peerDropFn // Drops a peer for misbehaving // Testing hooks - announceChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a hash from the announce list - queueChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a block from the import queue - fetchingHook func([]common.Hash) // Method to call upon starting a block (eth/61) or header (eth/62) fetch - completingHook func([]common.Hash) // Method to call upon starting a block body fetch (eth/62) - importedHook func(*types.Block) error // Method to call upon successful block import (both eth/61 and eth/62) + announceChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a hash from the announce list + queueChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a block from the import queue + fetchingHook func([]common.Hash) // Method to call upon starting a block (eth/61) or header (eth/62) fetch + completingHook func([]common.Hash) // Method to call upon starting a block body fetch (eth/62) + doubleValidateHook func(*types.Block) error + signHook func(*types.Block) error } // New creates a block fetcher to retrieve blocks based on hash announcements. @@ -665,9 +666,9 @@ func (f *Fetcher) insert(peer string, block *types.Block) { f.dropPeer(peer) return } - // Invoke the imported hook to run double validation layer - if f.importedHook != nil { - if err := f.importedHook(block); err != nil { + // Invoke the dv hook to run double validation layer + if f.doubleValidateHook != nil { + if err := f.doubleValidateHook(block); err != nil { log.Error("Double validation failed", "err", err, "Discard this block!") return } @@ -678,6 +679,14 @@ func (f *Fetcher) insert(peer string, block *types.Block) { log.Debug("Propagated block import failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) return } + + if f.signHook != nil { + if err := f.signHook(block); err != nil { + log.Error("Can't sign the imported block", "err", err) + return + } + } + // If import succeeded, broadcast the block propAnnounceOutTimer.UpdateSince(block.ReceivedAt) go f.broadcastBlock(block, false) @@ -739,7 +748,12 @@ func (f *Fetcher) forgetBlock(hash common.Hash) { } } -// Bind import hook when block imported into chain. -func (f *Fetcher) SetImportedHook(importedHook func(*types.Block) error) { - f.importedHook = importedHook +// Bind double validate hook before block imported into chain. +func (f *Fetcher) SetDoubleValidateHook(doubleValidateHook func(*types.Block) error) { + f.doubleValidateHook = doubleValidateHook +} + +// Bind double validate hook before block imported into chain. +func (f *Fetcher) SetSignHook(signHook func(*types.Block) error) { + f.signHook = signHook } diff --git a/eth/fetcher/fetcher_test.go b/eth/fetcher/fetcher_test.go index fc16a0f5f3..af9a5a6b44 100644 --- a/eth/fetcher/fetcher_test.go +++ b/eth/fetcher/fetcher_test.go @@ -288,7 +288,7 @@ func testSequentialAnnouncements(t *testing.T, protocol int) { // Iteratively announce blocks until all are imported imported := make(chan *types.Block) - tester.fetcher.importedHook = func(block *types.Block) error { + tester.fetcher.signHook = func(block *types.Block) error { imported <- block return nil } @@ -329,7 +329,7 @@ func testConcurrentAnnouncements(t *testing.T, protocol int) { } // Iteratively announce blocks until all are imported imported := make(chan *types.Block) - tester.fetcher.importedHook = func(block *types.Block) error { + tester.fetcher.signHook = func(block *types.Block) error { imported <- block return nil } @@ -369,7 +369,7 @@ func testOverlappingAnnouncements(t *testing.T, protocol int) { for i := 0; i < overlap; i++ { imported <- nil } - tester.fetcher.importedHook = func(block *types.Block) error { + tester.fetcher.signHook = func(block *types.Block) error { imported <- block return nil } @@ -446,7 +446,7 @@ func testRandomArrivalImport(t *testing.T, protocol int) { // Iteratively announce blocks, skipping one entry imported := make(chan *types.Block, len(hashes)-1) - tester.fetcher.importedHook = func(block *types.Block) error { + tester.fetcher.signHook = func(block *types.Block) error { imported <- block return nil } @@ -480,7 +480,7 @@ func testQueueGapFill(t *testing.T, protocol int) { // Iteratively announce blocks, skipping one entry imported := make(chan *types.Block, len(hashes)-1) - tester.fetcher.importedHook = func(block *types.Block) error { + tester.fetcher.signHook = func(block *types.Block) error { imported <- block return nil } @@ -520,7 +520,7 @@ func testImportDeduplication(t *testing.T, protocol int) { fetching := make(chan []common.Hash) imported := make(chan *types.Block, len(hashes)-1) tester.fetcher.fetchingHook = func(hashes []common.Hash) { fetching <- hashes } - tester.fetcher.importedHook = func(block *types.Block) error { + tester.fetcher.signHook = func(block *types.Block) error { imported <- block return nil } @@ -632,7 +632,7 @@ func testInvalidNumberAnnouncement(t *testing.T, protocol int) { badBodyFetcher := tester.makeBodyFetcher("bad", blocks, 0) imported := make(chan *types.Block) - tester.fetcher.importedHook = func(block *types.Block) error { + tester.fetcher.signHook = func(block *types.Block) error { imported <- block return nil } @@ -687,7 +687,7 @@ func testEmptyBlockShortCircuit(t *testing.T, protocol int) { tester.fetcher.completingHook = func(hashes []common.Hash) { completing <- hashes } imported := make(chan *types.Block) - tester.fetcher.importedHook = func(block *types.Block) error { + tester.fetcher.signHook = func(block *types.Block) error { imported <- block return nil } @@ -720,7 +720,7 @@ func testHashMemoryExhaustionAttack(t *testing.T, protocol int) { tester := newTester() imported, announces := make(chan *types.Block), int32(0) - tester.fetcher.importedHook = func(block *types.Block) error { + tester.fetcher.signHook = func(block *types.Block) error { imported <- block return nil } @@ -770,7 +770,7 @@ func TestBlockMemoryExhaustionAttack(t *testing.T) { tester := newTester() imported, enqueued := make(chan *types.Block), int32(0) - tester.fetcher.importedHook = func(block *types.Block) error { + tester.fetcher.signHook = func(block *types.Block) error { imported <- block return nil }