mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
fixed mined tx detection and storage
This commit is contained in:
parent
68ae0c411d
commit
5937563956
4 changed files with 71 additions and 29 deletions
|
|
@ -618,6 +618,37 @@ func (self *BlockChain) Rollback(chain []common.Hash) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetReceiptsData computes all the non-consensus fields of the receipts
|
||||||
|
func SetReceiptsData(block *types.Block, receipts types.Receipts) {
|
||||||
|
transactions, logIndex := block.Transactions(), uint(0)
|
||||||
|
|
||||||
|
for j := 0; j < len(receipts); j++ {
|
||||||
|
// The transaction hash can be retrieved from the transaction itself
|
||||||
|
receipts[j].TxHash = transactions[j].Hash()
|
||||||
|
|
||||||
|
// The contract address can be derived from the transaction itself
|
||||||
|
if MessageCreatesContract(transactions[j]) {
|
||||||
|
from, _ := transactions[j].From()
|
||||||
|
receipts[j].ContractAddress = crypto.CreateAddress(from, transactions[j].Nonce())
|
||||||
|
}
|
||||||
|
// The used gas can be calculated based on previous receipts
|
||||||
|
if j == 0 {
|
||||||
|
receipts[j].GasUsed = new(big.Int).Set(receipts[j].CumulativeGasUsed)
|
||||||
|
} else {
|
||||||
|
receipts[j].GasUsed = new(big.Int).Sub(receipts[j].CumulativeGasUsed, receipts[j-1].CumulativeGasUsed)
|
||||||
|
}
|
||||||
|
// The derived log fields can simply be set from the block and transaction
|
||||||
|
for k := 0; k < len(receipts[j].Logs); k++ {
|
||||||
|
receipts[j].Logs[k].BlockNumber = block.NumberU64()
|
||||||
|
receipts[j].Logs[k].BlockHash = block.Hash()
|
||||||
|
receipts[j].Logs[k].TxHash = receipts[j].TxHash
|
||||||
|
receipts[j].Logs[k].TxIndex = uint(j)
|
||||||
|
receipts[j].Logs[k].Index = logIndex
|
||||||
|
logIndex++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// InsertReceiptChain attempts to complete an already existing header chain with
|
// InsertReceiptChain attempts to complete an already existing header chain with
|
||||||
// transaction and receipt data.
|
// transaction and receipt data.
|
||||||
func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
|
func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
|
||||||
|
|
@ -659,32 +690,7 @@ func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Compute all the non-consensus fields of the receipts
|
// Compute all the non-consensus fields of the receipts
|
||||||
transactions, logIndex := block.Transactions(), uint(0)
|
SetReceiptsData(block, receipts)
|
||||||
for j := 0; j < len(receipts); j++ {
|
|
||||||
// The transaction hash can be retrieved from the transaction itself
|
|
||||||
receipts[j].TxHash = transactions[j].Hash()
|
|
||||||
|
|
||||||
// The contract address can be derived from the transaction itself
|
|
||||||
if MessageCreatesContract(transactions[j]) {
|
|
||||||
from, _ := transactions[j].From()
|
|
||||||
receipts[j].ContractAddress = crypto.CreateAddress(from, transactions[j].Nonce())
|
|
||||||
}
|
|
||||||
// The used gas can be calculated based on previous receipts
|
|
||||||
if j == 0 {
|
|
||||||
receipts[j].GasUsed = new(big.Int).Set(receipts[j].CumulativeGasUsed)
|
|
||||||
} else {
|
|
||||||
receipts[j].GasUsed = new(big.Int).Sub(receipts[j].CumulativeGasUsed, receipts[j-1].CumulativeGasUsed)
|
|
||||||
}
|
|
||||||
// The derived log fields can simply be set from the block and transaction
|
|
||||||
for k := 0; k < len(receipts[j].Logs); k++ {
|
|
||||||
receipts[j].Logs[k].BlockNumber = block.NumberU64()
|
|
||||||
receipts[j].Logs[k].BlockHash = block.Hash()
|
|
||||||
receipts[j].Logs[k].TxHash = receipts[j].TxHash
|
|
||||||
receipts[j].Logs[k].TxIndex = uint(j)
|
|
||||||
receipts[j].Logs[k].Index = logIndex
|
|
||||||
logIndex++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Write all the data out into the database
|
// Write all the data out into the database
|
||||||
if err := WriteBody(self.chainDb, block.Hash(), block.NumberU64(), block.Body()); err != nil {
|
if err := WriteBody(self.chainDb, block.Hash(), block.NumberU64(), block.Body()); err != nil {
|
||||||
errs[index] = fmt.Errorf("failed to write block body: %v", err)
|
errs[index] = fmt.Errorf("failed to write block body: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -447,6 +447,16 @@ func WriteTransactions(db ethdb.Database, block *types.Block) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteReceipt stores a single transaction receipt into the database.
|
||||||
|
func WriteReceipt(db ethdb.Database, receipt *types.Receipt) error {
|
||||||
|
storageReceipt := (*types.ReceiptForStorage)(receipt)
|
||||||
|
data, err := rlp.EncodeToBytes(storageReceipt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return db.Put(append(receiptsPrefix, receipt.TxHash.Bytes()...), data)
|
||||||
|
}
|
||||||
|
|
||||||
// WriteReceipts stores a batch of transaction receipts into the database.
|
// WriteReceipts stores a batch of transaction receipts into the database.
|
||||||
func WriteReceipts(db ethdb.Database, receipts types.Receipts) error {
|
func WriteReceipts(db ethdb.Database, receipts types.Receipts) error {
|
||||||
batch := db.NewBatch()
|
batch := db.NewBatch()
|
||||||
|
|
|
||||||
|
|
@ -1024,6 +1024,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, txH
|
||||||
|
|
||||||
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
|
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
|
||||||
func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (map[string]interface{}, error) {
|
func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (map[string]interface{}, error) {
|
||||||
|
//fmt.Println("API GetTransactionReceipt", txHash)
|
||||||
receipt := core.GetReceipt(s.b.ChainDb(), txHash)
|
receipt := core.GetReceipt(s.b.ChainDb(), txHash)
|
||||||
if receipt == nil {
|
if receipt == nil {
|
||||||
glog.V(logger.Debug).Infof("receipt not found for transaction %s", txHash.Hex())
|
glog.V(logger.Debug).Infof("receipt not found for transaction %s", txHash.Hex())
|
||||||
|
|
@ -1031,12 +1032,14 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma
|
||||||
}
|
}
|
||||||
|
|
||||||
tx, _, err := getTransaction(s.b.ChainDb(), s.b, txHash)
|
tx, _, err := getTransaction(s.b.ChainDb(), s.b, txHash)
|
||||||
|
//fmt.Println("getTransaction", err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(logger.Debug).Infof("%v\n", err)
|
glog.V(logger.Debug).Infof("%v\n", err)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
txBlock, blockIndex, index, err := getTransactionBlockData(s.b.ChainDb(), txHash)
|
txBlock, blockIndex, index, err := getTransactionBlockData(s.b.ChainDb(), txHash)
|
||||||
|
//fmt.Println("getTransactionBlockData", txBlock, blockIndex, index, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(logger.Debug).Infof("%v\n", err)
|
glog.V(logger.Debug).Infof("%v\n", err)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
||||||
|
|
@ -128,12 +128,14 @@ type txBlockData struct {
|
||||||
|
|
||||||
// storeTxBlockData stores the block position of a mined tx in the local db
|
// storeTxBlockData stores the block position of a mined tx in the local db
|
||||||
func (pool *TxPool) storeTxBlockData(txh common.Hash, tbd txBlockData) {
|
func (pool *TxPool) storeTxBlockData(txh common.Hash, tbd txBlockData) {
|
||||||
|
//fmt.Println("storeTxBlockData", txh, tbd)
|
||||||
data, _ := rlp.EncodeToBytes(tbd)
|
data, _ := rlp.EncodeToBytes(tbd)
|
||||||
pool.chainDb.Put(append(txh[:], byte(1)), data)
|
pool.chainDb.Put(append(txh[:], byte(1)), data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeTxBlockData removes the stored block position of a rolled back tx
|
// removeTxBlockData removes the stored block position of a rolled back tx
|
||||||
func (pool *TxPool) removeTxBlockData(txh common.Hash) {
|
func (pool *TxPool) removeTxBlockData(txh common.Hash) {
|
||||||
|
//fmt.Println("removeTxBlockData", txh)
|
||||||
pool.chainDb.Delete(append(txh[:], byte(1)))
|
pool.chainDb.Delete(append(txh[:], byte(1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,18 +169,38 @@ func (txc txStateChanges) getLists() (mined []common.Hash, rollback []common.Has
|
||||||
// and marks them as mined if necessary. It also stores block position in the db
|
// and marks them as mined if necessary. It also stores block position in the db
|
||||||
// and adds them to the received txStateChanges map.
|
// and adds them to the received txStateChanges map.
|
||||||
func (pool *TxPool) checkMinedTxs(ctx context.Context, hash common.Hash, idx uint64, txc txStateChanges) error {
|
func (pool *TxPool) checkMinedTxs(ctx context.Context, hash common.Hash, idx uint64, txc txStateChanges) error {
|
||||||
|
//fmt.Println("checkMinedTxs")
|
||||||
if len(pool.pending) == 0 {
|
if len(pool.pending) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
//fmt.Println("len(pool) =", len(pool.pending))
|
||||||
|
|
||||||
receipts, err := GetBlockReceipts(ctx, pool.odr, hash, idx)
|
block, err := GetBlock(ctx, pool.odr, hash, idx)
|
||||||
|
var receipts types.Receipts
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
//fmt.Println(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
//fmt.Println("len(block.Transactions()) =", len(block.Transactions()))
|
||||||
|
|
||||||
list := pool.mined[hash]
|
list := pool.mined[hash]
|
||||||
for i, receipt := range receipts {
|
for i, tx := range block.Transactions() {
|
||||||
txHash := receipt.TxHash
|
txHash := tx.Hash()
|
||||||
|
//fmt.Println(" txHash:", txHash)
|
||||||
if tx, ok := pool.pending[txHash]; ok {
|
if tx, ok := pool.pending[txHash]; ok {
|
||||||
|
//fmt.Println("TX FOUND")
|
||||||
|
if receipts == nil {
|
||||||
|
receipts, err = GetBlockReceipts(ctx, pool.odr, hash, idx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(receipts) != len(block.Transactions()) {
|
||||||
|
panic(nil) // should never happen if hashes did match
|
||||||
|
}
|
||||||
|
core.SetReceiptsData(block, receipts)
|
||||||
|
}
|
||||||
|
//fmt.Println("WriteReceipt", receipts[i].TxHash)
|
||||||
|
core.WriteReceipt(pool.chainDb, receipts[i])
|
||||||
pool.storeTxBlockData(txHash, txBlockData{hash, idx, uint64(i)})
|
pool.storeTxBlockData(txHash, txBlockData{hash, idx, uint64(i)})
|
||||||
delete(pool.pending, txHash)
|
delete(pool.pending, txHash)
|
||||||
list = append(list, tx)
|
list = append(list, tx)
|
||||||
|
|
@ -428,6 +450,7 @@ func (self *TxPool) Add(ctx context.Context, tx *types.Transaction) error {
|
||||||
if err := self.add(ctx, tx); err != nil {
|
if err := self.add(ctx, tx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
//fmt.Println("Send", tx.Hash())
|
||||||
self.relay.Send(types.Transactions{tx})
|
self.relay.Send(types.Transactions{tx})
|
||||||
|
|
||||||
self.chainDb.Put(tx.Hash().Bytes(), data)
|
self.chainDb.Put(tx.Hash().Bytes(), data)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue