|
|
|
@ -20,6 +20,7 @@ import ( |
|
|
|
|
"math/big" |
|
|
|
|
"math/rand" |
|
|
|
|
"testing" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
|
"github.com/ethereum/go-ethereum/core" |
|
|
|
@ -28,6 +29,7 @@ import ( |
|
|
|
|
"github.com/ethereum/go-ethereum/crypto" |
|
|
|
|
"github.com/ethereum/go-ethereum/eth/downloader" |
|
|
|
|
"github.com/ethereum/go-ethereum/ethdb" |
|
|
|
|
"github.com/ethereum/go-ethereum/event" |
|
|
|
|
"github.com/ethereum/go-ethereum/p2p" |
|
|
|
|
"github.com/ethereum/go-ethereum/params" |
|
|
|
|
) |
|
|
|
@ -580,3 +582,74 @@ func testGetReceipt(t *testing.T, protocol int) { |
|
|
|
|
t.Errorf("receipts mismatch: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that post eth protocol handshake, DAO fork-enabled clients also execute
|
|
|
|
|
// a DAO "challenge" verifying each others' DAO fork headers to ensure they're on
|
|
|
|
|
// compatible chains.
|
|
|
|
|
func TestDAOChallengeNoVsNo(t *testing.T) { testDAOChallenge(t, false, false, false) } |
|
|
|
|
func TestDAOChallengeNoVsPro(t *testing.T) { testDAOChallenge(t, false, true, false) } |
|
|
|
|
func TestDAOChallengeProVsNo(t *testing.T) { testDAOChallenge(t, true, false, false) } |
|
|
|
|
func TestDAOChallengeProVsPro(t *testing.T) { testDAOChallenge(t, true, true, false) } |
|
|
|
|
func TestDAOChallengeNoVsTimeout(t *testing.T) { testDAOChallenge(t, false, false, true) } |
|
|
|
|
func TestDAOChallengeProVsTimeout(t *testing.T) { testDAOChallenge(t, true, true, true) } |
|
|
|
|
|
|
|
|
|
func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool) { |
|
|
|
|
// Reduce the DAO handshake challenge timeout
|
|
|
|
|
if timeout { |
|
|
|
|
defer func(old time.Duration) { daoChallengeTimeout = old }(daoChallengeTimeout) |
|
|
|
|
daoChallengeTimeout = 500 * time.Millisecond |
|
|
|
|
} |
|
|
|
|
// Create a DAO aware protocol manager
|
|
|
|
|
var ( |
|
|
|
|
evmux = new(event.TypeMux) |
|
|
|
|
pow = new(core.FakePow) |
|
|
|
|
db, _ = ethdb.NewMemDatabase() |
|
|
|
|
genesis = core.WriteGenesisBlockForTesting(db) |
|
|
|
|
config = &core.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked} |
|
|
|
|
blockchain, _ = core.NewBlockChain(db, config, pow, evmux) |
|
|
|
|
) |
|
|
|
|
pm, err := NewProtocolManager(config, false, NetworkId, evmux, new(testTxPool), pow, blockchain, db) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to start test protocol manager: %v", err) |
|
|
|
|
} |
|
|
|
|
pm.Start() |
|
|
|
|
defer pm.Stop() |
|
|
|
|
|
|
|
|
|
// Connect a new peer and check that we receive the DAO challenge
|
|
|
|
|
peer, _ := newTestPeer("peer", eth63, pm, true) |
|
|
|
|
defer peer.close() |
|
|
|
|
|
|
|
|
|
challenge := &getBlockHeadersData{ |
|
|
|
|
Origin: hashOrNumber{Number: config.DAOForkBlock.Uint64()}, |
|
|
|
|
Amount: 1, |
|
|
|
|
Skip: 0, |
|
|
|
|
Reverse: false, |
|
|
|
|
} |
|
|
|
|
if err := p2p.ExpectMsg(peer.app, GetBlockHeadersMsg, challenge); err != nil { |
|
|
|
|
t.Fatalf("challenge mismatch: %v", err) |
|
|
|
|
} |
|
|
|
|
// Create a block to reply to the challenge if no timeout is simualted
|
|
|
|
|
if !timeout { |
|
|
|
|
blocks, _ := core.GenerateChain(genesis, db, 1, func(i int, block *core.BlockGen) { |
|
|
|
|
if remoteForked { |
|
|
|
|
block.SetExtra(params.DAOForkBlockExtra) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
if err := p2p.Send(peer.app, BlockHeadersMsg, []*types.Header{blocks[0].Header()}); err != nil { |
|
|
|
|
t.Fatalf("failed to answer challenge: %v", err) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// Otherwise wait until the test timeout passes
|
|
|
|
|
time.Sleep(daoChallengeTimeout + 500*time.Millisecond) |
|
|
|
|
} |
|
|
|
|
// Verify that depending on fork side, the remote peer is maintained or dropped
|
|
|
|
|
if localForked == remoteForked && !timeout { |
|
|
|
|
if peers := pm.peers.Len(); peers != 1 { |
|
|
|
|
t.Fatalf("peer count mismatch: have %d, want %d", peers, 1) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if peers := pm.peers.Len(); peers != 0 { |
|
|
|
|
t.Fatalf("peer count mismatch: have %d, want %d", peers, 0) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|