497 lines
13 KiB
Go
497 lines
13 KiB
Go
//go:build unittest
|
|
|
|
package eth
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"fmt"
|
|
"math/big"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/trezor/blockbook/bchain"
|
|
"github.com/trezor/blockbook/tests/dbtestdata"
|
|
)
|
|
|
|
func TestEthParser_GetAddrDescFromAddress(t *testing.T) {
|
|
type args struct {
|
|
address string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "with 0x prefix",
|
|
args: args{address: "0x81b7e08f65bdf5648606c89998a9cc8164397647"},
|
|
want: "81b7e08f65bdf5648606c89998a9cc8164397647",
|
|
},
|
|
{
|
|
name: "without 0x prefix",
|
|
args: args{address: "47526228d673e9f079630d6cdaff5a2ed13e0e60"},
|
|
want: "47526228d673e9f079630d6cdaff5a2ed13e0e60",
|
|
},
|
|
{
|
|
name: "address of wrong length",
|
|
args: args{address: "7526228d673e9f079630d6cdaff5a2ed13e0e60"},
|
|
want: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "ErrAddressMissing",
|
|
args: args{address: ""},
|
|
want: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "error - not eth address",
|
|
args: args{address: "1JKgN43B9SyLuZH19H5ECvr4KcfrbVHzZ6"},
|
|
want: "",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
p := NewEthereumParser(1, false)
|
|
got, err := p.GetAddrDescFromAddress(tt.args.address)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("EthParser.GetAddrDescFromAddress() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
h := hex.EncodeToString(got)
|
|
if !reflect.DeepEqual(h, tt.want) {
|
|
t.Errorf("EthParser.GetAddrDescFromAddress() = %v, want %v", h, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var testTx1, testTx2, testTx1Failed, testTx1NoStatus bchain.Tx
|
|
|
|
func init() {
|
|
|
|
testTx1 = bchain.Tx{
|
|
Blocktime: 1534858022,
|
|
Time: 1534858022,
|
|
Txid: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
|
|
Vin: []bchain.Vin{
|
|
{
|
|
Addresses: []string{"0x3E3a3D69dc66bA10737F531ed088954a9EC89d97"},
|
|
},
|
|
},
|
|
Vout: []bchain.Vout{
|
|
{
|
|
ValueSat: *big.NewInt(1999622000000000000),
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Addresses: []string{"0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f"},
|
|
},
|
|
},
|
|
},
|
|
CoinSpecificData: bchain.EthereumSpecificData{
|
|
Tx: &bchain.RpcTransaction{
|
|
AccountNonce: "0xb26c",
|
|
GasPrice: "0x430e23400",
|
|
GasLimit: "0x5208",
|
|
To: "0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f",
|
|
Value: "0x1bc0159d530e6000",
|
|
Payload: "0x",
|
|
Hash: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
|
|
BlockNumber: "0x41eee8",
|
|
From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97",
|
|
TransactionIndex: "0xa",
|
|
},
|
|
Receipt: &bchain.RpcReceipt{
|
|
GasUsed: "0x5208",
|
|
Status: "0x1",
|
|
Logs: []*bchain.RpcLog{},
|
|
},
|
|
},
|
|
}
|
|
|
|
testTx2 = bchain.Tx{
|
|
Blocktime: 1534858022,
|
|
Time: 1534858022,
|
|
Txid: "0xa9cd088aba2131000da6f38a33c20169baee476218deea6b78720700b895b101",
|
|
Vin: []bchain.Vin{
|
|
{
|
|
Addresses: []string{"0x20cD153de35D469BA46127A0C8F18626b59a256A"},
|
|
},
|
|
},
|
|
Vout: []bchain.Vout{
|
|
{
|
|
ValueSat: *big.NewInt(0),
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Addresses: []string{"0x4af4114F73d1c1C903aC9E0361b379D1291808A2"},
|
|
},
|
|
},
|
|
},
|
|
CoinSpecificData: bchain.EthereumSpecificData{
|
|
Tx: &bchain.RpcTransaction{
|
|
AccountNonce: "0xd0",
|
|
GasPrice: "0x9502f9000",
|
|
GasLimit: "0x130d5",
|
|
To: "0x4af4114F73d1c1C903aC9E0361b379D1291808A2",
|
|
Value: "0x0",
|
|
Payload: "0xa9059cbb000000000000000000000000555ee11fbddc0e49a9bab358a8941ad95ffdb48f00000000000000000000000000000000000000000000021e19e0c9bab2400000",
|
|
Hash: "0xa9cd088aba2131000da6f38a33c20169baee476218deea6b78720700b895b101",
|
|
BlockNumber: "0x41eee8",
|
|
From: "0x20cD153de35D469BA46127A0C8F18626b59a256A",
|
|
TransactionIndex: "0x0"},
|
|
Receipt: &bchain.RpcReceipt{
|
|
GasUsed: "0xcb39",
|
|
Status: "0x1",
|
|
Logs: []*bchain.RpcLog{
|
|
{
|
|
Address: "0x4af4114F73d1c1C903aC9E0361b379D1291808A2",
|
|
Data: "0x00000000000000000000000000000000000000000000021e19e0c9bab2400000",
|
|
Topics: []string{
|
|
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
|
|
"0x00000000000000000000000020cd153de35d469ba46127a0c8f18626b59a256a",
|
|
"0x000000000000000000000000555ee11fbddc0e49a9bab358a8941ad95ffdb48f",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
testTx1Failed = bchain.Tx{
|
|
Blocktime: 1534858022,
|
|
Time: 1534858022,
|
|
Txid: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
|
|
Vin: []bchain.Vin{
|
|
{
|
|
Addresses: []string{"0x3E3a3D69dc66bA10737F531ed088954a9EC89d97"},
|
|
},
|
|
},
|
|
Vout: []bchain.Vout{
|
|
{
|
|
ValueSat: *big.NewInt(1999622000000000000),
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Addresses: []string{"0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f"},
|
|
},
|
|
},
|
|
},
|
|
CoinSpecificData: bchain.EthereumSpecificData{
|
|
Tx: &bchain.RpcTransaction{
|
|
AccountNonce: "0xb26c",
|
|
GasPrice: "0x430e23400",
|
|
GasLimit: "0x5208",
|
|
To: "0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f",
|
|
Value: "0x1bc0159d530e6000",
|
|
Payload: "0x",
|
|
Hash: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
|
|
BlockNumber: "0x41eee8",
|
|
From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97",
|
|
TransactionIndex: "0xa",
|
|
},
|
|
Receipt: &bchain.RpcReceipt{
|
|
GasUsed: "0x5208",
|
|
Status: "0x0",
|
|
Logs: []*bchain.RpcLog{},
|
|
},
|
|
},
|
|
}
|
|
|
|
testTx1NoStatus = bchain.Tx{
|
|
Blocktime: 1534858022,
|
|
Time: 1534858022,
|
|
Txid: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
|
|
Vin: []bchain.Vin{
|
|
{
|
|
Addresses: []string{"0x3E3a3D69dc66bA10737F531ed088954a9EC89d97"},
|
|
},
|
|
},
|
|
Vout: []bchain.Vout{
|
|
{
|
|
ValueSat: *big.NewInt(1999622000000000000),
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Addresses: []string{"0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f"},
|
|
},
|
|
},
|
|
},
|
|
CoinSpecificData: bchain.EthereumSpecificData{
|
|
Tx: &bchain.RpcTransaction{
|
|
AccountNonce: "0xb26c",
|
|
GasPrice: "0x430e23400",
|
|
GasLimit: "0x5208",
|
|
To: "0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f",
|
|
Value: "0x1bc0159d530e6000",
|
|
Payload: "0x",
|
|
Hash: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
|
|
BlockNumber: "0x41eee8",
|
|
From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97",
|
|
TransactionIndex: "0xa",
|
|
},
|
|
Receipt: &bchain.RpcReceipt{
|
|
GasUsed: "0x5208",
|
|
Status: "",
|
|
Logs: []*bchain.RpcLog{},
|
|
},
|
|
},
|
|
}
|
|
|
|
}
|
|
|
|
func TestEthereumParser_PackTx(t *testing.T) {
|
|
type args struct {
|
|
tx *bchain.Tx
|
|
height uint32
|
|
blockTime int64
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
p *EthereumParser
|
|
args args
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "1",
|
|
args: args{
|
|
tx: &testTx1,
|
|
height: 4321000,
|
|
blockTime: 1534858022,
|
|
},
|
|
want: dbtestdata.EthTx1Packed,
|
|
},
|
|
{
|
|
name: "2",
|
|
args: args{
|
|
tx: &testTx2,
|
|
height: 4321000,
|
|
blockTime: 1534858022,
|
|
},
|
|
want: dbtestdata.EthTx2Packed,
|
|
},
|
|
{
|
|
name: "3",
|
|
args: args{
|
|
tx: &testTx1Failed,
|
|
height: 4321000,
|
|
blockTime: 1534858022,
|
|
},
|
|
want: dbtestdata.EthTx1FailedPacked,
|
|
},
|
|
{
|
|
name: "4",
|
|
args: args{
|
|
tx: &testTx1NoStatus,
|
|
height: 4321000,
|
|
blockTime: 1534858022,
|
|
},
|
|
want: dbtestdata.EthTx1NoStatusPacked,
|
|
},
|
|
}
|
|
p := NewEthereumParser(1, false)
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := p.PackTx(tt.args.tx, tt.args.height, tt.args.blockTime)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("EthereumParser.PackTx() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
h := hex.EncodeToString(got)
|
|
if !reflect.DeepEqual(h, tt.want) {
|
|
t.Errorf("EthereumParser.PackTx() = %v, want %v", h, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEthereumParser_UnpackTx(t *testing.T) {
|
|
type args struct {
|
|
hex string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
p *EthereumParser
|
|
args args
|
|
want *bchain.Tx
|
|
want1 uint32
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "1",
|
|
args: args{hex: dbtestdata.EthTx1Packed},
|
|
want: &testTx1,
|
|
want1: 4321000,
|
|
},
|
|
{
|
|
name: "2",
|
|
args: args{hex: dbtestdata.EthTx2Packed},
|
|
want: &testTx2,
|
|
want1: 4321000,
|
|
},
|
|
{
|
|
name: "3",
|
|
args: args{hex: dbtestdata.EthTx1FailedPacked},
|
|
want: &testTx1Failed,
|
|
want1: 4321000,
|
|
},
|
|
{
|
|
name: "4",
|
|
args: args{hex: dbtestdata.EthTx1NoStatusPacked},
|
|
want: &testTx1NoStatus,
|
|
want1: 4321000,
|
|
},
|
|
}
|
|
p := NewEthereumParser(1, false)
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
b, err := hex.DecodeString(tt.args.hex)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
got, got1, err := p.UnpackTx(b)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("EthereumParser.UnpackTx() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
// DeepEqual has problems with pointers in completeTransaction
|
|
gs := got.CoinSpecificData.(bchain.EthereumSpecificData)
|
|
ws := tt.want.CoinSpecificData.(bchain.EthereumSpecificData)
|
|
gc := *got
|
|
wc := *tt.want
|
|
gc.CoinSpecificData = nil
|
|
wc.CoinSpecificData = nil
|
|
if fmt.Sprint(gc) != fmt.Sprint(wc) {
|
|
// if !reflect.DeepEqual(gc, wc) {
|
|
t.Errorf("EthereumParser.UnpackTx() gc got = %+v, want %+v", gc, wc)
|
|
}
|
|
if !reflect.DeepEqual(gs.Tx, ws.Tx) {
|
|
t.Errorf("EthereumParser.UnpackTx() gs.Tx got = %+v, want %+v", gs.Tx, ws.Tx)
|
|
}
|
|
if !reflect.DeepEqual(gs.Receipt, ws.Receipt) {
|
|
t.Errorf("EthereumParser.UnpackTx() gs.Receipt got = %+v, want %+v", gs.Receipt, ws.Receipt)
|
|
}
|
|
if got1 != tt.want1 {
|
|
t.Errorf("EthereumParser.UnpackTx() got1 = %v, want %v", got1, tt.want1)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEthereumParser_GetEthereumTxData(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
tx *bchain.Tx
|
|
want string
|
|
}{
|
|
{
|
|
name: "Test empty data",
|
|
tx: &testTx1,
|
|
want: "0x",
|
|
},
|
|
{
|
|
name: "Test non empty data",
|
|
tx: &testTx2,
|
|
want: "0xa9059cbb000000000000000000000000555ee11fbddc0e49a9bab358a8941ad95ffdb48f00000000000000000000000000000000000000000000021e19e0c9bab2400000",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := GetEthereumTxData(tt.tx)
|
|
if got.Data != tt.want {
|
|
t.Errorf("EthereumParser.GetEthereumTxData() = %v, want %v", got.Data, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEthereumParser_ParseErrorFromOutput(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
output string
|
|
want string
|
|
}{
|
|
{
|
|
name: "ParseErrorFromOutput 1",
|
|
output: "0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000031546f74616c206e756d626572206f662067726f757073206d7573742062652067726561746572207468616e207a65726f2e000000000000000000000000000000",
|
|
want: "Total number of groups must be greater than zero.",
|
|
},
|
|
{
|
|
name: "ParseErrorFromOutput 2",
|
|
output: "0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000126e6f7420656e6f7567682062616c616e63650000000000000000000000000000",
|
|
want: "not enough balance",
|
|
},
|
|
{
|
|
name: "ParseErrorFromOutput empty",
|
|
output: "",
|
|
want: "",
|
|
},
|
|
{
|
|
name: "ParseErrorFromOutput short",
|
|
output: "0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012",
|
|
want: "",
|
|
},
|
|
{
|
|
name: "ParseErrorFromOutput invalid signature",
|
|
output: "0x08c379b0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000126e6f7420656e6f7567682062616c616e63650000000000000000000000000000",
|
|
want: "",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := ParseErrorFromOutput(tt.output)
|
|
if got != tt.want {
|
|
t.Errorf("EthereumParser.ParseErrorFromOutput() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEthereumParser_PackInternalTransactionError_UnpackInternalTransactionError(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
original string
|
|
packed string
|
|
unpacked string
|
|
}{
|
|
{
|
|
name: "execution reverted",
|
|
original: "execution reverted",
|
|
packed: "\x01",
|
|
unpacked: "Reverted.",
|
|
},
|
|
{
|
|
name: "out of gas",
|
|
original: "out of gas",
|
|
packed: "\x02",
|
|
unpacked: "Out of gas.",
|
|
},
|
|
{
|
|
name: "contract creation code storage out of gas",
|
|
original: "contract creation code storage out of gas",
|
|
packed: "\x03",
|
|
unpacked: "Contract creation code storage out of gas.",
|
|
},
|
|
{
|
|
name: "max code size exceeded",
|
|
original: "max code size exceeded",
|
|
packed: "\x04",
|
|
unpacked: "Max code size exceeded.",
|
|
},
|
|
{
|
|
name: "unknown error",
|
|
original: "unknown error",
|
|
packed: "unknown error",
|
|
unpacked: "unknown error",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
packed := PackInternalTransactionError(tt.original)
|
|
if packed != tt.packed {
|
|
t.Errorf("EthereumParser.PackInternalTransactionError() = %v, want %v", packed, tt.packed)
|
|
}
|
|
unpacked := UnpackInternalTransactionError([]byte(packed))
|
|
if unpacked != tt.unpacked {
|
|
t.Errorf("EthereumParser.UnpackInternalTransactionError() = %v, want %v", unpacked, tt.unpacked)
|
|
}
|
|
})
|
|
}
|
|
}
|