diff --git a/core/types/transaction.go b/core/types/transaction.go index ba3d5de91de1..4cfa639ba22f 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -43,6 +43,11 @@ type Transaction struct { from atomic.Value } +type TransactionEx struct { + Tx *Transaction + From common.Address `json:"from" rlp:"nil"` +} + type txdata struct { AccountNonce uint64 `json:"nonce" gencodec:"required"` Price *big.Int `json:"gasPrice" gencodec:"required"` @@ -212,6 +217,60 @@ func (tx *Transaction) Size() common.StorageSize { return common.StorageSize(c) } +// Convert []*Transaction to []*TransactionEx +func Txs2TxExs(txs []*Transaction) []*TransactionEx { + var out []*TransactionEx + for _, i := range txs { + var from common.Address + if sc := i.from.Load(); sc != nil { + from = sc.(sigCache).from + } + j := &TransactionEx{ + Tx: i, + From: from, + } + out = append(out, j) + } + return out +} + +// Convert []*TransactionEx to []*Transaction +func TxExs2Txs(signer Signer, txs []*TransactionEx, trustIt bool) []*Transaction { + var out []*Transaction + for _, i := range txs { + if trustIt { + i.Tx.from.Store(sigCache{signer: signer, from: i.From}) + } + out = append(out, i.Tx) + } + return out +} + +// EncodeRLP implements rlp.Encoder +func (tx *TransactionEx) EncodeRLP(w io.Writer) error { + if err := rlp.Encode(w, &tx.Tx.data); err != nil { + return err + } + var from common.Address + if sc := tx.Tx.from.Load(); sc != nil { + from = sc.(sigCache).from + } + return rlp.Encode(w, &from) +} + +// DecodeRLP implements rlp.Decoder +func (tx *TransactionEx) DecodeRLP(s *rlp.Stream) error { + tx.Tx = &Transaction{} + _, size, _ := s.Kind() + err := s.Decode(&tx.Tx.data) + if err != nil { + return err + } else { + tx.Tx.size.Store(common.StorageSize(rlp.ListSize(size))) + } + return s.Decode(&tx.From) +} + // AsMessage returns the transaction as a core.Message. // // AsMessage requires a signer to derive the sender. diff --git a/eth/handler.go b/eth/handler.go index 76c894857586..486ca6b8a320 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -832,6 +832,34 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { }() return nil + case p.version >= eth64 && msg.Code == TxExMsg: + // Transactions arrived, make sure we have a valid and fresh chain to handle them + if atomic.LoadUint32(&pm.acceptTxs) == 0 { + break + } + // Transactions can be processed, parse all of them and deliver to the pool + var txexs []*types.TransactionEx + if err := msg.Decode(&txexs); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + + // Metadium: it's non-blocking now + go func() error { + signer := types.MakeSigner(pm.chainconfig, pm.blockchain.CurrentBlock().Number()) + txs := types.TxExs2Txs(signer, txexs, metaminer.IsPartner(p.ID().String())) + for i, tx := range txs { + // Validate and mark the remote transaction + if tx == nil { + return errResp(ErrDecode, "transaction %d is nil", i) + } + p.MarkTransaction(tx.Hash()) + } + //pm.txpool.AddRemotes(txs) + remoteTxCh <- txs + return nil + }() + return nil + // Metadium: leader wants to get left-over transactions if any case p.version >= eth63 && msg.Code == GetPendingTxsMsg: if !metaminer.IsPartner(p.ID().String()) { diff --git a/eth/peer.go b/eth/peer.go index 6e935bafc968..2e67dd41ff6f 100644 --- a/eth/peer.go +++ b/eth/peer.go @@ -210,7 +210,11 @@ func (p *peer) SendTransactions(txs types.Transactions) error { for _, tx := range txs { p.knownTxs.Put(tx.Hash(), true) } - return p2p.Send(p.rw, TxMsg, txs) + if p.version >= eth64 { + return p2p.Send(p.rw, TxExMsg, types.Txs2TxExs(txs)) + } else { + return p2p.Send(p.rw, TxMsg, txs) + } } // AsyncSendTransactions queues list of transactions propagation to a remote diff --git a/eth/protocol.go b/eth/protocol.go index c370594f7bf4..aafdb8f4d723 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -32,16 +32,17 @@ import ( const ( eth62 = 62 eth63 = 63 + eth64 = 64 ) // ProtocolName is the official short name of the protocol used during capability negotiation. var ProtocolName = "meta" // ProtocolVersions are the supported versions of the eth protocol (first is primary). -var ProtocolVersions = []uint{eth63, eth62} +var ProtocolVersions = []uint{eth64, eth63, eth62} // ProtocolLengths are the number of implemented message corresponding to different protocol versions. -var ProtocolLengths = []uint64{22, 8} +var ProtocolLengths = []uint64{23, 22, 8} const ProtocolMaxMsgSize = 100 * 1024 * 1024 // Maximum cap on the size of a protocol message @@ -69,6 +70,7 @@ const ( StatusExMsg = 0x13 EtcdAddMemberMsg = 0x14 EtcdClusterMsg = 0x15 + TxExMsg = 0x16 ) type errCode int