Add receipts (#119)

* Conversion between Geth Receipt and core.Receipt

* Add receipt to DB

* Insert receipts with transactions

* Update Travis CI to use dep for dependencies
This commit is contained in:
Matt K
2018-01-03 11:23:43 -06:00
committed by GitHub
parent 13748a92e5
commit 4fabe3e917
17 changed files with 484 additions and 38 deletions
+27 -6
View File
@@ -3,6 +3,8 @@ package geth
import (
"strings"
"log"
"github.com/8thlight/vulcanizedb/pkg/core"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
@@ -16,12 +18,7 @@ type GethClient interface {
}
func GethBlockToCoreBlock(gethBlock *types.Block, client GethClient) core.Block {
transactions := []core.Transaction{}
for i, gethTransaction := range gethBlock.Transactions() {
from, _ := client.TransactionSender(context.Background(), gethTransaction, gethBlock.Hash(), uint(i))
transaction := gethTransToCoreTrans(gethTransaction, &from)
transactions = append(transactions, transaction)
}
transactions := convertGethTransactionsToCore(gethBlock, client)
blockReward := CalcBlockReward(gethBlock, client)
uncleReward := CalcUnclesReward(gethBlock)
return core.Block{
@@ -43,6 +40,30 @@ func GethBlockToCoreBlock(gethBlock *types.Block, client GethClient) core.Block
}
}
func convertGethTransactionsToCore(gethBlock *types.Block, client GethClient) []core.Transaction {
transactions := make([]core.Transaction, 0)
for i, gethTransaction := range gethBlock.Transactions() {
from, err := client.TransactionSender(context.Background(), gethTransaction, gethBlock.Hash(), uint(i))
if err != nil {
log.Println(err)
}
transaction := gethTransToCoreTrans(gethTransaction, &from)
transaction, err = appendReceiptToTransaction(client, transaction)
if err != nil {
log.Println(err)
}
transactions = append(transactions, transaction)
}
return transactions
}
func appendReceiptToTransaction(client GethClient, transaction core.Transaction) (core.Transaction, error) {
gethReceipt, err := client.TransactionReceipt(context.Background(), common.HexToHash(transaction.Hash))
receipt := GethReceiptToCoreReceipt(gethReceipt)
transaction.Receipt = receipt
return transaction, err
}
func gethTransToCoreTrans(transaction *types.Transaction, from *common.Address) core.Transaction {
data := hexutil.Encode(transaction.Data())
return core.Transaction{
+58 -14
View File
@@ -197,42 +197,86 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
})
It("converts a single transaction", func() {
nonce := uint64(10000)
header := types.Header{}
to := common.Address{1}
amount := big.NewInt(10)
gasLimit := big.NewInt(5000)
gasPrice := big.NewInt(3)
input := "0xf7d8c8830000000000000000000000000000000000000000000000000000000000037788000000000000000000000000000000000000000000000000000000000003bd14"
payload, _ := hexutil.Decode(input)
gethTransaction := types.NewTransaction(
uint64(10000), common.Address{1},
big.NewInt(10),
big.NewInt(5000),
big.NewInt(3),
hexutil.MustDecode("0xf7d8c8830000000000000000000000000000000000000000000000000000000000037788000000000000000000000000000000000000000000000000000000000003bd14"),
)
gethTransaction := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, payload)
gethReceipt := &types.Receipt{
Bloom: types.BytesToBloom(hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")),
ContractAddress: common.HexToAddress("x123"),
CumulativeGasUsed: big.NewInt(7996119),
GasUsed: big.NewInt(21000),
Logs: []*types.Log{},
Status: uint(1),
TxHash: gethTransaction.Hash(),
}
client := NewFakeClient()
client.AddReceipts([]*types.Receipt{gethReceipt})
gethBlock := types.NewBlock(&header, []*types.Transaction{gethTransaction}, []*types.Header{}, []*types.Receipt{})
header := types.Header{}
gethBlock := types.NewBlock(
&header,
[]*types.Transaction{gethTransaction},
[]*types.Header{},
[]*types.Receipt{gethReceipt},
)
coreBlock := geth.GethBlockToCoreBlock(gethBlock, client)
Expect(len(coreBlock.Transactions)).To(Equal(1))
coreTransaction := coreBlock.Transactions[0]
Expect(coreTransaction.Data).To(Equal(input))
Expect(coreTransaction.Data).To(Equal("0xf7d8c8830000000000000000000000000000000000000000000000000000000000037788000000000000000000000000000000000000000000000000000000000003bd14"))
Expect(coreTransaction.To).To(Equal(gethTransaction.To().Hex()))
Expect(coreTransaction.From).To(Equal("0x0000000000000000000000000000000000000123"))
Expect(coreTransaction.GasLimit).To(Equal(gethTransaction.Gas().Int64()))
Expect(coreTransaction.GasPrice).To(Equal(gethTransaction.GasPrice().Int64()))
Expect(coreTransaction.Value).To(Equal(gethTransaction.Value().Int64()))
Expect(coreTransaction.Nonce).To(Equal(gethTransaction.Nonce()))
coreReceipt := coreTransaction.Receipt
expectedReceipt := geth.GethReceiptToCoreReceipt(gethReceipt)
Expect(coreReceipt).To(Equal(expectedReceipt))
})
It("has an empty to field when transaction creates a new contract", func() {
gethTransaction := types.NewContractCreation(uint64(10000), big.NewInt(10), big.NewInt(5000), big.NewInt(3), []byte("1234"))
gethBlock := types.NewBlock(&types.Header{}, []*types.Transaction{gethTransaction}, []*types.Header{}, []*types.Receipt{})
It("has an empty 'To' field when transaction creates a new contract", func() {
gethTransaction := types.NewContractCreation(
uint64(10000),
big.NewInt(10),
big.NewInt(5000),
big.NewInt(3),
[]byte("1234"),
)
gethReceipt := &types.Receipt{
CumulativeGasUsed: big.NewInt(1),
GasUsed: big.NewInt(1),
TxHash: gethTransaction.Hash(),
ContractAddress: common.HexToAddress("0x1023342345"),
}
client := NewFakeClient()
client.AddReceipts([]*types.Receipt{gethReceipt})
gethBlock := types.NewBlock(
&types.Header{},
[]*types.Transaction{gethTransaction},
[]*types.Header{},
[]*types.Receipt{gethReceipt},
)
coreBlock := geth.GethBlockToCoreBlock(gethBlock, client)
coreTransaction := coreBlock.Transactions[0]
Expect(coreTransaction.To).To(Equal(""))
coreReceipt := coreTransaction.Receipt
expectedReceipt := geth.GethReceiptToCoreReceipt(gethReceipt)
Expect(coreReceipt).To(Equal(expectedReceipt))
})
})
+62
View File
@@ -0,0 +1,62 @@
package geth
import (
"math/big"
"bytes"
"github.com/8thlight/vulcanizedb/pkg/core"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
)
func BigTo64(n *big.Int) int64 {
if n != nil {
return n.Int64()
}
return 0
}
func GethReceiptToCoreReceipt(gethReceipt *types.Receipt) core.Receipt {
bloom := hexutil.Encode(gethReceipt.Bloom.Bytes())
var postState string
var status int
postState, status = postStateOrStatus(gethReceipt)
logs := dereferenceLogs(gethReceipt)
contractAddress := setContractAddress(gethReceipt)
return core.Receipt{
Bloom: bloom,
ContractAddress: contractAddress,
CumulativeGasUsed: gethReceipt.CumulativeGasUsed.Int64(),
GasUsed: gethReceipt.GasUsed.Int64(),
Logs: logs,
StateRoot: postState,
TxHash: gethReceipt.TxHash.Hex(),
Status: status,
}
}
func setContractAddress(gethReceipt *types.Receipt) string {
emptyAddress := common.Address{}.Bytes()
if bytes.Equal(gethReceipt.ContractAddress.Bytes(), emptyAddress) {
return ""
}
return gethReceipt.ContractAddress.Hex()
}
func dereferenceLogs(gethReceipt *types.Receipt) []core.Log {
logs := []core.Log{}
for _, log := range gethReceipt.Logs {
logs = append(logs, GethLogToCoreLog(*log))
}
return logs
}
func postStateOrStatus(gethReceipts *types.Receipt) (string, int) {
if len(gethReceipts.PostState) != 0 {
return hexutil.Encode(gethReceipts.PostState), -99
}
return "", int(gethReceipts.Status)
}
@@ -0,0 +1,85 @@
package geth_test
import (
"math/big"
"github.com/8thlight/vulcanizedb/pkg/core"
"github.com/8thlight/vulcanizedb/pkg/geth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Conversion of GethReceipt to core.Receipt", func() {
It(`converts geth receipt to internal receipt format (pre Byzantium has post-transaction stateroot)`, func() {
receipt := types.Receipt{
Bloom: types.BytesToBloom(hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")),
ContractAddress: common.Address{},
CumulativeGasUsed: big.NewInt(21000),
GasUsed: big.NewInt(21000),
Logs: []*types.Log{},
PostState: hexutil.MustDecode("0x88abf7e73128227370aa7baa3dd4e18d0af70e92ef1f9ef426942fbe2dddb733"),
TxHash: common.HexToHash("0x97d99bc7729211111a21b12c933c949d4f31684f1d6954ff477d0477538ff017"),
}
expected := core.Receipt{
Bloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
ContractAddress: "",
CumulativeGasUsed: 21000,
GasUsed: 21000,
Logs: []core.Log{},
StateRoot: "0x88abf7e73128227370aa7baa3dd4e18d0af70e92ef1f9ef426942fbe2dddb733",
Status: -99,
TxHash: receipt.TxHash.Hex(),
}
coreReceipt := geth.GethReceiptToCoreReceipt(&receipt)
Expect(coreReceipt.Bloom).To(Equal(expected.Bloom))
Expect(coreReceipt.ContractAddress).To(Equal(expected.ContractAddress))
Expect(coreReceipt.CumulativeGasUsed).To(Equal(expected.CumulativeGasUsed))
Expect(coreReceipt.GasUsed).To(Equal(expected.GasUsed))
Expect(coreReceipt.Logs).To(Equal(expected.Logs))
Expect(coreReceipt.StateRoot).To(Equal(expected.StateRoot))
Expect(coreReceipt.Status).To(Equal(expected.Status))
Expect(coreReceipt.TxHash).To(Equal(expected.TxHash))
})
It("converts geth receipt to internal receipt format (post Byzantium has status", func() {
receipt := types.Receipt{
Bloom: types.BytesToBloom(hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")),
ContractAddress: common.HexToAddress("x0123"),
CumulativeGasUsed: big.NewInt(7996119),
GasUsed: big.NewInt(21000),
Logs: []*types.Log{},
Status: uint(1),
TxHash: common.HexToHash("0xe340558980f89d5f86045ac11e5cc34e4bcec20f9f1e2a427aa39d87114e8223"),
}
expected := core.Receipt{
Bloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
ContractAddress: receipt.ContractAddress.Hex(),
CumulativeGasUsed: 7996119,
GasUsed: 21000,
Logs: []core.Log{},
StateRoot: "",
Status: 1,
TxHash: receipt.TxHash.Hex(),
}
coreReceipt := geth.GethReceiptToCoreReceipt(&receipt)
Expect(coreReceipt.Bloom).To(Equal(expected.Bloom))
Expect(coreReceipt.ContractAddress).To(Equal(""))
Expect(coreReceipt.CumulativeGasUsed).To(Equal(expected.CumulativeGasUsed))
Expect(coreReceipt.GasUsed).To(Equal(expected.GasUsed))
Expect(coreReceipt.Logs).To(Equal(expected.Logs))
Expect(coreReceipt.StateRoot).To(Equal(expected.StateRoot))
Expect(coreReceipt.Status).To(Equal(expected.Status))
Expect(coreReceipt.TxHash).To(Equal(expected.TxHash))
})
})