|
@@ -17,12 +17,11 @@
|
|
|
package eth
|
|
package eth
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
|
+ mapset "github.com/deckarep/golang-set"
|
|
|
"math/big"
|
|
"math/big"
|
|
|
"math/rand"
|
|
"math/rand"
|
|
|
"sync"
|
|
"sync"
|
|
|
|
|
|
|
|
- mapset "github.com/deckarep/golang-set"
|
|
|
|
|
-
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
|
"github.com/ethereum/go-ethereum/p2p"
|
|
"github.com/ethereum/go-ethereum/p2p"
|
|
@@ -141,6 +140,10 @@ func (p *Peer) ID() string {
|
|
|
return p.id
|
|
return p.id
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func (p *Peer) RW() p2p.MsgReadWriter {
|
|
|
|
|
+ return p.rw
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// Version retrieves the peer's negoatiated `eth` protocol version.
|
|
// Version retrieves the peer's negoatiated `eth` protocol version.
|
|
|
func (p *Peer) Version() uint {
|
|
func (p *Peer) Version() uint {
|
|
|
return p.version
|
|
return p.version
|
|
@@ -194,6 +197,10 @@ func (p *Peer) markTransaction(hash common.Hash) {
|
|
|
p.knownTxs.Add(hash)
|
|
p.knownTxs.Add(hash)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func (p *Peer) MarkTransaction(hash common.Hash) {
|
|
|
|
|
+ p.knownTxs.Add(hash)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// SendTransactions sends transactions to the peer and includes the hashes
|
|
// SendTransactions sends transactions to the peer and includes the hashes
|
|
|
// in its transaction hash set for future reference.
|
|
// in its transaction hash set for future reference.
|
|
|
//
|
|
//
|
|
@@ -211,12 +218,14 @@ func (p *Peer) SendTransactions(txs types.Transactions) error {
|
|
|
for _, tx := range txs {
|
|
for _, tx := range txs {
|
|
|
p.knownTxs.Add(tx.Hash())
|
|
p.knownTxs.Add(tx.Hash())
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
return p2p.Send(p.rw, TransactionsMsg, txs)
|
|
return p2p.Send(p.rw, TransactionsMsg, txs)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// AsyncSendTransactions queues a list of transactions (by hash) to eventually
|
|
// AsyncSendTransactions queues a list of transactions (by hash) to eventually
|
|
|
// propagate to a remote peer. The number of pending sends are capped (new ones
|
|
// propagate to a remote peer. The number of pending sends are capped (new ones
|
|
|
// will force old sends to be dropped)
|
|
// will force old sends to be dropped)
|
|
|
|
|
+// 0x2 >eth/protocols/eth/broadcast.go broadcastTransactions()
|
|
|
func (p *Peer) AsyncSendTransactions(hashes []common.Hash) {
|
|
func (p *Peer) AsyncSendTransactions(hashes []common.Hash) {
|
|
|
select {
|
|
select {
|
|
|
case p.txBroadcast <- hashes:
|
|
case p.txBroadcast <- hashes:
|
|
@@ -242,6 +251,7 @@ func (p *Peer) AsyncSendTransactions(hashes []common.Hash) {
|
|
|
// This method is a helper used by the async transaction announcer. Don't call it
|
|
// This method is a helper used by the async transaction announcer. Don't call it
|
|
|
// directly as the queueing (memory) and transmission (bandwidth) costs should
|
|
// directly as the queueing (memory) and transmission (bandwidth) costs should
|
|
|
// not be managed directly.
|
|
// not be managed directly.
|
|
|
|
|
+// 0x8
|
|
|
func (p *Peer) sendPooledTransactionHashes(hashes []common.Hash) error {
|
|
func (p *Peer) sendPooledTransactionHashes(hashes []common.Hash) error {
|
|
|
// Mark all the transactions as known, but ensure we don't overflow our limits
|
|
// Mark all the transactions as known, but ensure we don't overflow our limits
|
|
|
for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) {
|
|
for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) {
|
|
@@ -256,6 +266,7 @@ func (p *Peer) sendPooledTransactionHashes(hashes []common.Hash) error {
|
|
|
// AsyncSendPooledTransactionHashes queues a list of transactions hashes to eventually
|
|
// AsyncSendPooledTransactionHashes queues a list of transactions hashes to eventually
|
|
|
// announce to a remote peer. The number of pending sends are capped (new ones
|
|
// announce to a remote peer. The number of pending sends are capped (new ones
|
|
|
// will force old sends to be dropped)
|
|
// will force old sends to be dropped)
|
|
|
|
|
+// 0x8 > eth/protocols/eth/broadcast.go announceTransactions
|
|
|
func (p *Peer) AsyncSendPooledTransactionHashes(hashes []common.Hash) {
|
|
func (p *Peer) AsyncSendPooledTransactionHashes(hashes []common.Hash) {
|
|
|
select {
|
|
select {
|
|
|
case p.txAnnounce <- hashes:
|
|
case p.txAnnounce <- hashes:
|
|
@@ -280,6 +291,7 @@ func (p *Peer) AsyncSendPooledTransactionHashes(hashes []common.Hash) {
|
|
|
//
|
|
//
|
|
|
// Note, the method assumes the hashes are correct and correspond to the list of
|
|
// Note, the method assumes the hashes are correct and correspond to the list of
|
|
|
// transactions being sent.
|
|
// transactions being sent.
|
|
|
|
|
+// 0xa eth65
|
|
|
func (p *Peer) SendPooledTransactionsRLP(hashes []common.Hash, txs []rlp.RawValue) error {
|
|
func (p *Peer) SendPooledTransactionsRLP(hashes []common.Hash, txs []rlp.RawValue) error {
|
|
|
// Mark all the transactions as known, but ensure we don't overflow our limits
|
|
// Mark all the transactions as known, but ensure we don't overflow our limits
|
|
|
for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) {
|
|
for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) {
|
|
@@ -292,6 +304,7 @@ func (p *Peer) SendPooledTransactionsRLP(hashes []common.Hash, txs []rlp.RawValu
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ReplyPooledTransactionsRLP is the eth/66 version of SendPooledTransactionsRLP.
|
|
// ReplyPooledTransactionsRLP is the eth/66 version of SendPooledTransactionsRLP.
|
|
|
|
|
+// 0xa eth66
|
|
|
func (p *Peer) ReplyPooledTransactionsRLP(id uint64, hashes []common.Hash, txs []rlp.RawValue) error {
|
|
func (p *Peer) ReplyPooledTransactionsRLP(id uint64, hashes []common.Hash, txs []rlp.RawValue) error {
|
|
|
// Mark all the transactions as known, but ensure we don't overflow our limits
|
|
// Mark all the transactions as known, but ensure we don't overflow our limits
|
|
|
for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) {
|
|
for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) {
|
|
@@ -309,6 +322,7 @@ func (p *Peer) ReplyPooledTransactionsRLP(id uint64, hashes []common.Hash, txs [
|
|
|
|
|
|
|
|
// SendNewBlockHashes announces the availability of a number of blocks through
|
|
// SendNewBlockHashes announces the availability of a number of blocks through
|
|
|
// a hash notification.
|
|
// a hash notification.
|
|
|
|
|
+// 0x1
|
|
|
func (p *Peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error {
|
|
func (p *Peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error {
|
|
|
// Mark all the block hashes as known, but ensure we don't overflow our limits
|
|
// Mark all the block hashes as known, but ensure we don't overflow our limits
|
|
|
for p.knownBlocks.Cardinality() > max(0, maxKnownBlocks-len(hashes)) {
|
|
for p.knownBlocks.Cardinality() > max(0, maxKnownBlocks-len(hashes)) {
|
|
@@ -328,6 +342,7 @@ func (p *Peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error
|
|
|
// AsyncSendNewBlockHash queues the availability of a block for propagation to a
|
|
// AsyncSendNewBlockHash queues the availability of a block for propagation to a
|
|
|
// remote peer. If the peer's broadcast queue is full, the event is silently
|
|
// remote peer. If the peer's broadcast queue is full, the event is silently
|
|
|
// dropped.
|
|
// dropped.
|
|
|
|
|
+// 0x1 > broadcastBlocks > queuedBlockAnns > this.SendNewBlockHashes
|
|
|
func (p *Peer) AsyncSendNewBlockHash(block *types.Block) {
|
|
func (p *Peer) AsyncSendNewBlockHash(block *types.Block) {
|
|
|
select {
|
|
select {
|
|
|
case p.queuedBlockAnns <- block:
|
|
case p.queuedBlockAnns <- block:
|
|
@@ -342,6 +357,7 @@ func (p *Peer) AsyncSendNewBlockHash(block *types.Block) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// SendNewBlock propagates an entire block to a remote peer.
|
|
// SendNewBlock propagates an entire block to a remote peer.
|
|
|
|
|
+// 0x7
|
|
|
func (p *Peer) SendNewBlock(block *types.Block, td *big.Int) error {
|
|
func (p *Peer) SendNewBlock(block *types.Block, td *big.Int) error {
|
|
|
// Mark all the block hash as known, but ensure we don't overflow our limits
|
|
// Mark all the block hash as known, but ensure we don't overflow our limits
|
|
|
for p.knownBlocks.Cardinality() >= maxKnownBlocks {
|
|
for p.knownBlocks.Cardinality() >= maxKnownBlocks {
|
|
@@ -356,6 +372,7 @@ func (p *Peer) SendNewBlock(block *types.Block, td *big.Int) error {
|
|
|
|
|
|
|
|
// AsyncSendNewBlock queues an entire block for propagation to a remote peer. If
|
|
// AsyncSendNewBlock queues an entire block for propagation to a remote peer. If
|
|
|
// the peer's broadcast queue is full, the event is silently dropped.
|
|
// the peer's broadcast queue is full, the event is silently dropped.
|
|
|
|
|
+// 0x7 queuedBlocks > broadcastBlocks > queuedBlocks > this.SendNewBlock
|
|
|
func (p *Peer) AsyncSendNewBlock(block *types.Block, td *big.Int) {
|
|
func (p *Peer) AsyncSendNewBlock(block *types.Block, td *big.Int) {
|
|
|
select {
|
|
select {
|
|
|
case p.queuedBlocks <- &blockPropagation{block: block, td: td}:
|
|
case p.queuedBlocks <- &blockPropagation{block: block, td: td}:
|
|
@@ -370,11 +387,13 @@ func (p *Peer) AsyncSendNewBlock(block *types.Block, td *big.Int) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// SendBlockHeaders sends a batch of block headers to the remote peer.
|
|
// SendBlockHeaders sends a batch of block headers to the remote peer.
|
|
|
|
|
+// 0x4 eth65
|
|
|
func (p *Peer) SendBlockHeaders(headers []*types.Header) error {
|
|
func (p *Peer) SendBlockHeaders(headers []*types.Header) error {
|
|
|
return p2p.Send(p.rw, BlockHeadersMsg, BlockHeadersPacket(headers))
|
|
return p2p.Send(p.rw, BlockHeadersMsg, BlockHeadersPacket(headers))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ReplyBlockHeaders is the eth/66 version of SendBlockHeaders.
|
|
// ReplyBlockHeaders is the eth/66 version of SendBlockHeaders.
|
|
|
|
|
+// 0x4 eth66
|
|
|
func (p *Peer) ReplyBlockHeaders(id uint64, headers []*types.Header) error {
|
|
func (p *Peer) ReplyBlockHeaders(id uint64, headers []*types.Header) error {
|
|
|
return p2p.Send(p.rw, BlockHeadersMsg, BlockHeadersPacket66{
|
|
return p2p.Send(p.rw, BlockHeadersMsg, BlockHeadersPacket66{
|
|
|
RequestId: id,
|
|
RequestId: id,
|
|
@@ -384,11 +403,13 @@ func (p *Peer) ReplyBlockHeaders(id uint64, headers []*types.Header) error {
|
|
|
|
|
|
|
|
// SendBlockBodiesRLP sends a batch of block contents to the remote peer from
|
|
// SendBlockBodiesRLP sends a batch of block contents to the remote peer from
|
|
|
// an already RLP encoded format.
|
|
// an already RLP encoded format.
|
|
|
|
|
+// 0x6 eth65
|
|
|
func (p *Peer) SendBlockBodiesRLP(bodies []rlp.RawValue) error {
|
|
func (p *Peer) SendBlockBodiesRLP(bodies []rlp.RawValue) error {
|
|
|
return p2p.Send(p.rw, BlockBodiesMsg, bodies) // Not packed into BlockBodiesPacket to avoid RLP decoding
|
|
return p2p.Send(p.rw, BlockBodiesMsg, bodies) // Not packed into BlockBodiesPacket to avoid RLP decoding
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ReplyBlockBodiesRLP is the eth/66 version of SendBlockBodiesRLP.
|
|
// ReplyBlockBodiesRLP is the eth/66 version of SendBlockBodiesRLP.
|
|
|
|
|
+// 0x6 eth66
|
|
|
func (p *Peer) ReplyBlockBodiesRLP(id uint64, bodies []rlp.RawValue) error {
|
|
func (p *Peer) ReplyBlockBodiesRLP(id uint64, bodies []rlp.RawValue) error {
|
|
|
// Not packed into BlockBodiesPacket to avoid RLP decoding
|
|
// Not packed into BlockBodiesPacket to avoid RLP decoding
|
|
|
return p2p.Send(p.rw, BlockBodiesMsg, BlockBodiesRLPPacket66{
|
|
return p2p.Send(p.rw, BlockBodiesMsg, BlockBodiesRLPPacket66{
|
|
@@ -413,11 +434,13 @@ func (p *Peer) ReplyNodeData(id uint64, data [][]byte) error {
|
|
|
|
|
|
|
|
// SendReceiptsRLP sends a batch of transaction receipts, corresponding to the
|
|
// SendReceiptsRLP sends a batch of transaction receipts, corresponding to the
|
|
|
// ones requested from an already RLP encoded format.
|
|
// ones requested from an already RLP encoded format.
|
|
|
|
|
+// 0x10 eth65
|
|
|
func (p *Peer) SendReceiptsRLP(receipts []rlp.RawValue) error {
|
|
func (p *Peer) SendReceiptsRLP(receipts []rlp.RawValue) error {
|
|
|
return p2p.Send(p.rw, ReceiptsMsg, receipts) // Not packed into ReceiptsPacket to avoid RLP decoding
|
|
return p2p.Send(p.rw, ReceiptsMsg, receipts) // Not packed into ReceiptsPacket to avoid RLP decoding
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ReplyReceiptsRLP is the eth/66 response to GetReceipts.
|
|
// ReplyReceiptsRLP is the eth/66 response to GetReceipts.
|
|
|
|
|
+// 0x10 eth66
|
|
|
func (p *Peer) ReplyReceiptsRLP(id uint64, receipts []rlp.RawValue) error {
|
|
func (p *Peer) ReplyReceiptsRLP(id uint64, receipts []rlp.RawValue) error {
|
|
|
return p2p.Send(p.rw, ReceiptsMsg, ReceiptsRLPPacket66{
|
|
return p2p.Send(p.rw, ReceiptsMsg, ReceiptsRLPPacket66{
|
|
|
RequestId: id,
|
|
RequestId: id,
|
|
@@ -427,6 +450,7 @@ func (p *Peer) ReplyReceiptsRLP(id uint64, receipts []rlp.RawValue) error {
|
|
|
|
|
|
|
|
// RequestOneHeader is a wrapper around the header query functions to fetch a
|
|
// RequestOneHeader is a wrapper around the header query functions to fetch a
|
|
|
// single header. It is used solely by the fetcher.
|
|
// single header. It is used solely by the fetcher.
|
|
|
|
|
+// 0x3 > get 0x4
|
|
|
func (p *Peer) RequestOneHeader(hash common.Hash) error {
|
|
func (p *Peer) RequestOneHeader(hash common.Hash) error {
|
|
|
p.Log().Debug("Fetching single header", "hash", hash)
|
|
p.Log().Debug("Fetching single header", "hash", hash)
|
|
|
query := GetBlockHeadersPacket{
|
|
query := GetBlockHeadersPacket{
|
|
@@ -505,6 +529,7 @@ func (p *Peer) ExpectRequestHeadersByNumber(origin uint64, amount int, skip int,
|
|
|
|
|
|
|
|
// RequestBodies fetches a batch of blocks' bodies corresponding to the hashes
|
|
// RequestBodies fetches a batch of blocks' bodies corresponding to the hashes
|
|
|
// specified.
|
|
// specified.
|
|
|
|
|
+// 0x5 > get 0x6
|
|
|
func (p *Peer) RequestBodies(hashes []common.Hash) error {
|
|
func (p *Peer) RequestBodies(hashes []common.Hash) error {
|
|
|
p.Log().Debug("Fetching batch of block bodies", "count", len(hashes))
|
|
p.Log().Debug("Fetching batch of block bodies", "count", len(hashes))
|
|
|
if p.Version() >= ETH66 {
|
|
if p.Version() >= ETH66 {
|
|
@@ -551,12 +576,13 @@ func (p *Peer) RequestReceipts(hashes []common.Hash) error {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// RequestTxs fetches a batch of transactions from a remote node.
|
|
// RequestTxs fetches a batch of transactions from a remote node.
|
|
|
|
|
+// 0x9 > 0x10
|
|
|
func (p *Peer) RequestTxs(hashes []common.Hash) error {
|
|
func (p *Peer) RequestTxs(hashes []common.Hash) error {
|
|
|
p.Log().Debug("Fetching batch of transactions", "count", len(hashes))
|
|
p.Log().Debug("Fetching batch of transactions", "count", len(hashes))
|
|
|
if p.Version() >= ETH66 {
|
|
if p.Version() >= ETH66 {
|
|
|
id := rand.Uint64()
|
|
id := rand.Uint64()
|
|
|
|
|
|
|
|
- requestTracker.Track(p.id, p.version, GetPooledTransactionsMsg, PooledTransactionsMsg, id)
|
|
|
|
|
|
|
+ //requestTracker.Track(p.id, p.version, GetPooledTransactionsMsg, PooledTransactionsMsg, id)
|
|
|
return p2p.Send(p.rw, GetPooledTransactionsMsg, &GetPooledTransactionsPacket66{
|
|
return p2p.Send(p.rw, GetPooledTransactionsMsg, &GetPooledTransactionsPacket66{
|
|
|
RequestId: id,
|
|
RequestId: id,
|
|
|
GetPooledTransactionsPacket: hashes,
|
|
GetPooledTransactionsPacket: hashes,
|