diff options
author | Sonic <sonic@dexon.org> | 2018-12-04 16:13:41 +0800 |
---|---|---|
committer | Wei-Ning Huang <w@byzantine-lab.io> | 2019-06-12 17:27:19 +0800 |
commit | 5d031e08ed2758eb7fa9c2d9c107204f93ae0733 (patch) | |
tree | 3a7ed42404b9b9ace5424578c7b2753444014417 /dex/downloader/downloader_test.go | |
parent | 122e398cd89925216226f8f5a194c93bf8921897 (diff) | |
download | go-tangerine-5d031e08ed2758eb7fa9c2d9c107204f93ae0733.tar go-tangerine-5d031e08ed2758eb7fa9c2d9c107204f93ae0733.tar.gz go-tangerine-5d031e08ed2758eb7fa9c2d9c107204f93ae0733.tar.bz2 go-tangerine-5d031e08ed2758eb7fa9c2d9c107204f93ae0733.tar.lz go-tangerine-5d031e08ed2758eb7fa9c2d9c107204f93ae0733.tar.xz go-tangerine-5d031e08ed2758eb7fa9c2d9c107204f93ae0733.tar.zst go-tangerine-5d031e08ed2758eb7fa9c2d9c107204f93ae0733.zip |
dex: replace total difficulty with block number (#73)
In dexon, we don't "mine" and the blockchain won't and shouldn't fork, so
there is no difficulty concept, just replace it with block number.
Note: this commit only replace total difficulty related logic and code
in dex, dex/downloader package.
Diffstat (limited to 'dex/downloader/downloader_test.go')
-rw-r--r-- | dex/downloader/downloader_test.go | 105 |
1 files changed, 51 insertions, 54 deletions
diff --git a/dex/downloader/downloader_test.go b/dex/downloader/downloader_test.go index c5e1451f5..0d92ad97f 100644 --- a/dex/downloader/downloader_test.go +++ b/dex/downloader/downloader_test.go @@ -19,7 +19,6 @@ package downloader import ( "errors" "fmt" - "math/big" "sync" "sync/atomic" "testing" @@ -56,7 +55,6 @@ type downloadTester struct { ownHeaders map[common.Hash]*types.Header // Headers belonging to the tester ownBlocks map[common.Hash]*types.Block // Blocks belonging to the tester ownReceipts map[common.Hash]types.Receipts // Receipts belonging to the tester - ownChainTd map[common.Hash]*big.Int // Total difficulties of the blocks in the local chain lock sync.RWMutex } @@ -71,7 +69,6 @@ func newTester() *downloadTester { ownHeaders: map[common.Hash]*types.Header{testGenesis.Hash(): testGenesis.Header()}, ownBlocks: map[common.Hash]*types.Block{testGenesis.Hash(): testGenesis}, ownReceipts: map[common.Hash]types.Receipts{testGenesis.Hash(): nil}, - ownChainTd: map[common.Hash]*big.Int{testGenesis.Hash(): testGenesis.Difficulty()}, } tester.stateDb = ethdb.NewMemDatabase() tester.stateDb.Put(testGenesis.Root().Bytes(), []byte{0x00}) @@ -86,17 +83,17 @@ func (dl *downloadTester) terminate() { } // sync starts synchronizing with a remote peer, blocking until it completes. -func (dl *downloadTester) sync(id string, td *big.Int, mode SyncMode) error { +func (dl *downloadTester) sync(id string, number uint64, mode SyncMode) error { dl.lock.RLock() hash := dl.peers[id].chain.headBlock().Hash() - // If no particular TD was requested, load from the peer's blockchain - if td == nil { - td = dl.peers[id].chain.td(hash) + // If no particular number was requested, load from the peer's blockchain + if number == 0 { + number, _ = dl.peers[id].chain.hashToNumber(hash) } dl.lock.RUnlock() // Synchronise with the chosen peer and ensure proper cleanup afterwards - err := dl.downloader.synchronise(id, hash, td, mode) + err := dl.downloader.synchronise(id, hash, number, mode) select { case <-dl.downloader.cancelCh: // Ok, downloader fully cancelled after sync cycle @@ -202,14 +199,6 @@ func (dl *downloadTester) FastSyncCommitHead(hash common.Hash) error { return fmt.Errorf("non existent block: %x", hash[:4]) } -// GetTd retrieves the block's total difficulty from the canonical chain. -func (dl *downloadTester) GetTd(hash common.Hash, number uint64) *big.Int { - dl.lock.RLock() - defer dl.lock.RUnlock() - - return dl.ownChainTd[hash] -} - // InsertDexonHeaderChain injects a new batch of headers into the simulated chain. func (dl *downloadTester) InsertDexonHeaderChain(headers []*types.HeaderWithGovState, verifierCache *dexCore.TSigVerifierCache) (i int, err error) { dl.lock.Lock() @@ -234,7 +223,6 @@ func (dl *downloadTester) InsertDexonHeaderChain(headers []*types.HeaderWithGovS } dl.ownHashes = append(dl.ownHashes, header.Hash()) dl.ownHeaders[header.Hash()] = header.Header - dl.ownChainTd[header.Hash()] = new(big.Int).Add(dl.ownChainTd[header.ParentHash], header.Difficulty) } return len(headers), nil } @@ -256,7 +244,6 @@ func (dl *downloadTester) InsertDexonChain(blocks types.Blocks) (i int, err erro } dl.ownBlocks[block.Hash()] = block dl.stateDb.Put(block.Root().Bytes(), []byte{0x00}) - dl.ownChainTd[block.Hash()] = new(big.Int).Add(dl.ownChainTd[block.ParentHash()], block.Difficulty()) } return len(blocks), nil } @@ -288,7 +275,6 @@ func (dl *downloadTester) Rollback(hashes []common.Hash) { if dl.ownHashes[len(dl.ownHashes)-1] == hashes[i] { dl.ownHashes = dl.ownHashes[:len(dl.ownHashes)-1] } - delete(dl.ownChainTd, hashes[i]) delete(dl.ownHeaders, hashes[i]) delete(dl.ownReceipts, hashes[i]) delete(dl.ownBlocks, hashes[i]) @@ -324,9 +310,10 @@ type downloadTesterPeer struct { // Head constructs a function to retrieve a peer's current head hash // and total difficulty. -func (dlp *downloadTesterPeer) Head() (common.Hash, *big.Int) { +func (dlp *downloadTesterPeer) Head() (common.Hash, uint64) { b := dlp.chain.headBlock() - return b.Hash(), dlp.chain.td(b.Hash()) + number, _ := dlp.chain.hashToNumber(b.Hash()) + return b.Hash(), number } // RequestHeadersByHash constructs a GetBlockHeaders function based on a hashed @@ -457,7 +444,7 @@ func testCanonicalSynchronisation(t *testing.T, protocol int, mode SyncMode) { tester.newPeer("peer", protocol, chain) // Synchronise with the peer and make sure all relevant data was retrieved - if err := tester.sync("peer", nil, mode); err != nil { + if err := tester.sync("peer", 0, mode); err != nil { t.Fatalf("failed to synchronise blocks: %v", err) } assertOwnChain(t, tester, chain.len()) @@ -489,7 +476,7 @@ func testThrottling(t *testing.T, protocol int, mode SyncMode) { // Start a synchronisation concurrently errc := make(chan error) go func() { - errc <- tester.sync("peer", nil, mode) + errc <- tester.sync("peer", 0, mode) }() // Iteratively take some blocks, always checking the retrieval count for { @@ -604,7 +591,7 @@ func testCancel(t *testing.T, protocol int, mode SyncMode) { t.Errorf("download queue not idle") } // Synchronise with the peer, but cancel afterwards - if err := tester.sync("peer", nil, mode); err != nil { + if err := tester.sync("peer", 0, mode); err != nil { t.Fatalf("failed to synchronise blocks: %v", err) } tester.downloader.Cancel() @@ -635,7 +622,7 @@ func testMultiSynchronisation(t *testing.T, protocol int, mode SyncMode) { id := fmt.Sprintf("peer #%d", i) tester.newPeer(id, protocol, chain.shorten(chain.len()/(i+1))) } - if err := tester.sync("peer #0", nil, mode); err != nil { + if err := tester.sync("peer #0", 0, mode); err != nil { t.Fatalf("failed to synchronise blocks: %v", err) } assertOwnChain(t, tester, chain.len()) @@ -665,7 +652,7 @@ func testMultiProtoSync(t *testing.T, protocol int, mode SyncMode) { tester.newPeer("peer 64", 64, chain) // Synchronise with the requested peer and make sure all blocks were retrieved - if err := tester.sync(fmt.Sprintf("peer %d", protocol), nil, mode); err != nil { + if err := tester.sync(fmt.Sprintf("peer %d", protocol), 0, mode); err != nil { t.Fatalf("failed to synchronise blocks: %v", err) } assertOwnChain(t, tester, chain.len()) @@ -707,7 +694,7 @@ func testEmptyShortCircuit(t *testing.T, protocol int, mode SyncMode) { atomic.AddInt32(&receiptsHave, int32(len(headers))) } // Synchronise with the peer and make sure all blocks were retrieved - if err := tester.sync("peer", nil, mode); err != nil { + if err := tester.sync("peer", 0, mode); err != nil { t.Fatalf("failed to synchronise blocks: %v", err) } assertOwnChain(t, tester, chain.len()) @@ -752,12 +739,12 @@ func testMissingHeaderAttack(t *testing.T, protocol int, mode SyncMode) { delete(brokenChain.headerm, brokenChain.chain[brokenChain.len()/2]) tester.newPeer("attack", protocol, brokenChain) - if err := tester.sync("attack", nil, mode); err == nil { + if err := tester.sync("attack", 0, mode); err == nil { t.Fatalf("succeeded attacker synchronisation") } // Synchronise with the valid peer and make sure sync succeeds tester.newPeer("valid", protocol, chain) - if err := tester.sync("valid", nil, mode); err != nil { + if err := tester.sync("valid", 0, mode); err != nil { t.Fatalf("failed to synchronise blocks: %v", err) } assertOwnChain(t, tester, chain.len()) @@ -786,13 +773,13 @@ func testShiftedHeaderAttack(t *testing.T, protocol int, mode SyncMode) { delete(brokenChain.blockm, brokenChain.chain[1]) delete(brokenChain.receiptm, brokenChain.chain[1]) tester.newPeer("attack", protocol, brokenChain) - if err := tester.sync("attack", nil, mode); err == nil { + if err := tester.sync("attack", 0, mode); err == nil { t.Fatalf("succeeded attacker synchronisation") } // Synchronise with the valid peer and make sure sync succeeds tester.newPeer("valid", protocol, chain) - if err := tester.sync("valid", nil, mode); err != nil { + if err := tester.sync("valid", 0, mode); err != nil { t.Fatalf("failed to synchronise blocks: %v", err) } assertOwnChain(t, tester, chain.len()) @@ -822,7 +809,7 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) { delete(fastAttackChain.headerm, fastAttackChain.chain[missing]) tester.newPeer("fast-attack", protocol, fastAttackChain) - if err := tester.sync("fast-attack", nil, mode); err == nil { + if err := tester.sync("fast-attack", 0, mode); err == nil { t.Fatalf("succeeded fast attacker synchronisation") } if head := tester.CurrentHeader().Number.Int64(); int(head) > MaxHeaderFetch { @@ -838,7 +825,7 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) { delete(blockAttackChain.headerm, blockAttackChain.chain[missing]) tester.newPeer("block-attack", protocol, blockAttackChain) - if err := tester.sync("block-attack", nil, mode); err == nil { + if err := tester.sync("block-attack", 0, mode); err == nil { t.Fatalf("succeeded block attacker synchronisation") } if head := tester.CurrentHeader().Number.Int64(); int(head) > 2*fsHeaderSafetyNet+MaxHeaderFetch { @@ -861,7 +848,7 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) { } tester.downloader.syncInitHook = nil } - if err := tester.sync("withhold-attack", nil, mode); err == nil { + if err := tester.sync("withhold-attack", 0, mode); err == nil { t.Fatalf("succeeded withholding attacker synchronisation") } if head := tester.CurrentHeader().Number.Int64(); int(head) > 2*fsHeaderSafetyNet+MaxHeaderFetch { @@ -878,7 +865,7 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) { // sync. Note, we can't assert anything about the receipts since we won't purge the // database of them, hence we can't use assertOwnChain. tester.newPeer("valid", protocol, chain) - if err := tester.sync("valid", nil, mode); err != nil { + if err := tester.sync("valid", 0, mode); err != nil { t.Fatalf("failed to synchronise blocks: %v", err) } if hs := len(tester.ownHeaders); hs != chain.len() { @@ -891,16 +878,26 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) { } } -// Tests that a peer advertising an high TD doesn't get to stall the downloader +// Tests that a peer advertising an high number doesn't get to stall the downloader // afterwards by not sending any useful hashes. -func TestHighTDStarvationAttack62(t *testing.T) { testHighTDStarvationAttack(t, 62, FullSync) } -func TestHighTDStarvationAttack63Full(t *testing.T) { testHighTDStarvationAttack(t, 63, FullSync) } -func TestHighTDStarvationAttack63Fast(t *testing.T) { testHighTDStarvationAttack(t, 63, FastSync) } -func TestHighTDStarvationAttack64Full(t *testing.T) { testHighTDStarvationAttack(t, 64, FullSync) } -func TestHighTDStarvationAttack64Fast(t *testing.T) { testHighTDStarvationAttack(t, 64, FastSync) } -func TestHighTDStarvationAttack64Light(t *testing.T) { testHighTDStarvationAttack(t, 64, LightSync) } - -func testHighTDStarvationAttack(t *testing.T, protocol int, mode SyncMode) { +func TestHighNumberStarvationAttack62(t *testing.T) { testHighNumberStarvationAttack(t, 62, FullSync) } +func TestHighNumberStarvationAttack63Full(t *testing.T) { + testHighNumberStarvationAttack(t, 63, FullSync) +} +func TestHighNumberStarvationAttack63Fast(t *testing.T) { + testHighNumberStarvationAttack(t, 63, FastSync) +} +func TestHighNumberStarvationAttack64Full(t *testing.T) { + testHighNumberStarvationAttack(t, 64, FullSync) +} +func TestHighNumberStarvationAttack64Fast(t *testing.T) { + testHighNumberStarvationAttack(t, 64, FastSync) +} +func TestHighNumberStarvationAttack64Light(t *testing.T) { + testHighNumberStarvationAttack(t, 64, LightSync) +} + +func testHighNumberStarvationAttack(t *testing.T, protocol int, mode SyncMode) { t.Parallel() tester := newTester() @@ -908,7 +905,7 @@ func testHighTDStarvationAttack(t *testing.T, protocol int, mode SyncMode) { chain := testChainBase.shorten(1) tester.newPeer("attack", protocol, chain) - if err := tester.sync("attack", big.NewInt(1000000), mode); err != errStallingPeer { + if err := tester.sync("attack", 1000000, mode); err != errStallingPeer { t.Fatalf("synchronisation error mismatch: have %v, want %v", err, errStallingPeer) } } @@ -964,7 +961,7 @@ func testBlockHeaderAttackerDropping(t *testing.T, protocol int) { // Simulate a synchronisation and check the required result tester.downloader.synchroniseMock = func(string, common.Hash) error { return tt.result } - tester.downloader.Synchronise(id, tester.genesis.Hash(), big.NewInt(1000), FullSync) + tester.downloader.Synchronise(id, tester.genesis.Hash(), 1000, FullSync) if _, ok := tester.peers[id]; !ok != tt.drop { t.Errorf("test %d: peer drop mismatch for %v: have %v, want %v", i, tt.result, !ok, tt.drop) } @@ -1004,7 +1001,7 @@ func testSyncProgress(t *testing.T, protocol int, mode SyncMode) { go func() { defer pending.Done() - if err := tester.sync("peer-half", nil, mode); err != nil { + if err := tester.sync("peer-half", 0, mode); err != nil { panic(fmt.Sprintf("failed to synchronise blocks: %v", err)) } }() @@ -1020,7 +1017,7 @@ func testSyncProgress(t *testing.T, protocol int, mode SyncMode) { pending.Add(1) go func() { defer pending.Done() - if err := tester.sync("peer-full", nil, mode); err != nil { + if err := tester.sync("peer-full", 0, mode); err != nil { panic(fmt.Sprintf("failed to synchronise blocks: %v", err)) } }() @@ -1090,7 +1087,7 @@ func testFailedSyncProgress(t *testing.T, protocol int, mode SyncMode) { pending.Add(1) go func() { defer pending.Done() - if err := tester.sync("faulty", nil, mode); err == nil { + if err := tester.sync("faulty", 0, mode); err == nil { panic("succeeded faulty synchronisation") } }() @@ -1108,7 +1105,7 @@ func testFailedSyncProgress(t *testing.T, protocol int, mode SyncMode) { pending.Add(1) go func() { defer pending.Done() - if err := tester.sync("valid", nil, mode); err != nil { + if err := tester.sync("valid", 0, mode); err != nil { panic(fmt.Sprintf("failed to synchronise blocks: %v", err)) } }() @@ -1161,7 +1158,7 @@ func testFakedSyncProgress(t *testing.T, protocol int, mode SyncMode) { pending.Add(1) go func() { defer pending.Done() - if err := tester.sync("attack", nil, mode); err == nil { + if err := tester.sync("attack", 0, mode); err == nil { panic("succeeded attacker synchronisation") } }() @@ -1181,7 +1178,7 @@ func testFakedSyncProgress(t *testing.T, protocol int, mode SyncMode) { go func() { defer pending.Done() - if err := tester.sync("valid", nil, mode); err != nil { + if err := tester.sync("valid", 0, mode); err != nil { panic(fmt.Sprintf("failed to synchronise blocks: %v", err)) } }() @@ -1240,7 +1237,7 @@ func testDeliverHeadersHang(t *testing.T, protocol int, mode SyncMode) { peer: tester.downloader.peers.peers["peer"].peer, tester: tester, } - if err := tester.sync("peer", nil, mode); err != nil { + if err := tester.sync("peer", 0, mode); err != nil { t.Errorf("test %d: sync failed: %v", i, err) } tester.terminate() @@ -1252,7 +1249,7 @@ type floodingTestPeer struct { tester *downloadTester } -func (ftp *floodingTestPeer) Head() (common.Hash, *big.Int) { return ftp.peer.Head() } +func (ftp *floodingTestPeer) Head() (common.Hash, uint64) { return ftp.peer.Head() } func (ftp *floodingTestPeer) RequestHeadersByHash(hash common.Hash, count int, skip int, reverse, withGov bool) error { return ftp.peer.RequestHeadersByHash(hash, count, skip, reverse, withGov) } |