mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 01:13:45 +00:00
les: implement GetTxStatusMsg and SendTxV2Msg
This commit is contained in:
parent
bc23b730b0
commit
780fc83a6f
6 changed files with 203 additions and 39 deletions
|
|
@ -74,9 +74,9 @@ var (
|
||||||
preimageHitCounter = metrics.NewCounter("db/preimage/hits")
|
preimageHitCounter = metrics.NewCounter("db/preimage/hits")
|
||||||
)
|
)
|
||||||
|
|
||||||
// txLookupEntry is a positional metadata to help looking up the data content of
|
// TxLookupEntry is a positional metadata to help looking up the data content of
|
||||||
// a transaction or receipt given only its hash.
|
// a transaction or receipt given only its hash.
|
||||||
type txLookupEntry struct {
|
type TxLookupEntry struct {
|
||||||
BlockHash common.Hash
|
BlockHash common.Hash
|
||||||
BlockIndex uint64
|
BlockIndex uint64
|
||||||
Index uint64
|
Index uint64
|
||||||
|
|
@ -260,7 +260,7 @@ func GetTxLookupEntry(db DatabaseReader, hash common.Hash) (common.Hash, uint64,
|
||||||
return common.Hash{}, 0, 0
|
return common.Hash{}, 0, 0
|
||||||
}
|
}
|
||||||
// Parse and return the contents of the lookup entry
|
// Parse and return the contents of the lookup entry
|
||||||
var entry txLookupEntry
|
var entry TxLookupEntry
|
||||||
if err := rlp.DecodeBytes(data, &entry); err != nil {
|
if err := rlp.DecodeBytes(data, &entry); err != nil {
|
||||||
log.Error("Invalid lookup entry RLP", "hash", hash, "err", err)
|
log.Error("Invalid lookup entry RLP", "hash", hash, "err", err)
|
||||||
return common.Hash{}, 0, 0
|
return common.Hash{}, 0, 0
|
||||||
|
|
@ -296,7 +296,7 @@ func GetTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, co
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return nil, common.Hash{}, 0, 0
|
return nil, common.Hash{}, 0, 0
|
||||||
}
|
}
|
||||||
var entry txLookupEntry
|
var entry TxLookupEntry
|
||||||
if err := rlp.DecodeBytes(data, &entry); err != nil {
|
if err := rlp.DecodeBytes(data, &entry); err != nil {
|
||||||
return nil, common.Hash{}, 0, 0
|
return nil, common.Hash{}, 0, 0
|
||||||
}
|
}
|
||||||
|
|
@ -464,7 +464,7 @@ func WriteBlockReceipts(db ethdb.Putter, hash common.Hash, number uint64, receip
|
||||||
func WriteTxLookupEntries(db ethdb.Putter, block *types.Block) error {
|
func WriteTxLookupEntries(db ethdb.Putter, block *types.Block) error {
|
||||||
// Iterate over each transaction and encode its metadata
|
// Iterate over each transaction and encode its metadata
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
entry := txLookupEntry{
|
entry := TxLookupEntry{
|
||||||
BlockHash: block.Hash(),
|
BlockHash: block.Hash(),
|
||||||
BlockIndex: block.NumberU64(),
|
BlockIndex: block.NumberU64(),
|
||||||
Index: uint64(i),
|
Index: uint64(i),
|
||||||
|
|
|
||||||
|
|
@ -384,13 +384,13 @@ func (h *priceHeap) Pop() interface{} {
|
||||||
// txPricedList is a price-sorted heap to allow operating on transactions pool
|
// txPricedList is a price-sorted heap to allow operating on transactions pool
|
||||||
// contents in a price-incrementing way.
|
// contents in a price-incrementing way.
|
||||||
type txPricedList struct {
|
type txPricedList struct {
|
||||||
all *map[common.Hash]*types.Transaction // Pointer to the map of all transactions
|
all *map[common.Hash]txLookupRec // Pointer to the map of all transactions
|
||||||
items *priceHeap // Heap of prices of all the stored transactions
|
items *priceHeap // Heap of prices of all the stored transactions
|
||||||
stales int // Number of stale price points to (re-heap trigger)
|
stales int // Number of stale price points to (re-heap trigger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTxPricedList creates a new price-sorted transaction heap.
|
// newTxPricedList creates a new price-sorted transaction heap.
|
||||||
func newTxPricedList(all *map[common.Hash]*types.Transaction) *txPricedList {
|
func newTxPricedList(all *map[common.Hash]txLookupRec) *txPricedList {
|
||||||
return &txPricedList{
|
return &txPricedList{
|
||||||
all: all,
|
all: all,
|
||||||
items: new(priceHeap),
|
items: new(priceHeap),
|
||||||
|
|
@ -416,7 +416,7 @@ func (l *txPricedList) Removed() {
|
||||||
|
|
||||||
l.stales, l.items = 0, &reheap
|
l.stales, l.items = 0, &reheap
|
||||||
for _, tx := range *l.all {
|
for _, tx := range *l.all {
|
||||||
*l.items = append(*l.items, tx)
|
*l.items = append(*l.items, tx.tx)
|
||||||
}
|
}
|
||||||
heap.Init(l.items)
|
heap.Init(l.items)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -195,7 +195,7 @@ type TxPool struct {
|
||||||
pending map[common.Address]*txList // All currently processable transactions
|
pending map[common.Address]*txList // All currently processable transactions
|
||||||
queue map[common.Address]*txList // Queued but non-processable transactions
|
queue map[common.Address]*txList // Queued but non-processable transactions
|
||||||
beats map[common.Address]time.Time // Last heartbeat from each known account
|
beats map[common.Address]time.Time // Last heartbeat from each known account
|
||||||
all map[common.Hash]*types.Transaction // All transactions to allow lookups
|
all map[common.Hash]txLookupRec // All transactions to allow lookups
|
||||||
priced *txPricedList // All transactions sorted by price
|
priced *txPricedList // All transactions sorted by price
|
||||||
|
|
||||||
wg sync.WaitGroup // for shutdown sync
|
wg sync.WaitGroup // for shutdown sync
|
||||||
|
|
@ -203,6 +203,11 @@ type TxPool struct {
|
||||||
homestead bool
|
homestead bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type txLookupRec struct {
|
||||||
|
tx *types.Transaction
|
||||||
|
pending bool
|
||||||
|
}
|
||||||
|
|
||||||
// NewTxPool creates a new transaction pool to gather, sort and filter inbound
|
// NewTxPool creates a new transaction pool to gather, sort and filter inbound
|
||||||
// trnsactions from the network.
|
// trnsactions from the network.
|
||||||
func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain) *TxPool {
|
func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain) *TxPool {
|
||||||
|
|
@ -218,7 +223,7 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block
|
||||||
pending: make(map[common.Address]*txList),
|
pending: make(map[common.Address]*txList),
|
||||||
queue: make(map[common.Address]*txList),
|
queue: make(map[common.Address]*txList),
|
||||||
beats: make(map[common.Address]time.Time),
|
beats: make(map[common.Address]time.Time),
|
||||||
all: make(map[common.Hash]*types.Transaction),
|
all: make(map[common.Hash]txLookupRec),
|
||||||
chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize),
|
chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize),
|
||||||
gasPrice: new(big.Int).SetUint64(config.PriceLimit),
|
gasPrice: new(big.Int).SetUint64(config.PriceLimit),
|
||||||
}
|
}
|
||||||
|
|
@ -594,7 +599,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
||||||
func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
|
func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
|
||||||
// If the transaction is already known, discard it
|
// If the transaction is already known, discard it
|
||||||
hash := tx.Hash()
|
hash := tx.Hash()
|
||||||
if pool.all[hash] != nil {
|
if _, ok := pool.all[hash]; ok {
|
||||||
log.Trace("Discarding already known transaction", "hash", hash)
|
log.Trace("Discarding already known transaction", "hash", hash)
|
||||||
return false, fmt.Errorf("known transaction: %x", hash)
|
return false, fmt.Errorf("known transaction: %x", hash)
|
||||||
}
|
}
|
||||||
|
|
@ -635,7 +640,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
|
||||||
pool.priced.Removed()
|
pool.priced.Removed()
|
||||||
pendingReplaceCounter.Inc(1)
|
pendingReplaceCounter.Inc(1)
|
||||||
}
|
}
|
||||||
pool.all[tx.Hash()] = tx
|
pool.all[tx.Hash()] = txLookupRec{tx, false}
|
||||||
pool.priced.Put(tx)
|
pool.priced.Put(tx)
|
||||||
pool.journalTx(from, tx)
|
pool.journalTx(from, tx)
|
||||||
|
|
||||||
|
|
@ -678,7 +683,7 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction) (bool, er
|
||||||
pool.priced.Removed()
|
pool.priced.Removed()
|
||||||
queuedReplaceCounter.Inc(1)
|
queuedReplaceCounter.Inc(1)
|
||||||
}
|
}
|
||||||
pool.all[hash] = tx
|
pool.all[hash] = txLookupRec{tx, false}
|
||||||
pool.priced.Put(tx)
|
pool.priced.Put(tx)
|
||||||
return old != nil, nil
|
return old != nil, nil
|
||||||
}
|
}
|
||||||
|
|
@ -721,10 +726,13 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T
|
||||||
|
|
||||||
pendingReplaceCounter.Inc(1)
|
pendingReplaceCounter.Inc(1)
|
||||||
}
|
}
|
||||||
|
if pool.all[hash].tx == nil {
|
||||||
// Failsafe to work around direct pending inserts (tests)
|
// Failsafe to work around direct pending inserts (tests)
|
||||||
if pool.all[hash] == nil {
|
pool.all[hash] = txLookupRec{tx, true}
|
||||||
pool.all[hash] = tx
|
|
||||||
pool.priced.Put(tx)
|
pool.priced.Put(tx)
|
||||||
|
} else {
|
||||||
|
// set pending flag to true
|
||||||
|
pool.all[hash] = txLookupRec{tx, true}
|
||||||
}
|
}
|
||||||
// Set the potentially new pending nonce and notify any subsystems of the new tx
|
// Set the potentially new pending nonce and notify any subsystems of the new tx
|
||||||
pool.beats[addr] = time.Now()
|
pool.beats[addr] = time.Now()
|
||||||
|
|
@ -750,14 +758,16 @@ func (pool *TxPool) AddRemote(tx *types.Transaction) error {
|
||||||
// marking the senders as a local ones in the mean time, ensuring they go around
|
// marking the senders as a local ones in the mean time, ensuring they go around
|
||||||
// the local pricing constraints.
|
// the local pricing constraints.
|
||||||
func (pool *TxPool) AddLocals(txs []*types.Transaction) error {
|
func (pool *TxPool) AddLocals(txs []*types.Transaction) error {
|
||||||
return pool.addTxs(txs, !pool.config.NoLocals)
|
pool.addTxs(txs, !pool.config.NoLocals)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRemotes enqueues a batch of transactions into the pool if they are valid.
|
// AddRemotes enqueues a batch of transactions into the pool if they are valid.
|
||||||
// If the senders are not among the locally tracked ones, full pricing constraints
|
// If the senders are not among the locally tracked ones, full pricing constraints
|
||||||
// will apply.
|
// will apply.
|
||||||
func (pool *TxPool) AddRemotes(txs []*types.Transaction) error {
|
func (pool *TxPool) AddRemotes(txs []*types.Transaction) error {
|
||||||
return pool.addTxs(txs, false)
|
pool.addTxs(txs, false)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// addTx enqueues a single transaction into the pool if it is valid.
|
// addTx enqueues a single transaction into the pool if it is valid.
|
||||||
|
|
@ -779,7 +789,7 @@ func (pool *TxPool) addTx(tx *types.Transaction, local bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// addTxs attempts to queue a batch of transactions if they are valid.
|
// addTxs attempts to queue a batch of transactions if they are valid.
|
||||||
func (pool *TxPool) addTxs(txs []*types.Transaction, local bool) error {
|
func (pool *TxPool) addTxs(txs []*types.Transaction, local bool) []error {
|
||||||
pool.mu.Lock()
|
pool.mu.Lock()
|
||||||
defer pool.mu.Unlock()
|
defer pool.mu.Unlock()
|
||||||
|
|
||||||
|
|
@ -788,11 +798,13 @@ func (pool *TxPool) addTxs(txs []*types.Transaction, local bool) error {
|
||||||
|
|
||||||
// addTxsLocked attempts to queue a batch of transactions if they are valid,
|
// addTxsLocked attempts to queue a batch of transactions if they are valid,
|
||||||
// whilst assuming the transaction pool lock is already held.
|
// whilst assuming the transaction pool lock is already held.
|
||||||
func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) error {
|
func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) []error {
|
||||||
// Add the batch of transaction, tracking the accepted ones
|
// Add the batch of transaction, tracking the accepted ones
|
||||||
dirty := make(map[common.Address]struct{})
|
dirty := make(map[common.Address]struct{})
|
||||||
for _, tx := range txs {
|
txErr := make([]error, len(txs))
|
||||||
if replace, err := pool.add(tx, local); err == nil {
|
for i, tx := range txs {
|
||||||
|
var replace bool
|
||||||
|
if replace, txErr[i] = pool.add(tx, local); txErr[i] == nil {
|
||||||
if !replace {
|
if !replace {
|
||||||
from, _ := types.Sender(pool.signer, tx) // already validated
|
from, _ := types.Sender(pool.signer, tx) // already validated
|
||||||
dirty[from] = struct{}{}
|
dirty[from] = struct{}{}
|
||||||
|
|
@ -807,7 +819,58 @@ func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) error {
|
||||||
}
|
}
|
||||||
pool.promoteExecutables(addrs)
|
pool.promoteExecutables(addrs)
|
||||||
}
|
}
|
||||||
return nil
|
return txErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxStatusData is returned by AddOrGetTxStatus for each transaction
|
||||||
|
type TxStatusData struct {
|
||||||
|
Status uint
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TxStatusUnknown = iota
|
||||||
|
TxStatusQueued
|
||||||
|
TxStatusPending
|
||||||
|
TxStatusIncluded // Data contains a TxChainPos struct
|
||||||
|
TxStatusError // Data contains the error string
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddOrGetTxStatus returns the status (unknown/pending/queued) of a batch of transactions
|
||||||
|
// identified by their hashes in txHashes. Optionally the transactions themselves can be
|
||||||
|
// passed too in txs, in which case the function will try adding the previously unknown ones
|
||||||
|
// to the pool. If a new transaction cannot be added, TxStatusError is returned. Adding already
|
||||||
|
// known transactions will return their previous status.
|
||||||
|
// If txs is specified, txHashes is still required and has to match the transactions in txs.
|
||||||
|
|
||||||
|
// Note: TxStatusIncluded is never returned by this function since the pool does not track
|
||||||
|
// mined transactions. Included status can be checked by the caller (as it happens in the
|
||||||
|
// LES protocol manager)
|
||||||
|
func (pool *TxPool) AddOrGetTxStatus(txs []*types.Transaction, txHashes []common.Hash) []TxStatusData {
|
||||||
|
status := make([]TxStatusData, len(txHashes))
|
||||||
|
if txs != nil {
|
||||||
|
if len(txs) != len(txHashes) {
|
||||||
|
panic(nil)
|
||||||
|
}
|
||||||
|
txErr := pool.addTxs(txs, false)
|
||||||
|
for i, err := range txErr {
|
||||||
|
if err != nil {
|
||||||
|
status[i] = TxStatusData{TxStatusError, ([]byte)(err.Error())}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, hash := range txHashes {
|
||||||
|
r, ok := pool.all[hash]
|
||||||
|
if ok {
|
||||||
|
if r.pending {
|
||||||
|
status[i] = TxStatusData{TxStatusPending, nil}
|
||||||
|
} else {
|
||||||
|
status[i] = TxStatusData{TxStatusQueued, nil}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns a transaction if it is contained in the pool
|
// Get returns a transaction if it is contained in the pool
|
||||||
|
|
@ -816,17 +879,18 @@ func (pool *TxPool) Get(hash common.Hash) *types.Transaction {
|
||||||
pool.mu.RLock()
|
pool.mu.RLock()
|
||||||
defer pool.mu.RUnlock()
|
defer pool.mu.RUnlock()
|
||||||
|
|
||||||
return pool.all[hash]
|
return pool.all[hash].tx
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeTx removes a single transaction from the queue, moving all subsequent
|
// removeTx removes a single transaction from the queue, moving all subsequent
|
||||||
// transactions back to the future queue.
|
// transactions back to the future queue.
|
||||||
func (pool *TxPool) removeTx(hash common.Hash) {
|
func (pool *TxPool) removeTx(hash common.Hash) {
|
||||||
// Fetch the transaction we wish to delete
|
// Fetch the transaction we wish to delete
|
||||||
tx, ok := pool.all[hash]
|
txl, ok := pool.all[hash]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
tx := txl.tx
|
||||||
addr, _ := types.Sender(pool.signer, tx) // already validated during insertion
|
addr, _ := types.Sender(pool.signer, tx) // already validated during insertion
|
||||||
|
|
||||||
// Remove it from the list of known transactions
|
// Remove it from the list of known transactions
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ const (
|
||||||
MaxProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request
|
MaxProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request
|
||||||
MaxPPTProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request
|
MaxPPTProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request
|
||||||
MaxTxSend = 64 // Amount of transactions to be send per request
|
MaxTxSend = 64 // Amount of transactions to be send per request
|
||||||
|
MaxTxStatus = 256 // Amount of transactions to queried per request
|
||||||
|
|
||||||
disableClientRemovePeer = false
|
disableClientRemovePeer = false
|
||||||
)
|
)
|
||||||
|
|
@ -88,8 +89,7 @@ type BlockChain interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type txPool interface {
|
type txPool interface {
|
||||||
// AddRemotes should add the given transactions to the pool.
|
AddOrGetTxStatus(txs []*types.Transaction, txHashes []common.Hash) []core.TxStatusData
|
||||||
AddRemotes([]*types.Transaction) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProtocolManager struct {
|
type ProtocolManager struct {
|
||||||
|
|
@ -318,7 +318,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var reqList = []uint64{GetBlockHeadersMsg, GetBlockBodiesMsg, GetCodeMsg, GetReceiptsMsg, GetProofsV1Msg, SendTxMsg, GetHeaderProofsMsg, GetProofsV2Msg, GetPPTProofsMsg}
|
var reqList = []uint64{GetBlockHeadersMsg, GetBlockBodiesMsg, GetCodeMsg, GetReceiptsMsg, GetProofsV1Msg, SendTxMsg, SendTxV2Msg, GetTxStatusMsg, GetHeaderProofsMsg, GetProofsV2Msg, GetPPTProofsMsg}
|
||||||
|
|
||||||
// handleMsg is invoked whenever an inbound message is received from a remote
|
// handleMsg is invoked whenever an inbound message is received from a remote
|
||||||
// peer. The remote connection is torn down upon returning any error.
|
// peer. The remote connection is torn down upon returning any error.
|
||||||
|
|
@ -972,7 +972,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
||||||
|
|
||||||
case SendTxMsg:
|
case SendTxMsg:
|
||||||
if pm.txpool == nil {
|
if pm.txpool == nil {
|
||||||
return errResp(ErrUnexpectedResponse, "")
|
return errResp(ErrRequestRejected, "")
|
||||||
}
|
}
|
||||||
// Transactions arrived, parse all of them and deliver to the pool
|
// Transactions arrived, parse all of them and deliver to the pool
|
||||||
var txs []*types.Transaction
|
var txs []*types.Transaction
|
||||||
|
|
@ -984,13 +984,82 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
||||||
return errResp(ErrRequestRejected, "")
|
return errResp(ErrRequestRejected, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := pm.txpool.AddRemotes(txs); err != nil {
|
txHashes := make([]common.Hash, len(txs))
|
||||||
return errResp(ErrUnexpectedResponse, "msg: %v", err)
|
for i, tx := range txs {
|
||||||
|
txHashes[i] = tx.Hash()
|
||||||
}
|
}
|
||||||
|
pm.addOrGetTxStatus(txs, txHashes)
|
||||||
|
|
||||||
_, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
|
_, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
|
||||||
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
|
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
|
||||||
|
|
||||||
|
case SendTxV2Msg:
|
||||||
|
if pm.txpool == nil {
|
||||||
|
return errResp(ErrRequestRejected, "")
|
||||||
|
}
|
||||||
|
// Transactions arrived, parse all of them and deliver to the pool
|
||||||
|
var req struct {
|
||||||
|
ReqID uint64
|
||||||
|
Txs []*types.Transaction
|
||||||
|
}
|
||||||
|
if err := msg.Decode(&req); err != nil {
|
||||||
|
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
||||||
|
}
|
||||||
|
reqCnt := len(req.Txs)
|
||||||
|
if reject(uint64(reqCnt), MaxTxSend) {
|
||||||
|
return errResp(ErrRequestRejected, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
txHashes := make([]common.Hash, len(req.Txs))
|
||||||
|
for i, tx := range req.Txs {
|
||||||
|
txHashes[i] = tx.Hash()
|
||||||
|
}
|
||||||
|
|
||||||
|
res := pm.addOrGetTxStatus(req.Txs, txHashes)
|
||||||
|
|
||||||
|
bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
|
||||||
|
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
|
||||||
|
return p.SendTxStatus(req.ReqID, bv, res)
|
||||||
|
|
||||||
|
case GetTxStatusMsg:
|
||||||
|
if pm.txpool == nil {
|
||||||
|
return errResp(ErrUnexpectedResponse, "")
|
||||||
|
}
|
||||||
|
// Transactions arrived, parse all of them and deliver to the pool
|
||||||
|
var req struct {
|
||||||
|
ReqID uint64
|
||||||
|
TxHashes []common.Hash
|
||||||
|
}
|
||||||
|
if err := msg.Decode(&req); err != nil {
|
||||||
|
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
||||||
|
}
|
||||||
|
reqCnt := len(req.TxHashes)
|
||||||
|
if reject(uint64(reqCnt), MaxTxStatus) {
|
||||||
|
return errResp(ErrRequestRejected, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
res := pm.addOrGetTxStatus(nil, req.TxHashes)
|
||||||
|
|
||||||
|
bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
|
||||||
|
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
|
||||||
|
return p.SendTxStatus(req.ReqID, bv, res)
|
||||||
|
|
||||||
|
case TxStatusMsg:
|
||||||
|
if pm.odr == nil {
|
||||||
|
return errResp(ErrUnexpectedResponse, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Log().Trace("Received tx status response")
|
||||||
|
var resp struct {
|
||||||
|
ReqID, BV uint64
|
||||||
|
Status []core.TxStatusData
|
||||||
|
}
|
||||||
|
if err := msg.Decode(&resp); err != nil {
|
||||||
|
return errResp(ErrDecode, "msg %v: %v", msg, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.fcServer.GotReply(resp.ReqID, resp.BV)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
p.Log().Trace("Received unknown message", "code", msg.Code)
|
p.Log().Trace("Received unknown message", "code", msg.Code)
|
||||||
return errResp(ErrInvalidMsgCode, "%v", msg.Code)
|
return errResp(ErrInvalidMsgCode, "%v", msg.Code)
|
||||||
|
|
@ -1034,6 +1103,21 @@ func (pm *ProtocolManager) getPPTAuxData(req PPTReq) []byte {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pm *ProtocolManager) addOrGetTxStatus(txs []*types.Transaction, txHashes []common.Hash) []core.TxStatusData {
|
||||||
|
status := pm.txpool.AddOrGetTxStatus(txs, txHashes)
|
||||||
|
for i, _ := range status {
|
||||||
|
blockHash, blockNum, txIndex := core.GetTxLookupEntry(pm.chainDb, txHashes[i])
|
||||||
|
if blockHash != (common.Hash{}) {
|
||||||
|
enc, err := rlp.EncodeToBytes(core.TxLookupEntry{BlockHash: blockHash, BlockIndex: blockNum, Index: txIndex})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
status[i] = core.TxStatusData{Status: core.TxStatusIncluded, Data: enc}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
|
||||||
// NodeInfo retrieves some protocol metadata about the running host node.
|
// NodeInfo retrieves some protocol metadata about the running host node.
|
||||||
func (self *ProtocolManager) NodeInfo() *eth.EthNodeInfo {
|
func (self *ProtocolManager) NodeInfo() *eth.EthNodeInfo {
|
||||||
return ð.EthNodeInfo{
|
return ð.EthNodeInfo{
|
||||||
|
|
|
||||||
15
les/peer.go
15
les/peer.go
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
||||||
|
|
@ -231,6 +232,11 @@ func (p *peer) SendPPTProofs(reqID, bv uint64, resp PPTResps) error {
|
||||||
return sendResponse(p.rw, PPTProofsMsg, reqID, bv, resp)
|
return sendResponse(p.rw, PPTProofsMsg, reqID, bv, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendTxStatus sends a batch of transaction status records, corresponding to the ones requested.
|
||||||
|
func (p *peer) SendTxStatus(reqID, bv uint64, status []core.TxStatusData) error {
|
||||||
|
return sendResponse(p.rw, TxStatusMsg, reqID, bv, status)
|
||||||
|
}
|
||||||
|
|
||||||
// RequestHeadersByHash fetches a batch of blocks' headers corresponding to the
|
// RequestHeadersByHash fetches a batch of blocks' headers corresponding to the
|
||||||
// specified header query, based on the hash of an origin block.
|
// specified header query, based on the hash of an origin block.
|
||||||
func (p *peer) RequestHeadersByHash(reqID, cost uint64, origin common.Hash, amount int, skip int, reverse bool) error {
|
func (p *peer) RequestHeadersByHash(reqID, cost uint64, origin common.Hash, amount int, skip int, reverse bool) error {
|
||||||
|
|
@ -303,7 +309,14 @@ func (p *peer) RequestPPTProofs(reqID, cost uint64, reqs []PPTReq) error {
|
||||||
|
|
||||||
func (p *peer) SendTxs(reqID, cost uint64, txs types.Transactions) error {
|
func (p *peer) SendTxs(reqID, cost uint64, txs types.Transactions) error {
|
||||||
p.Log().Debug("Fetching batch of transactions", "count", len(txs))
|
p.Log().Debug("Fetching batch of transactions", "count", len(txs))
|
||||||
return p2p.Send(p.rw, SendTxMsg, txs)
|
switch p.version {
|
||||||
|
case lpv1:
|
||||||
|
return p2p.Send(p.rw, SendTxMsg, txs) // old message format does not include reqID
|
||||||
|
case lpv2:
|
||||||
|
return sendRequest(p.rw, SendTxV2Msg, reqID, cost, txs)
|
||||||
|
default:
|
||||||
|
panic(nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type keyValueEntry struct {
|
type keyValueEntry struct {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Number of implemented message corresponding to different protocol versions.
|
// Number of implemented message corresponding to different protocol versions.
|
||||||
var ProtocolLengths = map[uint]uint64{lpv1: 15, lpv2: 19}
|
var ProtocolLengths = map[uint]uint64{lpv1: 15, lpv2: 22}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NetworkId = 1
|
NetworkId = 1
|
||||||
|
|
@ -75,6 +75,9 @@ const (
|
||||||
ProofsV2Msg = 0x10
|
ProofsV2Msg = 0x10
|
||||||
GetPPTProofsMsg = 0x11
|
GetPPTProofsMsg = 0x11
|
||||||
PPTProofsMsg = 0x12
|
PPTProofsMsg = 0x12
|
||||||
|
SendTxV2Msg = 0x13
|
||||||
|
GetTxStatusMsg = 0x14
|
||||||
|
TxStatusMsg = 0x15
|
||||||
)
|
)
|
||||||
|
|
||||||
type errCode int
|
type errCode int
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue