Process tx receipts and ERC20 tokens WIP
This commit is contained in:
parent
1ac7a7abca
commit
ef03abcd1c
71
bchain/coins/eth/erc20.go
Normal file
71
bchain/coins/eth/erc20.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package eth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
ethcommon "github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/juju/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var erc20abi = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","signature":"0x06fdde03"},
|
||||||
|
{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","signature":"0x95d89b41"},
|
||||||
|
{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function","signature":"0x313ce567"},
|
||||||
|
{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function","signature":"0x18160ddd"},
|
||||||
|
{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function","signature":"0x70a08231"},
|
||||||
|
{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function","signature":"0xa9059cbb"},
|
||||||
|
{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function","signature":"0x23b872dd"},
|
||||||
|
{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function","signature":"0x095ea7b3"},
|
||||||
|
{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function","signature":"0xdd62ed3e"},
|
||||||
|
{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event","signature":"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"},
|
||||||
|
{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event","signature":"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"},
|
||||||
|
{"inputs":[{"name":"_initialAmount","type":"uint256"},{"name":"_tokenName","type":"string"},{"name":"_decimalUnits","type":"uint8"},{"name":"_tokenSymbol","type":"string"}],"payable":false,"type":"constructor"},
|
||||||
|
{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_extraData","type":"bytes"}],"name":"approveAndCall","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function","signature":"0xcae9ca51"},
|
||||||
|
{"constant":true,"inputs":[],"name":"version","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","signature":"0x54fd4d50"}]`
|
||||||
|
|
||||||
|
// doing the parsing/processing without using go-ethereum/accounts/abi library, it is simple to get data from Transfer event
|
||||||
|
const erc20EventTransferSignature = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
|
||||||
|
|
||||||
|
type erc20Transfer struct {
|
||||||
|
Contract ethcommon.Address
|
||||||
|
From ethcommon.Address
|
||||||
|
To ethcommon.Address
|
||||||
|
Tokens big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
func addressFromPaddedHex(s string) (*ethcommon.Address, error) {
|
||||||
|
var t big.Int
|
||||||
|
_, ok := t.SetString(s, 0)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("Data is not a number")
|
||||||
|
}
|
||||||
|
a := ethcommon.BigToAddress(&t)
|
||||||
|
return &a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func erc20GetTransfersFromLog(logs []*rpcLog) ([]erc20Transfer, error) {
|
||||||
|
var r []erc20Transfer
|
||||||
|
for _, l := range logs {
|
||||||
|
if len(l.Topics) == 3 && l.Topics[0] == erc20EventTransferSignature {
|
||||||
|
var t big.Int
|
||||||
|
_, ok := t.SetString(l.Data, 0)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("Data is not a number")
|
||||||
|
}
|
||||||
|
from, err := addressFromPaddedHex(l.Topics[1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
to, err := addressFromPaddedHex(l.Topics[2])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r = append(r, erc20Transfer{
|
||||||
|
Contract: l.Address,
|
||||||
|
From: *from,
|
||||||
|
To: *to,
|
||||||
|
Tokens: t,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
112
bchain/coins/eth/erc20_test.go
Normal file
112
bchain/coins/eth/erc20_test.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
// build unittest
|
||||||
|
|
||||||
|
package eth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
ethcommon "github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestErc20_erc20GetTransfersFromLog(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args []*rpcLog
|
||||||
|
want []erc20Transfer
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "1",
|
||||||
|
args: []*rpcLog{
|
||||||
|
&rpcLog{
|
||||||
|
Address: ethcommon.HexToAddress("0x76a45e8976499ab9ae223cc584019341d5a84e96"),
|
||||||
|
Topics: []string{
|
||||||
|
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
|
||||||
|
"0x0000000000000000000000002aacf811ac1a60081ea39f7783c0d26c500871a8",
|
||||||
|
"0x000000000000000000000000e9a5216ff992cfa01594d43501a56e12769eb9d2",
|
||||||
|
},
|
||||||
|
Data: "0x0000000000000000000000000000000000000000000000000000000000000123",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []erc20Transfer{
|
||||||
|
{
|
||||||
|
Contract: ethcommon.HexToAddress("0x76a45e8976499ab9ae223cc584019341d5a84e96"),
|
||||||
|
From: ethcommon.HexToAddress("0x2aacf811ac1a60081ea39f7783c0d26c500871a8"),
|
||||||
|
To: ethcommon.HexToAddress("0xe9a5216ff992cfa01594d43501a56e12769eb9d2"),
|
||||||
|
Tokens: *big.NewInt(0x123),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "2",
|
||||||
|
args: []*rpcLog{
|
||||||
|
&rpcLog{ // Transfer
|
||||||
|
Address: ethcommon.HexToAddress("0x0d0f936ee4c93e25944694d6c121de94d9760f11"),
|
||||||
|
Topics: []string{
|
||||||
|
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
|
||||||
|
"0x0000000000000000000000006f44cceb49b4a5812d54b6f494fc2febf25511ed",
|
||||||
|
"0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d",
|
||||||
|
},
|
||||||
|
Data: "0x0000000000000000000000000000000000000000000000006a8313d60b1f606b",
|
||||||
|
},
|
||||||
|
&rpcLog{ // Transfer
|
||||||
|
Address: ethcommon.HexToAddress("0xc778417e063141139fce010982780140aa0cd5ab"),
|
||||||
|
Topics: []string{
|
||||||
|
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
|
||||||
|
"0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d",
|
||||||
|
"0x0000000000000000000000006f44cceb49b4a5812d54b6f494fc2febf25511ed",
|
||||||
|
},
|
||||||
|
Data: "0x000000000000000000000000000000000000000000000000000308fd0e798ac0",
|
||||||
|
},
|
||||||
|
&rpcLog{ // not Transfer
|
||||||
|
Address: ethcommon.HexToAddress("0x479cc461fecd078f766ecc58533d6f69580cf3ac"),
|
||||||
|
Topics: []string{
|
||||||
|
"0x0d0b9391970d9a25552f37d436d2aae2925e2bfe1b2a923754bada030c498cb3",
|
||||||
|
"0x0000000000000000000000006f44cceb49b4a5812d54b6f494fc2febf25511ed",
|
||||||
|
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x5af266c0a89a07c1917deaa024414577e6c3c31c8907d079e13eb448c082594f",
|
||||||
|
},
|
||||||
|
Data: "0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d0000000000000",
|
||||||
|
},
|
||||||
|
&rpcLog{ // not Transfer
|
||||||
|
Address: ethcommon.HexToAddress("0x0d0f936ee4c93e25944694d6c121de94d9760f11"),
|
||||||
|
Topics: []string{
|
||||||
|
"0x0d0b9391970d9a25552f37d436d2aae2925e2bfe1b2a923754bada030c498cb3",
|
||||||
|
"0x0000000000000000000000007b62eb7fe80350dc7ec945c0b73242cb9877fb1b",
|
||||||
|
"0xb0b69dad58df6032c3b266e19b1045b19c87acd2c06fb0c598090f44b8e263aa",
|
||||||
|
},
|
||||||
|
Data: "0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d000000000000000000000000c778417e063141139fce010982780140aa0cd5ab0000000000000000000000000d0f936ee4c93e25944694d6c121de94d9760f1100000000000000000000000000000000000000000000000000031855667df7a80000000000000000000000000000000000000000000000006a8313d60b1f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []erc20Transfer{
|
||||||
|
{
|
||||||
|
Contract: ethcommon.HexToAddress("0x0d0f936ee4c93e25944694d6c121de94d9760f11"),
|
||||||
|
From: ethcommon.HexToAddress("0x6f44cceb49b4a5812d54b6f494fc2febf25511ed"),
|
||||||
|
To: ethcommon.HexToAddress("0x4bda106325c335df99eab7fe363cac8a0ba2a24d"),
|
||||||
|
Tokens: *big.NewInt(0x6a8313d60b1f606b),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Contract: ethcommon.HexToAddress("0xc778417e063141139fce010982780140aa0cd5ab"),
|
||||||
|
From: ethcommon.HexToAddress("0x4bda106325c335df99eab7fe363cac8a0ba2a24d"),
|
||||||
|
To: ethcommon.HexToAddress("0x6f44cceb49b4a5812d54b6f494fc2febf25511ed"),
|
||||||
|
Tokens: *big.NewInt(0x308fd0e798ac0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := erc20GetTransfersFromLog(tt.args)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("erc20GetTransfersFromLog error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("erc20GetTransfersFromLog = %+v, want %+v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
ethcommon "github.com/ethereum/go-ethereum/common"
|
ethcommon "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/golang/glog"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
)
|
)
|
||||||
@ -38,16 +39,33 @@ type rpcTransaction struct {
|
|||||||
BlockHash *ethcommon.Hash `json:"blockHash,omitempty"`
|
BlockHash *ethcommon.Hash `json:"blockHash,omitempty"`
|
||||||
From string `json:"from"`
|
From string `json:"from"`
|
||||||
TransactionIndex string `json:"transactionIndex"`
|
TransactionIndex string `json:"transactionIndex"`
|
||||||
// Signature values
|
// Signature values - ignored
|
||||||
V string `json:"v" gencodec:"required"`
|
// V string `json:"v" gencodec:"required"`
|
||||||
R string `json:"r" gencodec:"required"`
|
// R string `json:"r" gencodec:"required"`
|
||||||
S string `json:"s" gencodec:"required"`
|
// S string `json:"s" gencodec:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type rpcLog struct {
|
||||||
|
Address ethcommon.Address `json:"address" gencodec:"required"`
|
||||||
|
Topics []string `json:"topics" gencodec:"required"`
|
||||||
|
Data string `json:"data" gencodec:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type rpcReceipt struct {
|
||||||
|
GasUsed string `json:"gasUsed" gencodec:"required"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Logs []*rpcLog `json:"logs" gencodec:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type completeTransaction struct {
|
||||||
|
Tx *rpcTransaction `json:"tx"`
|
||||||
|
Receipt *rpcReceipt `json:"receipt,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type rpcBlock struct {
|
type rpcBlock struct {
|
||||||
Hash ethcommon.Hash `json:"hash"`
|
Hash ethcommon.Hash `json:"hash"`
|
||||||
|
Size string `json:"size"`
|
||||||
Transactions []rpcTransaction `json:"transactions"`
|
Transactions []rpcTransaction `json:"transactions"`
|
||||||
UncleHashes []ethcommon.Hash `json:"uncles"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ethHashToHash(h ethcommon.Hash) string {
|
func ethHashToHash(h ethcommon.Hash) string {
|
||||||
@ -61,7 +79,7 @@ func ethNumber(n string) (int64, error) {
|
|||||||
return 0, errors.Errorf("Not a number: '%v'", n)
|
return 0, errors.Errorf("Not a number: '%v'", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *EthereumParser) ethTxToTx(tx *rpcTransaction, blocktime int64, confirmations uint32) (*bchain.Tx, error) {
|
func (p *EthereumParser) ethTxToTx(tx *rpcTransaction, receipt *rpcReceipt, blocktime int64, confirmations uint32) (*bchain.Tx, error) {
|
||||||
txid := ethHashToHash(tx.Hash)
|
txid := ethHashToHash(tx.Hash)
|
||||||
var (
|
var (
|
||||||
fa, ta []string
|
fa, ta []string
|
||||||
@ -73,15 +91,21 @@ func (p *EthereumParser) ethTxToTx(tx *rpcTransaction, blocktime int64, confirma
|
|||||||
if len(tx.To) > 2 {
|
if len(tx.To) > 2 {
|
||||||
ta = []string{tx.To}
|
ta = []string{tx.To}
|
||||||
}
|
}
|
||||||
// temporarily, the complete rpcTransaction without BlockHash is marshalled and hex encoded to bchain.Tx.Hex
|
|
||||||
|
// completeTransaction without BlockHash is marshalled and hex encoded to bchain.Tx.Hex
|
||||||
bh := tx.BlockHash
|
bh := tx.BlockHash
|
||||||
tx.BlockHash = nil
|
tx.BlockHash = nil
|
||||||
b, err := json.Marshal(tx)
|
ct := completeTransaction{
|
||||||
|
Tx: tx,
|
||||||
|
Receipt: receipt,
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(ct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tx.BlockHash = bh
|
tx.BlockHash = bh
|
||||||
h := hex.EncodeToString(b)
|
h := hex.EncodeToString(b)
|
||||||
|
glog.Info(h)
|
||||||
vs, err := hexutil.DecodeBig(tx.Value)
|
vs, err := hexutil.DecodeBig(tx.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -181,79 +205,96 @@ func (p *EthereumParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var r rpcTransaction
|
var r completeTransaction
|
||||||
var n uint64
|
var n uint64
|
||||||
err = json.Unmarshal(b, &r)
|
err = json.Unmarshal(b, &r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pt := &ProtoTransaction{}
|
pt := &ProtoCompleteTransaction{}
|
||||||
if pt.AccountNonce, err = hexutil.DecodeUint64(r.AccountNonce); err != nil {
|
if pt.Tx.AccountNonce, err = hexutil.DecodeUint64(r.Tx.AccountNonce); err != nil {
|
||||||
return nil, errors.Annotatef(err, "AccountNonce %v", r.AccountNonce)
|
return nil, errors.Annotatef(err, "AccountNonce %v", r.Tx.AccountNonce)
|
||||||
}
|
}
|
||||||
if n, err = hexutil.DecodeUint64(r.BlockNumber); err != nil {
|
if n, err = hexutil.DecodeUint64(r.Tx.BlockNumber); err != nil {
|
||||||
return nil, errors.Annotatef(err, "BlockNumber %v", r.BlockNumber)
|
return nil, errors.Annotatef(err, "BlockNumber %v", r.Tx.BlockNumber)
|
||||||
}
|
}
|
||||||
pt.BlockNumber = uint32(n)
|
pt.BlockNumber = uint32(n)
|
||||||
pt.BlockTime = uint64(blockTime)
|
pt.BlockTime = uint64(blockTime)
|
||||||
if pt.From, err = hexDecode(r.From); err != nil {
|
if pt.Tx.From, err = hexDecode(r.Tx.From); err != nil {
|
||||||
return nil, errors.Annotatef(err, "From %v", r.From)
|
return nil, errors.Annotatef(err, "From %v", r.Tx.From)
|
||||||
}
|
}
|
||||||
if pt.GasLimit, err = hexutil.DecodeUint64(r.GasLimit); err != nil {
|
if pt.Tx.GasLimit, err = hexutil.DecodeUint64(r.Tx.GasLimit); err != nil {
|
||||||
return nil, errors.Annotatef(err, "GasLimit %v", r.GasLimit)
|
return nil, errors.Annotatef(err, "GasLimit %v", r.Tx.GasLimit)
|
||||||
}
|
}
|
||||||
pt.Hash = r.Hash.Bytes()
|
pt.Tx.Hash = r.Tx.Hash.Bytes()
|
||||||
if pt.Payload, err = hexDecode(r.Payload); err != nil {
|
if pt.Tx.Payload, err = hexDecode(r.Tx.Payload); err != nil {
|
||||||
return nil, errors.Annotatef(err, "Payload %v", r.Payload)
|
return nil, errors.Annotatef(err, "Payload %v", r.Tx.Payload)
|
||||||
}
|
}
|
||||||
if pt.Price, err = hexDecodeBig(r.Price); err != nil {
|
if pt.Tx.Price, err = hexDecodeBig(r.Tx.Price); err != nil {
|
||||||
return nil, errors.Annotatef(err, "Price %v", r.Price)
|
return nil, errors.Annotatef(err, "Price %v", r.Tx.Price)
|
||||||
}
|
}
|
||||||
if pt.R, err = hexDecodeBig(r.R); err != nil {
|
// if pt.R, err = hexDecodeBig(r.R); err != nil {
|
||||||
return nil, errors.Annotatef(err, "R %v", r.R)
|
// return nil, errors.Annotatef(err, "R %v", r.R)
|
||||||
|
// }
|
||||||
|
// if pt.S, err = hexDecodeBig(r.S); err != nil {
|
||||||
|
// return nil, errors.Annotatef(err, "S %v", r.S)
|
||||||
|
// }
|
||||||
|
// if pt.V, err = hexDecodeBig(r.V); err != nil {
|
||||||
|
// return nil, errors.Annotatef(err, "V %v", r.V)
|
||||||
|
// }
|
||||||
|
if pt.Tx.To, err = hexDecode(r.Tx.To); err != nil {
|
||||||
|
return nil, errors.Annotatef(err, "To %v", r.Tx.To)
|
||||||
}
|
}
|
||||||
if pt.S, err = hexDecodeBig(r.S); err != nil {
|
if n, err = hexutil.DecodeUint64(r.Tx.TransactionIndex); err != nil {
|
||||||
return nil, errors.Annotatef(err, "S %v", r.S)
|
return nil, errors.Annotatef(err, "TransactionIndex %v", r.Tx.TransactionIndex)
|
||||||
}
|
}
|
||||||
if pt.V, err = hexDecodeBig(r.V); err != nil {
|
pt.Tx.TransactionIndex = uint32(n)
|
||||||
return nil, errors.Annotatef(err, "V %v", r.V)
|
if pt.Tx.Value, err = hexDecodeBig(r.Tx.Value); err != nil {
|
||||||
}
|
return nil, errors.Annotatef(err, "Value %v", r.Tx.Value)
|
||||||
if pt.To, err = hexDecode(r.To); err != nil {
|
|
||||||
return nil, errors.Annotatef(err, "To %v", r.To)
|
|
||||||
}
|
|
||||||
if n, err = hexutil.DecodeUint64(r.TransactionIndex); err != nil {
|
|
||||||
return nil, errors.Annotatef(err, "TransactionIndex %v", r.TransactionIndex)
|
|
||||||
}
|
|
||||||
pt.TransactionIndex = uint32(n)
|
|
||||||
if pt.Value, err = hexDecodeBig(r.Value); err != nil {
|
|
||||||
return nil, errors.Annotatef(err, "Value %v", r.Value)
|
|
||||||
}
|
}
|
||||||
return proto.Marshal(pt)
|
return proto.Marshal(pt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnpackTx unpacks transaction from byte array
|
// UnpackTx unpacks transaction from byte array
|
||||||
func (p *EthereumParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
func (p *EthereumParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
||||||
var pt ProtoTransaction
|
var pt ProtoCompleteTransaction
|
||||||
err := proto.Unmarshal(buf, &pt)
|
err := proto.Unmarshal(buf, &pt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
r := rpcTransaction{
|
rt := rpcTransaction{
|
||||||
AccountNonce: hexutil.EncodeUint64(pt.AccountNonce),
|
AccountNonce: hexutil.EncodeUint64(pt.Tx.AccountNonce),
|
||||||
BlockNumber: hexutil.EncodeUint64(uint64(pt.BlockNumber)),
|
BlockNumber: hexutil.EncodeUint64(uint64(pt.BlockNumber)),
|
||||||
From: hexutil.Encode(pt.From),
|
From: hexutil.Encode(pt.Tx.From),
|
||||||
GasLimit: hexutil.EncodeUint64(pt.GasLimit),
|
GasLimit: hexutil.EncodeUint64(pt.Tx.GasLimit),
|
||||||
Hash: ethcommon.BytesToHash(pt.Hash),
|
Hash: ethcommon.BytesToHash(pt.Tx.Hash),
|
||||||
Payload: hexutil.Encode(pt.Payload),
|
Payload: hexutil.Encode(pt.Tx.Payload),
|
||||||
Price: hexEncodeBig(pt.Price),
|
Price: hexEncodeBig(pt.Tx.Price),
|
||||||
R: hexEncodeBig(pt.R),
|
// R: hexEncodeBig(pt.R),
|
||||||
S: hexEncodeBig(pt.S),
|
// S: hexEncodeBig(pt.S),
|
||||||
V: hexEncodeBig(pt.V),
|
// V: hexEncodeBig(pt.V),
|
||||||
To: hexutil.Encode(pt.To),
|
To: hexutil.Encode(pt.Tx.To),
|
||||||
TransactionIndex: hexutil.EncodeUint64(uint64(pt.TransactionIndex)),
|
TransactionIndex: hexutil.EncodeUint64(uint64(pt.Tx.TransactionIndex)),
|
||||||
Value: hexEncodeBig(pt.Value),
|
Value: hexEncodeBig(pt.Tx.Value),
|
||||||
}
|
}
|
||||||
tx, err := p.ethTxToTx(&r, int64(pt.BlockTime), 0)
|
logs := make([]*rpcLog, len(pt.Receipt.Log))
|
||||||
|
for i, l := range pt.Receipt.Log {
|
||||||
|
topics := make([]string, len(l.Topics))
|
||||||
|
for j, t := range l.Topics {
|
||||||
|
topics[j] = hexutil.Encode(t)
|
||||||
|
}
|
||||||
|
logs[i] = &rpcLog{
|
||||||
|
Address: ethcommon.BytesToAddress(l.Address),
|
||||||
|
Data: hexutil.Encode(l.Data),
|
||||||
|
Topics: topics,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rr := rpcReceipt{
|
||||||
|
GasUsed: hexEncodeBig(pt.Receipt.GasUsed),
|
||||||
|
Status: hexEncodeBig(pt.Receipt.Status),
|
||||||
|
Logs: logs,
|
||||||
|
}
|
||||||
|
tx, err := p.ethTxToTx(&rt, &rr, int64(pt.BlockTime), 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
@ -303,14 +344,14 @@ func GetHeightFromTx(tx *bchain.Tx) (uint32, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
var r rpcTransaction
|
var ct completeTransaction
|
||||||
var n uint64
|
var n uint64
|
||||||
err = json.Unmarshal(b, &r)
|
err = json.Unmarshal(b, &ct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if n, err = hexutil.DecodeUint64(r.BlockNumber); err != nil {
|
if n, err = hexutil.DecodeUint64(ct.Tx.BlockNumber); err != nil {
|
||||||
return 0, errors.Annotatef(err, "BlockNumber %v", r.BlockNumber)
|
return 0, errors.Annotatef(err, "BlockNumber %v", ct.Tx.BlockNumber)
|
||||||
}
|
}
|
||||||
return uint32(n), nil
|
return uint32(n), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// +build unittest
|
// build unittest
|
||||||
|
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
ethereum "github.com/ethereum/go-ethereum"
|
ethereum "github.com/ethereum/go-ethereum"
|
||||||
ethcommon "github.com/ethereum/go-ethereum/common"
|
ethcommon "github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
@ -423,12 +424,6 @@ func (b *EthereumRPC) GetBlock(hash string, height uint32) (*bchain.Block, error
|
|||||||
return nil, errors.Annotatef(err, "hash %v, height %v", hash, height)
|
return nil, errors.Annotatef(err, "hash %v, height %v", hash, height)
|
||||||
}
|
}
|
||||||
// Quick-verify transaction and uncle lists. This mostly helps with debugging the server.
|
// Quick-verify transaction and uncle lists. This mostly helps with debugging the server.
|
||||||
if head.UncleHash == ethtypes.EmptyUncleHash && len(body.UncleHashes) > 0 {
|
|
||||||
return nil, errors.Annotatef(fmt.Errorf("server returned non-empty uncle list but block header indicates no uncles"), "hash %v, height %v", hash, height)
|
|
||||||
}
|
|
||||||
if head.UncleHash != ethtypes.EmptyUncleHash && len(body.UncleHashes) == 0 {
|
|
||||||
return nil, errors.Annotatef(fmt.Errorf("server returned empty uncle list but block header indicates uncles"), "hash %v, height %v", hash, height)
|
|
||||||
}
|
|
||||||
if head.TxHash == ethtypes.EmptyRootHash && len(body.Transactions) > 0 {
|
if head.TxHash == ethtypes.EmptyRootHash && len(body.Transactions) > 0 {
|
||||||
return nil, errors.Annotatef(fmt.Errorf("server returned non-empty transaction list but block header indicates no transactions"), "hash %v, height %v", hash, height)
|
return nil, errors.Annotatef(fmt.Errorf("server returned non-empty transaction list but block header indicates no transactions"), "hash %v, height %v", hash, height)
|
||||||
}
|
}
|
||||||
@ -439,11 +434,16 @@ func (b *EthereumRPC) GetBlock(hash string, height uint32) (*bchain.Block, error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "hash %v, height %v", hash, height)
|
return nil, errors.Annotatef(err, "hash %v, height %v", hash, height)
|
||||||
}
|
}
|
||||||
// TODO - this is probably not the correct size
|
bigSize, err := hexutil.DecodeBig(body.Size)
|
||||||
bbh.Size = len(raw)
|
if err != nil {
|
||||||
|
glog.Error("invalid size of block ", body.Hash, ": ", body.Size)
|
||||||
|
} else {
|
||||||
|
bbh.Size = int(bigSize.Int64())
|
||||||
|
}
|
||||||
|
// TODO - get ERC20 events
|
||||||
btxs := make([]bchain.Tx, len(body.Transactions))
|
btxs := make([]bchain.Tx, len(body.Transactions))
|
||||||
for i, tx := range body.Transactions {
|
for i, tx := range body.Transactions {
|
||||||
btx, err := b.Parser.ethTxToTx(&tx, int64(head.Time.Uint64()), uint32(bbh.Confirmations))
|
btx, err := b.Parser.ethTxToTx(&tx, nil, int64(head.Time.Uint64()), uint32(bbh.Confirmations))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "hash %v, height %v, txid %v", hash, height, tx.Hash.String())
|
return nil, errors.Annotatef(err, "hash %v, height %v, txid %v", hash, height, tx.Hash.String())
|
||||||
}
|
}
|
||||||
@ -473,32 +473,38 @@ func (b *EthereumRPC) GetTransaction(txid string) (*bchain.Tx, error) {
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
|
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
var tx *rpcTransaction
|
var tx *rpcTransaction
|
||||||
err := b.rpc.CallContext(ctx, &tx, "eth_getTransactionByHash", ethcommon.HexToHash(txid))
|
hash := ethcommon.HexToHash(txid)
|
||||||
|
err := b.rpc.CallContext(ctx, &tx, "eth_getTransactionByHash", hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if tx == nil {
|
} else if tx == nil {
|
||||||
return nil, ethereum.NotFound
|
return nil, ethereum.NotFound
|
||||||
} else if tx.R == "" {
|
|
||||||
if !b.isETC {
|
|
||||||
return nil, errors.Annotatef(fmt.Errorf("server returned transaction without signature"), "txid %v", txid)
|
|
||||||
} else {
|
|
||||||
glog.Warning("server returned transaction without signature, txid ", txid)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// else if tx.R == "" {
|
||||||
|
// if !b.isETC {
|
||||||
|
// return nil, errors.Annotatef(fmt.Errorf("server returned transaction without signature"), "txid %v", txid)
|
||||||
|
// }
|
||||||
|
// glog.Warning("server returned transaction without signature, txid ", txid)
|
||||||
|
// }
|
||||||
var btx *bchain.Tx
|
var btx *bchain.Tx
|
||||||
if tx.BlockNumber == "" {
|
if tx.BlockNumber == "" {
|
||||||
// mempool tx
|
// mempool tx
|
||||||
btx, err = b.Parser.ethTxToTx(tx, 0, 0)
|
btx, err = b.Parser.ethTxToTx(tx, nil, 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// non mempool tx - we must read the block header to get the block time
|
// non mempool tx - we must read the block header to get the block time
|
||||||
n, err := ethNumber(tx.BlockNumber)
|
h, err := b.client.HeaderByHash(ctx, *tx.BlockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||||
}
|
}
|
||||||
h, err := b.client.HeaderByHash(ctx, *tx.BlockHash)
|
var receipt rpcReceipt
|
||||||
|
err = b.rpc.CallContext(ctx, &receipt, "eth_getTransactionReceipt", hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||||
|
}
|
||||||
|
n, err := ethNumber(tx.BlockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||||
}
|
}
|
||||||
@ -506,7 +512,7 @@ func (b *EthereumRPC) GetTransaction(txid string) (*bchain.Tx, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||||
}
|
}
|
||||||
btx, err = b.Parser.ethTxToTx(tx, h.Time.Int64(), confirmations)
|
btx, err = b.Parser.ethTxToTx(tx, &receipt, h.Time.Int64(), confirmations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ It is generated from these files:
|
|||||||
tx.proto
|
tx.proto
|
||||||
|
|
||||||
It has these top-level messages:
|
It has these top-level messages:
|
||||||
ProtoTransaction
|
ProtoCompleteTransaction
|
||||||
*/
|
*/
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
@ -27,149 +27,234 @@ var _ = math.Inf
|
|||||||
// proto package needs to be updated.
|
// proto package needs to be updated.
|
||||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||||
|
|
||||||
type ProtoTransaction struct {
|
type ProtoCompleteTransaction struct {
|
||||||
AccountNonce uint64 `protobuf:"varint,1,opt,name=AccountNonce" json:"AccountNonce,omitempty"`
|
BlockNumber uint32 `protobuf:"varint,1,opt,name=BlockNumber" json:"BlockNumber,omitempty"`
|
||||||
Price []byte `protobuf:"bytes,2,opt,name=Price,proto3" json:"Price,omitempty"`
|
BlockTime uint64 `protobuf:"varint,2,opt,name=BlockTime" json:"BlockTime,omitempty"`
|
||||||
GasLimit uint64 `protobuf:"varint,3,opt,name=GasLimit" json:"GasLimit,omitempty"`
|
Tx *ProtoCompleteTransaction_TxType `protobuf:"bytes,3,opt,name=Tx" json:"Tx,omitempty"`
|
||||||
Value []byte `protobuf:"bytes,4,opt,name=Value,proto3" json:"Value,omitempty"`
|
Receipt *ProtoCompleteTransaction_ReceiptType `protobuf:"bytes,4,opt,name=Receipt" json:"Receipt,omitempty"`
|
||||||
Payload []byte `protobuf:"bytes,5,opt,name=Payload,proto3" json:"Payload,omitempty"`
|
|
||||||
Hash []byte `protobuf:"bytes,6,opt,name=Hash,proto3" json:"Hash,omitempty"`
|
|
||||||
BlockNumber uint32 `protobuf:"varint,7,opt,name=BlockNumber" json:"BlockNumber,omitempty"`
|
|
||||||
BlockTime uint64 `protobuf:"varint,8,opt,name=BlockTime" json:"BlockTime,omitempty"`
|
|
||||||
To []byte `protobuf:"bytes,9,opt,name=To,proto3" json:"To,omitempty"`
|
|
||||||
From []byte `protobuf:"bytes,10,opt,name=From,proto3" json:"From,omitempty"`
|
|
||||||
TransactionIndex uint32 `protobuf:"varint,11,opt,name=TransactionIndex" json:"TransactionIndex,omitempty"`
|
|
||||||
V []byte `protobuf:"bytes,12,opt,name=V,proto3" json:"V,omitempty"`
|
|
||||||
R []byte `protobuf:"bytes,13,opt,name=R,proto3" json:"R,omitempty"`
|
|
||||||
S []byte `protobuf:"bytes,14,opt,name=S,proto3" json:"S,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ProtoTransaction) Reset() { *m = ProtoTransaction{} }
|
func (m *ProtoCompleteTransaction) Reset() { *m = ProtoCompleteTransaction{} }
|
||||||
func (m *ProtoTransaction) String() string { return proto.CompactTextString(m) }
|
func (m *ProtoCompleteTransaction) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ProtoTransaction) ProtoMessage() {}
|
func (*ProtoCompleteTransaction) ProtoMessage() {}
|
||||||
func (*ProtoTransaction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
func (*ProtoCompleteTransaction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetAccountNonce() uint64 {
|
func (m *ProtoCompleteTransaction) GetBlockNumber() uint32 {
|
||||||
if m != nil {
|
|
||||||
return m.AccountNonce
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetPrice() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.Price
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetGasLimit() uint64 {
|
|
||||||
if m != nil {
|
|
||||||
return m.GasLimit
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetValue() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.Value
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetPayload() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.Payload
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetHash() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.Hash
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetBlockNumber() uint32 {
|
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.BlockNumber
|
return m.BlockNumber
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetBlockTime() uint64 {
|
func (m *ProtoCompleteTransaction) GetBlockTime() uint64 {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.BlockTime
|
return m.BlockTime
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetTo() []byte {
|
func (m *ProtoCompleteTransaction) GetTx() *ProtoCompleteTransaction_TxType {
|
||||||
|
if m != nil {
|
||||||
|
return m.Tx
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction) GetReceipt() *ProtoCompleteTransaction_ReceiptType {
|
||||||
|
if m != nil {
|
||||||
|
return m.Receipt
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProtoCompleteTransaction_TxType struct {
|
||||||
|
AccountNonce uint64 `protobuf:"varint,1,opt,name=AccountNonce" json:"AccountNonce,omitempty"`
|
||||||
|
Price []byte `protobuf:"bytes,2,opt,name=Price,proto3" json:"Price,omitempty"`
|
||||||
|
GasLimit uint64 `protobuf:"varint,3,opt,name=GasLimit" json:"GasLimit,omitempty"`
|
||||||
|
Value []byte `protobuf:"bytes,4,opt,name=Value,proto3" json:"Value,omitempty"`
|
||||||
|
Payload []byte `protobuf:"bytes,5,opt,name=Payload,proto3" json:"Payload,omitempty"`
|
||||||
|
Hash []byte `protobuf:"bytes,6,opt,name=Hash,proto3" json:"Hash,omitempty"`
|
||||||
|
To []byte `protobuf:"bytes,7,opt,name=To,proto3" json:"To,omitempty"`
|
||||||
|
From []byte `protobuf:"bytes,8,opt,name=From,proto3" json:"From,omitempty"`
|
||||||
|
TransactionIndex uint32 `protobuf:"varint,9,opt,name=TransactionIndex" json:"TransactionIndex,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_TxType) Reset() { *m = ProtoCompleteTransaction_TxType{} }
|
||||||
|
func (m *ProtoCompleteTransaction_TxType) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*ProtoCompleteTransaction_TxType) ProtoMessage() {}
|
||||||
|
func (*ProtoCompleteTransaction_TxType) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor0, []int{0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_TxType) GetAccountNonce() uint64 {
|
||||||
|
if m != nil {
|
||||||
|
return m.AccountNonce
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_TxType) GetPrice() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Price
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_TxType) GetGasLimit() uint64 {
|
||||||
|
if m != nil {
|
||||||
|
return m.GasLimit
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_TxType) GetValue() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Value
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_TxType) GetPayload() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Payload
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_TxType) GetHash() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Hash
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_TxType) GetTo() []byte {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.To
|
return m.To
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetFrom() []byte {
|
func (m *ProtoCompleteTransaction_TxType) GetFrom() []byte {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.From
|
return m.From
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetTransactionIndex() uint32 {
|
func (m *ProtoCompleteTransaction_TxType) GetTransactionIndex() uint32 {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.TransactionIndex
|
return m.TransactionIndex
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetV() []byte {
|
type ProtoCompleteTransaction_ReceiptType struct {
|
||||||
|
GasUsed []byte `protobuf:"bytes,1,opt,name=GasUsed,proto3" json:"GasUsed,omitempty"`
|
||||||
|
Status []byte `protobuf:"bytes,2,opt,name=Status,proto3" json:"Status,omitempty"`
|
||||||
|
Log []*ProtoCompleteTransaction_ReceiptType_LogType `protobuf:"bytes,3,rep,name=Log" json:"Log,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_ReceiptType) Reset() { *m = ProtoCompleteTransaction_ReceiptType{} }
|
||||||
|
func (m *ProtoCompleteTransaction_ReceiptType) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*ProtoCompleteTransaction_ReceiptType) ProtoMessage() {}
|
||||||
|
func (*ProtoCompleteTransaction_ReceiptType) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor0, []int{0, 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_ReceiptType) GetGasUsed() []byte {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.V
|
return m.GasUsed
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetR() []byte {
|
func (m *ProtoCompleteTransaction_ReceiptType) GetStatus() []byte {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.R
|
return m.Status
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ProtoTransaction) GetS() []byte {
|
func (m *ProtoCompleteTransaction_ReceiptType) GetLog() []*ProtoCompleteTransaction_ReceiptType_LogType {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.S
|
return m.Log
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProtoCompleteTransaction_ReceiptType_LogType struct {
|
||||||
|
Address []byte `protobuf:"bytes,1,opt,name=Address,proto3" json:"Address,omitempty"`
|
||||||
|
Data []byte `protobuf:"bytes,2,opt,name=Data,proto3" json:"Data,omitempty"`
|
||||||
|
Topics [][]byte `protobuf:"bytes,3,rep,name=Topics,proto3" json:"Topics,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_ReceiptType_LogType) Reset() {
|
||||||
|
*m = ProtoCompleteTransaction_ReceiptType_LogType{}
|
||||||
|
}
|
||||||
|
func (m *ProtoCompleteTransaction_ReceiptType_LogType) String() string {
|
||||||
|
return proto.CompactTextString(m)
|
||||||
|
}
|
||||||
|
func (*ProtoCompleteTransaction_ReceiptType_LogType) ProtoMessage() {}
|
||||||
|
func (*ProtoCompleteTransaction_ReceiptType_LogType) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor0, []int{0, 1, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_ReceiptType_LogType) GetAddress() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Address
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_ReceiptType_LogType) GetData() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Data
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProtoCompleteTransaction_ReceiptType_LogType) GetTopics() [][]byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Topics
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterType((*ProtoTransaction)(nil), "eth.ProtoTransaction")
|
proto.RegisterType((*ProtoCompleteTransaction)(nil), "eth.ProtoCompleteTransaction")
|
||||||
|
proto.RegisterType((*ProtoCompleteTransaction_TxType)(nil), "eth.ProtoCompleteTransaction.TxType")
|
||||||
|
proto.RegisterType((*ProtoCompleteTransaction_ReceiptType)(nil), "eth.ProtoCompleteTransaction.ReceiptType")
|
||||||
|
proto.RegisterType((*ProtoCompleteTransaction_ReceiptType_LogType)(nil), "eth.ProtoCompleteTransaction.ReceiptType.LogType")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { proto.RegisterFile("tx.proto", fileDescriptor0) }
|
func init() { proto.RegisterFile("tx.proto", fileDescriptor0) }
|
||||||
|
|
||||||
var fileDescriptor0 = []byte{
|
var fileDescriptor0 = []byte{
|
||||||
// 262 bytes of a gzipped FileDescriptorProto
|
// 393 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x90, 0xbd, 0x6a, 0xeb, 0x40,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xdf, 0x8a, 0xd4, 0x30,
|
||||||
0x10, 0x85, 0x59, 0x59, 0xb6, 0xe5, 0xb1, 0x6c, 0xcc, 0x70, 0x8b, 0xe1, 0x92, 0x42, 0xb8, 0x12,
|
0x14, 0xc6, 0xe9, 0x9f, 0x69, 0x67, 0x4f, 0xab, 0x48, 0x10, 0x09, 0xc5, 0x8b, 0xb2, 0x78, 0x51,
|
||||||
0x29, 0xd2, 0xe4, 0x09, 0x92, 0x22, 0x3f, 0x10, 0x8c, 0x90, 0x85, 0xfa, 0xf5, 0x7a, 0xc1, 0x22,
|
0xbd, 0x28, 0xb8, 0xfa, 0x02, 0xeb, 0x88, 0xab, 0x30, 0xac, 0x43, 0x8c, 0xde, 0x67, 0xd3, 0xb0,
|
||||||
0x92, 0x26, 0x48, 0x2b, 0x70, 0x5e, 0x38, 0xcf, 0x11, 0x76, 0x44, 0x12, 0x87, 0x74, 0xf3, 0x7d,
|
0x53, 0x6c, 0x9b, 0xd2, 0xa4, 0xd0, 0x7d, 0x1d, 0xdf, 0xc9, 0x17, 0xf1, 0x09, 0x24, 0xa7, 0xad,
|
||||||
0x70, 0xf6, 0x2c, 0x07, 0x22, 0x77, 0xbe, 0x79, 0xeb, 0xd8, 0x31, 0x4e, 0xac, 0x3b, 0x6d, 0x3f,
|
0x8e, 0x88, 0xb2, 0x77, 0xe7, 0xf7, 0x71, 0xbe, 0xc9, 0xf7, 0x9d, 0x29, 0x6c, 0xed, 0x54, 0xf6,
|
||||||
0x02, 0xd8, 0x64, 0x1e, 0x8b, 0x4e, 0xb7, 0xbd, 0x36, 0xae, 0xe2, 0x16, 0xb7, 0x10, 0xdf, 0x19,
|
0x83, 0xb6, 0x9a, 0x04, 0xca, 0x1e, 0xcf, 0xbf, 0x6d, 0x80, 0x1e, 0x1c, 0xee, 0x74, 0xdb, 0x37,
|
||||||
0xc3, 0x43, 0xeb, 0x76, 0xdc, 0x1a, 0x4b, 0x2a, 0x51, 0x69, 0x98, 0xff, 0x72, 0xf8, 0x0f, 0xa6,
|
0xca, 0x2a, 0x3e, 0x88, 0xce, 0x08, 0x69, 0x6b, 0xdd, 0x91, 0x1c, 0x92, 0x37, 0x8d, 0x96, 0x5f,
|
||||||
0x59, 0x57, 0x19, 0x4b, 0x41, 0xa2, 0xd2, 0x38, 0x1f, 0x01, 0xff, 0x43, 0xf4, 0xa8, 0xfb, 0x97,
|
0xaf, 0xc7, 0xf6, 0x46, 0x0d, 0xd4, 0xcb, 0xbd, 0xe2, 0x01, 0x3b, 0x95, 0xc8, 0x53, 0x38, 0x43,
|
||||||
0xaa, 0xa9, 0x1c, 0x4d, 0x24, 0xf5, 0xcd, 0x3e, 0x51, 0xea, 0x7a, 0xb0, 0x14, 0x8e, 0x09, 0x01,
|
0xe4, 0x75, 0xab, 0xa8, 0x9f, 0x7b, 0x45, 0xc8, 0x7e, 0x0b, 0xe4, 0x35, 0xf8, 0x7c, 0xa2, 0x41,
|
||||||
0x24, 0x98, 0x67, 0xfa, 0xbd, 0x66, 0x7d, 0xa4, 0xa9, 0xf8, 0x2f, 0x44, 0x84, 0xf0, 0x49, 0xf7,
|
0xee, 0x15, 0xc9, 0xc5, 0xb3, 0x52, 0xd9, 0x63, 0xf9, 0xaf, 0xa7, 0x4a, 0x3e, 0xf1, 0xbb, 0x5e,
|
||||||
0x27, 0x9a, 0x89, 0x96, 0x1b, 0x13, 0x58, 0xde, 0xd7, 0x6c, 0x5e, 0x77, 0x43, 0x73, 0xb0, 0x1d,
|
0x31, 0x9f, 0x4f, 0x64, 0x07, 0x31, 0x53, 0x52, 0xd5, 0xbd, 0xa5, 0x21, 0x5a, 0x9f, 0xff, 0xdf,
|
||||||
0xcd, 0x13, 0x95, 0xae, 0xf2, 0x4b, 0x85, 0x57, 0xb0, 0x10, 0x2c, 0xaa, 0xc6, 0x52, 0x24, 0x5f,
|
0xba, 0x2c, 0xa3, 0x7f, 0x75, 0x66, 0x3f, 0x3c, 0x88, 0xe6, 0xdf, 0x24, 0xe7, 0x90, 0x5e, 0x4a,
|
||||||
0xf8, 0x11, 0xb8, 0x86, 0xa0, 0x60, 0x5a, 0xc8, 0x8b, 0x41, 0xc1, 0xbe, 0xe3, 0xa1, 0xe3, 0x86,
|
0xa9, 0xc7, 0xce, 0x5e, 0xeb, 0x4e, 0x2a, 0xac, 0x11, 0xb2, 0x3f, 0x34, 0xf2, 0x18, 0x36, 0x87,
|
||||||
0x60, 0xec, 0xf0, 0x37, 0x5e, 0xc3, 0xe6, 0x62, 0x8c, 0xe7, 0xf6, 0x68, 0xcf, 0xb4, 0x94, 0xa2,
|
0xa1, 0x96, 0x73, 0x87, 0x94, 0xcd, 0x40, 0x32, 0xd8, 0x5e, 0x09, 0xb3, 0xaf, 0xdb, 0xda, 0x62,
|
||||||
0x3f, 0x1e, 0x63, 0x50, 0x25, 0xc5, 0x12, 0x56, 0xa5, 0xa7, 0x9c, 0x56, 0x23, 0xe5, 0x9e, 0xf6,
|
0x8b, 0x90, 0xfd, 0x62, 0xe7, 0xf8, 0x22, 0x9a, 0x51, 0x61, 0xc6, 0x94, 0xcd, 0x40, 0x28, 0xc4,
|
||||||
0xb4, 0x1e, 0x69, 0x7f, 0x98, 0xc9, 0xe8, 0xb7, 0x9f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x15, 0xc8,
|
0x07, 0x71, 0xd7, 0x68, 0x51, 0xd1, 0x0d, 0xea, 0x2b, 0x12, 0x02, 0xe1, 0x7b, 0x61, 0x8e, 0x34,
|
||||||
0xe4, 0x30, 0x80, 0x01, 0x00, 0x00,
|
0x42, 0x19, 0x67, 0xf2, 0x10, 0x7c, 0xae, 0x69, 0x8c, 0x8a, 0xcf, 0xb5, 0xdb, 0x79, 0x37, 0xe8,
|
||||||
|
0x96, 0x6e, 0xe7, 0x1d, 0x37, 0x93, 0x17, 0xf0, 0xe8, 0xa4, 0xec, 0x87, 0xae, 0x52, 0x13, 0x3d,
|
||||||
|
0xc3, 0x3f, 0xe2, 0x2f, 0x3d, 0xfb, 0xee, 0x41, 0x72, 0x72, 0x0d, 0x97, 0xe6, 0x4a, 0x98, 0xcf,
|
||||||
|
0x46, 0x55, 0x58, 0x3a, 0x65, 0x2b, 0x92, 0x27, 0x10, 0x7d, 0xb2, 0xc2, 0x8e, 0x66, 0x29, 0xbc,
|
||||||
|
0x10, 0xd9, 0x41, 0xb0, 0xd7, 0xb7, 0x34, 0xc8, 0x83, 0x22, 0xb9, 0x78, 0x79, 0xef, 0xbb, 0x97,
|
||||||
|
0x7b, 0x7d, 0x8b, 0xf7, 0x77, 0xee, 0xec, 0x23, 0xc4, 0x0b, 0xbb, 0x04, 0x97, 0x55, 0x35, 0x28,
|
||||||
|
0x63, 0xd6, 0x04, 0x0b, 0xba, 0xae, 0x6f, 0x85, 0x15, 0xcb, 0xfb, 0x38, 0xbb, 0x54, 0x5c, 0xf7,
|
||||||
|
0xb5, 0x34, 0x18, 0x20, 0x65, 0x0b, 0xdd, 0x44, 0xf8, 0xc1, 0xbe, 0xfa, 0x19, 0x00, 0x00, 0xff,
|
||||||
|
0xff, 0x84, 0x73, 0x4b, 0xa3, 0xbc, 0x02, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,30 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
package eth;
|
package eth;
|
||||||
|
|
||||||
message ProtoTransaction {
|
message ProtoCompleteTransaction {
|
||||||
uint64 AccountNonce = 1;
|
message TxType {
|
||||||
bytes Price = 2;
|
uint64 AccountNonce = 1;
|
||||||
uint64 GasLimit = 3;
|
bytes Price = 2;
|
||||||
bytes Value = 4;
|
uint64 GasLimit = 3;
|
||||||
bytes Payload = 5;
|
bytes Value = 4;
|
||||||
bytes Hash = 6;
|
bytes Payload = 5;
|
||||||
uint32 BlockNumber = 7;
|
bytes Hash = 6;
|
||||||
uint64 BlockTime = 8;
|
bytes To = 7;
|
||||||
bytes To = 9;
|
bytes From = 8;
|
||||||
bytes From = 10;
|
uint32 TransactionIndex = 9;
|
||||||
uint32 TransactionIndex = 11;
|
}
|
||||||
bytes V = 12;
|
message ReceiptType {
|
||||||
bytes R = 13;
|
message LogType {
|
||||||
bytes S = 14;
|
bytes Address = 1;
|
||||||
|
bytes Data = 2;
|
||||||
|
repeated bytes Topics = 3;
|
||||||
|
}
|
||||||
|
bytes GasUsed = 1;
|
||||||
|
bytes Status = 2;
|
||||||
|
repeated LogType Log = 3;
|
||||||
|
}
|
||||||
|
uint32 BlockNumber = 1;
|
||||||
|
uint64 BlockTime = 2;
|
||||||
|
TxType Tx = 3;
|
||||||
|
ReceiptType Receipt = 4;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user