forked from cerc-io/ipld-eth-server
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:
@@ -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{
|
||||
|
||||
@@ -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))
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
Reference in New Issue
Block a user