// Tests that receipts can be stored and retrieved. func TestReceiptStorage(t *testing.T) { db, _ := ethdb.NewMemDatabase() receipt1 := &types.Receipt{ PostState: []byte{0x01}, CumulativeGasUsed: big.NewInt(1), Logs: vm.Logs{ &vm.Log{Address: common.BytesToAddress([]byte{0x11})}, &vm.Log{Address: common.BytesToAddress([]byte{0x01, 0x11})}, }, TxHash: common.BytesToHash([]byte{0x11, 0x11}), ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), GasUsed: big.NewInt(111111), } receipt2 := &types.Receipt{ PostState: []byte{0x02}, CumulativeGasUsed: big.NewInt(2), Logs: vm.Logs{ &vm.Log{Address: common.BytesToAddress([]byte{0x22})}, &vm.Log{Address: common.BytesToAddress([]byte{0x02, 0x22})}, }, TxHash: common.BytesToHash([]byte{0x22, 0x22}), ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), GasUsed: big.NewInt(222222), } receipts := []*types.Receipt{receipt1, receipt2} // Check that no receipt entries are in a pristine database for i, receipt := range receipts { if r := GetReceipt(db, receipt.TxHash); r != nil { t.Fatalf("receipt #%d [%x]: non existent receipt returned: %v", i, receipt.TxHash, r) } } // Insert all the receipts into the database, and verify contents if err := WriteReceipts(db, receipts); err != nil { t.Fatalf("failed to write receipts: %v", err) } for i, receipt := range receipts { if r := GetReceipt(db, receipt.TxHash); r == nil { t.Fatalf("receipt #%d [%x]: receipt not found", i, receipt.TxHash) } else { rlpHave, _ := rlp.EncodeToBytes(r) rlpWant, _ := rlp.EncodeToBytes(receipt) if bytes.Compare(rlpHave, rlpWant) != 0 { t.Fatalf("receipt #%d [%x]: receipt mismatch: have %v, want %v", i, receipt.TxHash, r, receipt) } } } // Delete the receipts and check purge for i, receipt := range receipts { DeleteReceipt(db, receipt.TxHash) if r := GetReceipt(db, receipt.TxHash); r != nil { t.Fatalf("receipt #%d [%x]: deleted receipt returned: %v", i, receipt.TxHash, r) } } }
// Tests that receipts associated with a single block can be stored and retrieved. func TestBlockReceiptStorage(t *testing.T) { db, _ := ethdb.NewMemDatabase() receipt1 := &types.Receipt{ PostState: []byte{0x01}, CumulativeGasUsed: big.NewInt(1), Logs: vm.Logs{ &vm.Log{Address: common.BytesToAddress([]byte{0x11})}, &vm.Log{Address: common.BytesToAddress([]byte{0x01, 0x11})}, }, TxHash: common.BytesToHash([]byte{0x11, 0x11}), ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), GasUsed: big.NewInt(111111), } receipt2 := &types.Receipt{ PostState: []byte{0x02}, CumulativeGasUsed: big.NewInt(2), Logs: vm.Logs{ &vm.Log{Address: common.BytesToAddress([]byte{0x22})}, &vm.Log{Address: common.BytesToAddress([]byte{0x02, 0x22})}, }, TxHash: common.BytesToHash([]byte{0x22, 0x22}), ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), GasUsed: big.NewInt(222222), } receipts := []*types.Receipt{receipt1, receipt2} // Check that no receipt entries are in a pristine database hash := common.BytesToHash([]byte{0x03, 0x14}) if rs := GetBlockReceipts(db, hash); len(rs) != 0 { t.Fatalf("non existent receipts returned: %v", rs) } // Insert the receipt slice into the database and check presence if err := WriteBlockReceipts(db, hash, receipts); err != nil { t.Fatalf("failed to write block receipts: %v", err) } if rs := GetBlockReceipts(db, hash); len(rs) == 0 { t.Fatalf("no receipts returned") } else { for i := 0; i < len(receipts); i++ { rlpHave, _ := rlp.EncodeToBytes(rs[i]) rlpWant, _ := rlp.EncodeToBytes(receipts[i]) if bytes.Compare(rlpHave, rlpWant) != 0 { t.Fatalf("receipt #%d: receipt mismatch: have %v, want %v", i, rs[i], receipts[i]) } } } // Delete the receipt slice and check purge DeleteBlockReceipts(db, hash) if rs := GetBlockReceipts(db, hash); len(rs) != 0 { t.Fatalf("deleted receipts returned: %v", rs) } }
// ExpectMsg reads a message from r and verifies that its // code and encoded RLP content match the provided values. // If content is nil, the payload is discarded and not verified. func ExpectMsg(r MsgReader, code uint64, content interface{}) error { msg, err := r.ReadMsg() if err != nil { return err } if msg.Code != code { return fmt.Errorf("message code mismatch: got %d, expected %d", msg.Code, code) } if content == nil { return msg.Discard() } else { contentEnc, err := rlp.EncodeToBytes(content) if err != nil { panic("content encode error: " + err.Error()) } if int(msg.Size) != len(contentEnc) { return fmt.Errorf("message size mismatch: got %d, want %d", msg.Size, len(contentEnc)) } actualContent, err := ioutil.ReadAll(msg.Payload) if err != nil { return err } if !bytes.Equal(actualContent, contentEnc) { return fmt.Errorf("message payload mismatch:\ngot: %x\nwant: %x", actualContent, contentEnc) } } return nil }
func TestEncodeZero(t *testing.T) { b, _ := rlp.EncodeToBytes(NewValue(0)) exp := []byte{0xc0} if bytes.Compare(b, exp) == 0 { t.Error("Expected", exp, "got", b) } }
// updateNode inserts - potentially overwriting - a node into the peer database. func (db *nodeDB) updateNode(node *Node) error { blob, err := rlp.EncodeToBytes(node) if err != nil { return err } return db.lvl.Put(makeKey(node.ID, nodeDBDiscoverRoot), blob, nil) }
func (self *Receipt) RlpEncode() []byte { bytes, err := rlp.EncodeToBytes(self) if err != nil { fmt.Println("TMP -- RECEIPT ENCODE ERROR", err) } return bytes }
// PutReceipts stores the receipts in the current database func PutReceipts(db common.Database, receipts types.Receipts) error { batch := new(leveldb.Batch) _, batchWrite := db.(*ethdb.LDBDatabase) for _, receipt := range receipts { storageReceipt := (*types.ReceiptForStorage)(receipt) bytes, err := rlp.EncodeToBytes(storageReceipt) if err != nil { return err } if batchWrite { batch.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) } else { err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) if err != nil { return err } } } if db, ok := db.(*ethdb.LDBDatabase); ok { if err := db.LDB().Write(batch, nil); err != nil { return err } } return nil }
// Hash returns the SHA3 hash of the envelope, calculating it if not yet done. func (self *Envelope) Hash() common.Hash { if (self.hash == common.Hash{}) { enc, _ := rlp.EncodeToBytes(self) self.hash = crypto.Sha3Hash(enc) } return self.hash }
func (self *ethApi) SignTransaction(req *shared.Request) (interface{}, error) { args := new(NewTxArgs) if err := self.codec.Decode(req.Params, &args); err != nil { return nil, shared.NewDecodeParamError(err.Error()) } // nonce may be nil ("guess" mode) var nonce string if args.Nonce != nil { nonce = args.Nonce.String() } var gas, price string if args.Gas != nil { gas = args.Gas.String() } if args.GasPrice != nil { price = args.GasPrice.String() } tx, err := self.xeth.SignTransaction(args.From, args.To, nonce, args.Value.String(), gas, price, args.Data) if err != nil { return nil, err } data, err := rlp.EncodeToBytes(tx) if err != nil { return nil, err } return JsonTransaction{"0x" + common.Bytes2Hex(data), newTx(tx)}, nil }
// RlpEncode implements common.RlpEncode required for SHA3 derivation. func (r *Receipt) RlpEncode() []byte { bytes, err := rlp.EncodeToBytes(r) if err != nil { panic(err) } return bytes }
func sendBadBlockReport(block *types.Block, err error) { if !EnableBadBlockReporting { return } var ( blockRLP, _ = rlp.EncodeToBytes(block) params = map[string]interface{}{ "block": common.Bytes2Hex(blockRLP), "blockHash": block.Hash().Hex(), "errortype": err.Error(), "client": "go", } ) if !block.ReceivedAt.IsZero() { params["receivedAt"] = block.ReceivedAt.UTC().String() } if p, ok := block.ReceivedFrom.(*peer); ok { params["receivedFrom"] = map[string]interface{}{ "enode": fmt.Sprintf("enode://%x@%v", p.ID(), p.RemoteAddr()), "name": p.Name(), "protocolVersion": p.version, } } jsonStr, _ := json.Marshal(map[string]interface{}{"method": "eth_badBlock", "id": "1", "jsonrpc": "2.0", "params": []interface{}{params}}) client := http.Client{Timeout: 8 * time.Second} resp, err := client.Post(badBlocksURL, "application/json", bytes.NewReader(jsonStr)) if err != nil { glog.V(logger.Debug).Infoln(err) return } glog.V(logger.Debug).Infof("Bad Block Report posted (%d)", resp.StatusCode) resp.Body.Close() }
func TestEncodeDecodeBytes(t *testing.T) { bv := NewValue([]interface{}{[]byte{1, 2, 3, 4, 5}, []byte{6}}) b, _ := rlp.EncodeToBytes(bv) val := NewValueFromBytes(b) if !bv.Cmp(val) { t.Errorf("Expected %#v, got %#v", bv, val) } }
// updateStateObject writes the given object to the trie. func (self *StateDB) updateStateObject(stateObject *StateObject) { addr := stateObject.Address() data, err := rlp.EncodeToBytes(stateObject) if err != nil { panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err)) } self.trie.Update(addr[:], data) }
func (c *StateObject) setAddr(addr []byte, value common.Hash) { v, err := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) if err != nil { // if RLPing failed we better panic and not fail silently. This would be considered a consensus issue panic(err) } c.trie.Update(addr, v) }
// PutTransactions stores the transactions in the given database func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) { batch := new(leveldb.Batch) _, batchWrite := db.(*ethdb.LDBDatabase) for i, tx := range block.Transactions() { rlpEnc, err := rlp.EncodeToBytes(tx) if err != nil { glog.V(logger.Debug).Infoln("Failed encoding tx", err) return } if batchWrite { batch.Put(tx.Hash().Bytes(), rlpEnc) } else { db.Put(tx.Hash().Bytes(), rlpEnc) } var txExtra struct { BlockHash common.Hash BlockIndex uint64 Index uint64 } txExtra.BlockHash = block.Hash() txExtra.BlockIndex = block.NumberU64() txExtra.Index = uint64(i) rlpMeta, err := rlp.EncodeToBytes(txExtra) if err != nil { glog.V(logger.Debug).Infoln("Failed encoding tx meta data", err) return } if batchWrite { batch.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) } else { db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) } } if db, ok := db.(*ethdb.LDBDatabase); ok { if err := db.LDB().Write(batch, nil); err != nil { glog.V(logger.Error).Infoln("db write err:", err) } } }
func TestRLPXFrameRW(t *testing.T) { var ( aesSecret = make([]byte, 16) macSecret = make([]byte, 16) egressMACinit = make([]byte, 32) ingressMACinit = make([]byte, 32) ) for _, s := range [][]byte{aesSecret, macSecret, egressMACinit, ingressMACinit} { rand.Read(s) } conn := new(bytes.Buffer) s1 := secrets{ AES: aesSecret, MAC: macSecret, EgressMAC: sha3.NewKeccak256(), IngressMAC: sha3.NewKeccak256(), } s1.EgressMAC.Write(egressMACinit) s1.IngressMAC.Write(ingressMACinit) rw1 := newRLPXFrameRW(conn, s1) s2 := secrets{ AES: aesSecret, MAC: macSecret, EgressMAC: sha3.NewKeccak256(), IngressMAC: sha3.NewKeccak256(), } s2.EgressMAC.Write(ingressMACinit) s2.IngressMAC.Write(egressMACinit) rw2 := newRLPXFrameRW(conn, s2) // send some messages for i := 0; i < 10; i++ { // write message into conn buffer wmsg := []interface{}{"foo", "bar", strings.Repeat("test", i)} err := Send(rw1, uint64(i), wmsg) if err != nil { t.Fatalf("WriteMsg error (i=%d): %v", i, err) } // read message that rw1 just wrote msg, err := rw2.ReadMsg() if err != nil { t.Fatalf("ReadMsg error (i=%d): %v", i, err) } if msg.Code != uint64(i) { t.Fatalf("msg code mismatch: got %d, want %d", msg.Code, i) } payload, _ := ioutil.ReadAll(msg.Payload) wantPayload, _ := rlp.EncodeToBytes(wmsg) if !bytes.Equal(payload, wantPayload) { t.Fatalf("msg payload mismatch:\ngot %x\nwant %x", payload, wantPayload) } } }
func DeriveSha(list DerivableList) common.Hash { db, _ := ethdb.NewMemDatabase() trie := trie.New(nil, db) for i := 0; i < list.Len(); i++ { key, _ := rlp.EncodeToBytes(uint(i)) trie.Update(key, list.GetRlp(i)) } return common.BytesToHash(trie.Root()) }
func TestTransactionEncode(t *testing.T) { txb, err := rlp.EncodeToBytes(rightvrsTx) if err != nil { t.Fatalf("encode error: %v", err) } should := common.FromHex("f86103018207d094b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a8255441ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3") if !bytes.Equal(txb, should) { t.Errorf("encoded RLP mismatch, got %x", txb) } }
// updateTrie writes cached storage modifications into the object's storage trie. func (self *StateObject) updateTrie(db trie.Database) { tr := self.getTrie(db) for key, value := range self.dirtyStorage { delete(self.dirtyStorage, key) if (value == common.Hash{}) { tr.Delete(key[:]) continue } // Encoding []byte cannot fail, ok to ignore the error. v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) tr.Update(key[:], v) } }
// WriteHeader serializes a block header into the database. func WriteHeader(db ethdb.Database, header *types.Header) error { data, err := rlp.EncodeToBytes(header) if err != nil { return err } key := append(append(blockPrefix, header.Hash().Bytes()...), headerSuffix...) if err := db.Put(key, data); err != nil { glog.Fatalf("failed to store header into database: %v", err) return err } glog.V(logger.Debug).Infof("stored header #%v [%x…]", header.Number, header.Hash().Bytes()[:4]) return nil }
// WriteBody serializes the body of a block into the database. func WriteBody(db ethdb.Database, hash common.Hash, body *types.Body) error { data, err := rlp.EncodeToBytes(body) if err != nil { return err } key := append(append(blockPrefix, hash.Bytes()...), bodySuffix...) if err := db.Put(key, data); err != nil { glog.Fatalf("failed to store block body into database: %v", err) return err } glog.V(logger.Debug).Infof("stored block body [%x…]", hash.Bytes()[:4]) return nil }
// WriteTd serializes the total difficulty of a block into the database. func WriteTd(db ethdb.Database, hash common.Hash, td *big.Int) error { data, err := rlp.EncodeToBytes(td) if err != nil { return err } key := append(append(blockPrefix, hash.Bytes()...), tdSuffix...) if err := db.Put(key, data); err != nil { glog.Fatalf("failed to store block total difficulty into database: %v", err) return err } glog.V(logger.Debug).Infof("stored block total difficulty [%x…]: %v", hash.Bytes()[:4], td) return nil }
func (self *debugApi) GetBlockRlp(req *shared.Request) (interface{}, error) { args := new(BlockNumArg) if err := self.codec.Decode(req.Params, &args); err != nil { return nil, shared.NewDecodeParamError(err.Error()) } block := self.xeth.EthBlockByNumber(args.BlockNumber) if block == nil { return nil, fmt.Errorf("block #%d not found", args.BlockNumber) } encoded, err := rlp.EncodeToBytes(block) return fmt.Sprintf("%x", encoded), err }
// WriteTransactions stores the transactions associated with a specific block // into the given database. Beside writing the transaction, the function also // stores a metadata entry along with the transaction, detailing the position // of this within the blockchain. func WriteTransactions(db ethdb.Database, block *types.Block) error { batch := db.NewBatch() // Iterate over each transaction and encode it with its metadata for i, tx := range block.Transactions() { // Encode and queue up the transaction for storage data, err := rlp.EncodeToBytes(tx) if err != nil { return err } if err := batch.Put(tx.Hash().Bytes(), data); err != nil { return err } // Encode and queue up the transaction metadata for storage meta := struct { BlockHash common.Hash BlockIndex uint64 Index uint64 }{ BlockHash: block.Hash(), BlockIndex: block.NumberU64(), Index: uint64(i), } data, err = rlp.EncodeToBytes(meta) if err != nil { return err } if err := batch.Put(append(tx.Hash().Bytes(), txMetaSuffix...), data); err != nil { return err } } // Write the scheduled data into the database if err := batch.Write(); err != nil { glog.Fatalf("failed to store transactions into database: %v", err) return err } return nil }
func TestRlpValueEncoding(t *testing.T) { val := EmptyValue() val.AppendList().Append(byte(1)).Append(byte(2)).Append(byte(3)) val.Append("4").AppendList().Append(byte(5)) res, err := rlp.EncodeToBytes(val) if err != nil { t.Fatalf("encode error: %v", err) } exp := Encode([]interface{}{[]interface{}{1, 2, 3}, "4", []interface{}{5}}) if bytes.Compare(res, exp) != 0 { t.Errorf("expected %x, got %x", exp, res) } }
// Prove constructs a merkle proof for key. The result contains all // encoded nodes on the path to the value at key. The value itself is // also included in the last node and can be retrieved by verifying // the proof. // // If the trie does not contain a value for key, the returned proof // contains all nodes of the longest existing prefix of the key // (at least the root node), ending with the node that proves the // absence of the key. func (t *Trie) Prove(key []byte) []rlp.RawValue { // Collect all nodes on the path to key. key = compactHexDecode(key) nodes := []node{} tn := t.root for len(key) > 0 && tn != nil { switch n := tn.(type) { case shortNode: if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) { // The trie doesn't contain the key. tn = nil } else { tn = n.Val key = key[len(n.Key):] } nodes = append(nodes, n) case fullNode: tn = n.Children[key[0]] key = key[1:] nodes = append(nodes, n) case hashNode: var err error tn, err = t.resolveHash(n, nil, nil) if err != nil { if glog.V(logger.Error) { glog.Errorf("Unhandled trie error: %v", err) } return nil } default: panic(fmt.Sprintf("%T: invalid node: %v", tn, tn)) } } hasher := newHasher() proof := make([]rlp.RawValue, 0, len(nodes)) for i, n := range nodes { // Don't bother checking for errors here since hasher panics // if encoding doesn't work and we're not writing to any database. n, _, _ = hasher.hashChildren(n, nil) hn, _ := hasher.store(n, nil, false) if _, ok := hn.(hashNode); ok || i == 0 { // If the node's database encoding is a hash (or is the // root node), it becomes a proof element. enc, _ := rlp.EncodeToBytes(n) proof = append(proof, enc) } } return proof }
// SendTransaction implements ContractTransactor.SendTransaction, delegating the // raw transaction injection to the remote node. func (b *rpcBackend) SendTransaction(tx *types.Transaction) error { data, err := rlp.EncodeToBytes(tx) if err != nil { return err } res, err := b.request("exp_sendRawTransaction", []interface{}{common.ToHex(data)}) if err != nil { return err } var hex string if err := json.Unmarshal(res, &hex); err != nil { return err } return nil }
// WriteBlock writes a block to the database func WriteBlock(db common.Database, block *types.Block) error { tstart := time.Now() enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block)) key := append(blockHashPre, block.Hash().Bytes()...) err := db.Put(key, enc) if err != nil { glog.Fatal("db write fail:", err) return err } if glog.V(logger.Debug) { glog.Infof("wrote block #%v %s. Took %v\n", block.Number(), common.PP(block.Hash().Bytes()), time.Since(tstart)) } return nil }
// PutBlockReceipts stores the block's transactions associated receipts // and stores them by block hash in a single slice. This is required for // forks and chain reorgs func PutBlockReceipts(db common.Database, block *types.Block, receipts types.Receipts) error { rs := make([]*types.ReceiptForStorage, len(receipts)) for i, receipt := range receipts { rs[i] = (*types.ReceiptForStorage)(receipt) } bytes, err := rlp.EncodeToBytes(rs) if err != nil { return err } hash := block.Hash() err = db.Put(append(blockReceiptsPre, hash[:]...), bytes) if err != nil { return err } return nil }
// WriteBlockReceipts stores all the transaction receipts belonging to a block // as a single receipt slice. This is used during chain reorganisations for // rescheduling dropped transactions. func WriteBlockReceipts(db ethdb.Database, hash common.Hash, receipts types.Receipts) error { // Convert the receipts into their storage form and serialize them 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 } // Store the flattened receipt slice if err := db.Put(append(blockReceiptsPrefix, hash.Bytes()...), bytes); err != nil { glog.Fatalf("failed to store block receipts into database: %v", err) return err } glog.V(logger.Debug).Infof("stored block receipts [%x…]", hash.Bytes()[:4]) return nil }