core: fixed an issue with storing receipts
This commit is contained in:
		| @@ -102,7 +102,7 @@ window.filter = filter; | ||||
| 		var amount = parseInt( value.value ); | ||||
| 		console.log("transact: ", to.value, " => ", amount) | ||||
|  | ||||
| 		contract.sendTransaction({from: eth.accounts[0]}).send( to.value, amount ); | ||||
| 		contract.send.sendTransaction(to.value, amount ,{from: eth.accounts[0]}); | ||||
|  | ||||
| 		to.value = ""; | ||||
| 		value.value = ""; | ||||
|   | ||||
| @@ -40,11 +40,6 @@ type BlockProcessor struct { | ||||
|  | ||||
| 	txpool *TxPool | ||||
|  | ||||
| 	// The last attempted block is mainly used for debugging purposes | ||||
| 	// This does not have to be a valid block and will be set during | ||||
| 	// 'Process' & canonical validation. | ||||
| 	lastAttemptedBlock *types.Block | ||||
|  | ||||
| 	events event.Subscription | ||||
|  | ||||
| 	eventMux *event.TypeMux | ||||
| @@ -188,8 +183,6 @@ func (sm *BlockProcessor) Process(block *types.Block) (logs state.Logs, err erro | ||||
| } | ||||
|  | ||||
| func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.Logs, err error) { | ||||
| 	sm.lastAttemptedBlock = block | ||||
|  | ||||
| 	// Create a new state based on the parent's root (e.g., create copy) | ||||
| 	state := state.New(parent.Root(), sm.db) | ||||
|  | ||||
| @@ -255,6 +248,12 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// store the receipts | ||||
| 	err = putReceipts(sm.extraDb, block.Hash(), receipts) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// Calculate the td for this block | ||||
| 	//td = CalculateTD(block, parent) | ||||
| 	// Sync the current block's state to the database | ||||
| @@ -268,23 +267,9 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st | ||||
| 		putTx(sm.extraDb, tx, block, uint64(i)) | ||||
| 	} | ||||
|  | ||||
| 	receiptsRlp := block.Receipts().RlpEncode() | ||||
| 	sm.extraDb.Put(append(receiptsPre, block.Hash().Bytes()...), receiptsRlp) | ||||
|  | ||||
| 	return state.Logs(), nil | ||||
| } | ||||
|  | ||||
| func (self *BlockProcessor) GetBlockReceipts(bhash common.Hash) (receipts types.Receipts, err error) { | ||||
| 	var rdata []byte | ||||
| 	rdata, err = self.extraDb.Get(append(receiptsPre, bhash[:]...)) | ||||
|  | ||||
| 	if err == nil { | ||||
| 		err = rlp.DecodeBytes(rdata, &receipts) | ||||
| 	} | ||||
| 	return | ||||
|  | ||||
| } | ||||
|  | ||||
| // See YP section 4.3.4. "Block Header Validity" | ||||
| // Validates a block. Returns an error if the block is invalid. | ||||
| func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header, checkPow bool) error { | ||||
| @@ -391,13 +376,25 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // GetBlockReceipts returns the receipts beloniging to the block hash | ||||
| func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) (receipts types.Receipts, err error) { | ||||
| 	return getBlockReceipts(sm.extraDb, bhash) | ||||
| } | ||||
|  | ||||
| // GetLogs returns the logs of the given block. This method is using a two step approach | ||||
| // where it tries to get it from the (updated) method which gets them from the receipts or | ||||
| // the depricated way by re-processing the block. | ||||
| func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) { | ||||
| 	if !sm.bc.HasBlock(block.Header().ParentHash) { | ||||
| 		return nil, ParentError(block.Header().ParentHash) | ||||
| 	receipts, err := sm.GetBlockReceipts(block.Hash()) | ||||
| 	if err == nil && len(receipts) > 0 { | ||||
| 		// coalesce logs | ||||
| 		for _, receipt := range receipts { | ||||
| 			logs = append(logs, receipt.Logs()...) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	sm.lastAttemptedBlock = block | ||||
|  | ||||
| 	// TODO: remove backward compatibility | ||||
| 	var ( | ||||
| 		parent = sm.bc.GetBlock(block.Header().ParentHash) | ||||
| 		state  = state.New(parent.Root(), sm.db) | ||||
| @@ -408,6 +405,16 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro | ||||
| 	return state.Logs(), nil | ||||
| } | ||||
|  | ||||
| func getBlockReceipts(db common.Database, bhash common.Hash) (receipts types.Receipts, err error) { | ||||
| 	var rdata []byte | ||||
| 	rdata, err = db.Get(append(receiptsPre, bhash[:]...)) | ||||
|  | ||||
| 	if err == nil { | ||||
| 		err = rlp.DecodeBytes(rdata, &receipts) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func putTx(db common.Database, tx *types.Transaction, block *types.Block, i uint64) { | ||||
| 	rlpEnc, err := rlp.EncodeToBytes(tx) | ||||
| 	if err != nil { | ||||
| @@ -431,3 +438,19 @@ func putTx(db common.Database, tx *types.Transaction, block *types.Block, i uint | ||||
| 	} | ||||
| 	db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) | ||||
| } | ||||
|  | ||||
| func putReceipts(db common.Database, hash common.Hash, receipts types.Receipts) error { | ||||
| 	storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) | ||||
| 	for i, receipt := range receipts { | ||||
| 		storageReceipts[i] = (*types.ReceiptForStorage)(receipt) | ||||
| 	} | ||||
|  | ||||
| 	bytes, err := rlp.EncodeToBytes(storageReceipts) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	db.Put(append(receiptsPre, hash[:]...), bytes) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -5,6 +5,8 @@ import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/core/state" | ||||
| 	"github.com/ethereum/go-ethereum/core/types" | ||||
| 	"github.com/ethereum/go-ethereum/ethdb" | ||||
| 	"github.com/ethereum/go-ethereum/event" | ||||
| 	"github.com/ethereum/go-ethereum/pow/ezp" | ||||
| @@ -35,3 +37,33 @@ func TestNumber(t *testing.T) { | ||||
| 		t.Errorf("didn't expect block number error") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestPutReceipt(t *testing.T) { | ||||
| 	db, _ := ethdb.NewMemDatabase() | ||||
|  | ||||
| 	var addr common.Address | ||||
| 	addr[0] = 1 | ||||
| 	var hash common.Hash | ||||
| 	hash[0] = 2 | ||||
|  | ||||
| 	receipt := new(types.Receipt) | ||||
| 	receipt.SetLogs(state.Logs{&state.Log{ | ||||
| 		Address:   addr, | ||||
| 		Topics:    []common.Hash{hash}, | ||||
| 		Data:      []byte("hi"), | ||||
| 		Number:    42, | ||||
| 		TxHash:    hash, | ||||
| 		TxIndex:   0, | ||||
| 		BlockHash: hash, | ||||
| 		Index:     0, | ||||
| 	}}) | ||||
|  | ||||
| 	putReceipts(db, hash, types.Receipts{receipt}) | ||||
| 	receipts, err := getBlockReceipts(db, hash) | ||||
| 	if err != nil { | ||||
| 		t.Error("got err:", err) | ||||
| 	} | ||||
| 	if len(receipts) != 1 { | ||||
| 		t.Error("expected to get 1 receipt, got", len(receipts)) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -29,15 +29,22 @@ func (self *Log) EncodeRLP(w io.Writer) error { | ||||
| } | ||||
|  | ||||
| func (self *Log) String() string { | ||||
| 	return fmt.Sprintf(`log: %x %x %x`, self.Address, self.Topics, self.Data) | ||||
| 	return fmt.Sprintf(`log: %x %x %x %x %d %x %d`, self.Address, self.Topics, self.Data, self.TxHash, self.TxIndex, self.BlockHash, self.Index) | ||||
| } | ||||
|  | ||||
| type Logs []*Log | ||||
|  | ||||
| func (self Logs) String() (ret string) { | ||||
| 	for _, log := range self { | ||||
| 		ret += fmt.Sprintf("%v", log) | ||||
| 	} | ||||
| type LogForStorage Log | ||||
|  | ||||
| 	return "[" + ret + "]" | ||||
| func (self *LogForStorage) EncodeRLP(w io.Writer) error { | ||||
| 	return rlp.Encode(w, []interface{}{ | ||||
| 		self.Address, | ||||
| 		self.Topics, | ||||
| 		self.Data, | ||||
| 		self.Number, | ||||
| 		self.TxHash, | ||||
| 		self.TxIndex, | ||||
| 		self.BlockHash, | ||||
| 		self.Index, | ||||
| 	}) | ||||
| } | ||||
|   | ||||
| @@ -26,10 +26,39 @@ func (self *Receipt) SetLogs(logs state.Logs) { | ||||
| 	self.logs = logs | ||||
| } | ||||
|  | ||||
| func (self *Receipt) Logs() state.Logs { | ||||
| 	return self.logs | ||||
| } | ||||
|  | ||||
| func (self *Receipt) EncodeRLP(w io.Writer) error { | ||||
| 	return rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs}) | ||||
| } | ||||
|  | ||||
| func (self *Receipt) DecodeRLP(s *rlp.Stream) error { | ||||
| 	var r struct { | ||||
| 		PostState         []byte | ||||
| 		CumulativeGasUsed *big.Int | ||||
| 		Bloom             Bloom | ||||
| 		Logs              state.Logs | ||||
| 	} | ||||
| 	if err := s.Decode(&r); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs = r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type ReceiptForStorage Receipt | ||||
|  | ||||
| func (self *ReceiptForStorage) EncodeRLP(w io.Writer) error { | ||||
| 	storageLogs := make([]*state.LogForStorage, len(self.logs)) | ||||
| 	for i, log := range self.logs { | ||||
| 		storageLogs[i] = (*state.LogForStorage)(log) | ||||
| 	} | ||||
| 	return rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, storageLogs}) | ||||
| } | ||||
|  | ||||
| func (self *Receipt) RlpEncode() []byte { | ||||
| 	bytes, err := rlp.EncodeToBytes(self) | ||||
| 	if err != nil { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user