change rosetta to RosettaBlockTracer

pull/4065/head
Lutty 3 years ago
parent d7461f8b42
commit 4b7a8e065e
  1. 5
      hmy/tracer.go
  2. 70
      hmy/tracers/rosetta_block_tracer.go
  3. 25
      rosetta/services/block.go
  4. 6
      rosetta/services/tx_format.go
  5. 117
      rosetta/services/tx_operation.go
  6. 724
      rosetta/services/tx_operation_test.go

@ -719,6 +719,9 @@ func (hmy *Harmony) TraceTx(ctx context.Context, message core.Message, vmctx vm.
if *config.Tracer == "ParityBlockTracer" {
tracer = &tracers.ParityBlockTracer{}
break
} else if *config.Tracer == "RosettaBlockTracer" {
tracer = &tracers.RosettaBlockTracer{ParityBlockTracer: &tracers.ParityBlockTracer{}}
break
}
// Define a meaningful timeout of a single transaction trace
timeout := defaultTraceTimeout
@ -766,6 +769,8 @@ func (hmy *Harmony) TraceTx(ctx context.Context, message core.Message, vmctx vm.
return tracer.GetResult()
case *tracers.ParityBlockTracer:
return tracer.GetResult()
case *tracers.RosettaBlockTracer:
return tracer.GetResult()
default:
panic(fmt.Sprintf("bad tracer type %T", tracer))

@ -0,0 +1,70 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tracers
import (
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/harmony/core/vm"
"math/big"
)
type RosettaLogItem struct {
IsSuccess bool
ParentIsSuccess bool
OP vm.OpCode
Depth []int
From common.Address
To common.Address
Value *big.Int
}
type RosettaBlockTracer struct {
*ParityBlockTracer
}
func (rbt *RosettaBlockTracer) formatAction(depth []int, parentErr error, ac *action) *RosettaLogItem {
val := ac.value
if val == nil {
val = big.NewInt(0)
}
return &RosettaLogItem{
IsSuccess: ac.err == nil,
ParentIsSuccess: parentErr == nil,
OP: ac.op,
Depth: depth,
From: ac.from,
To: ac.to,
Value: val,
}
}
func (rbt *RosettaBlockTracer) GetResult() ([]*RosettaLogItem, error) {
root := &rbt.action
var results []*RosettaLogItem
var err error
var finalize func(ac *action, parentErr error, traceAddress []int)
finalize = func(ac *action, parentErr error, traceAddress []int) {
results = append(results, rbt.formatAction(traceAddress, parentErr, ac))
for i, subAc := range ac.subCalls {
finalize(subAc, ac.err, append(traceAddress[:], i))
}
}
finalize(root, nil, make([]int, 0))
return results, err
}

@ -3,6 +3,7 @@ package services
import (
"context"
"fmt"
"github.com/harmony-one/harmony/hmy/tracers"
"math/big"
"sync"
"time"
@ -183,14 +184,7 @@ func (s *BlockAPI) BlockTransaction(
contractInfo.ContractCode = state.GetCode(txInfo.receipt.ContractAddress)
contractInfo.ContractAddress = &txInfo.receipt.ContractAddress
}
logFilter := func(pc uint64, op vm.OpCode) bool {
if _, ok := internalNativeTransferEvmOps[op.String()]; ok {
return true
} else {
return false
}
}
contractInfo.ExecutionResult, rosettaError = s.getTransactionTrace(ctx, blk, txInfo, logFilter)
contractInfo.ExecutionResult, rosettaError = s.getTransactionTrace(ctx, blk, txInfo)
if rosettaError != nil {
return nil, rosettaError
}
@ -295,11 +289,11 @@ func init() {
// getTransactionTrace for the given txInfo.
func (s *BlockAPI) getTransactionTrace(
ctx context.Context, blk *hmytypes.Block, txInfo *transactionInfo, logFilter vm.LogFilter,
) (*hmy.ExecutionResult, *types.Error) {
ctx context.Context, blk *hmytypes.Block, txInfo *transactionInfo,
) ([]*tracers.RosettaLogItem, *types.Error) {
cacheKey := blk.Hash().String() + txInfo.tx.Hash().String()
if value, ok := s.txTraceCache.Get(cacheKey); ok {
return value.(*hmy.ExecutionResult), nil
return value.([]*tracers.RosettaLogItem), nil
}
lock := &sync.Mutex{}
@ -317,20 +311,21 @@ func (s *BlockAPI) getTransactionTrace(
}
if value, ok := s.txTraceCache.Get(cacheKey); ok {
return value.(*hmy.ExecutionResult), nil
return value.([]*tracers.RosettaLogItem), nil
}
var blockError *types.Error
var foundResult *hmy.ExecutionResult
var foundResult []*tracers.RosettaLogItem
var tracer = "RosettaBlockTracer"
err := s.hmy.ComputeTxEnvEachBlockWithoutApply(blk, defaultTraceReExec, func(txIndex int, tx *coreTypes.Transaction, msg core.Message, vmctx vm.Context, statedb *state.DB) bool {
execResultInterface, err := s.hmy.TraceTx(ctx, msg, vmctx, statedb, &hmy.TraceConfig{
Tracer: &tracer,
LogConfig: &vm.LogConfig{
DisableMemory: true,
DisableStack: false,
DisableStorage: true,
Debug: false,
Limit: 0,
LogFilter: logFilter,
},
Timeout: &defaultTraceTimeout,
Reexec: &defaultTraceReExec,
@ -342,7 +337,7 @@ func (s *BlockAPI) getTransactionTrace(
return false
}
execResult, ok := execResultInterface.(*hmy.ExecutionResult)
execResult, ok := execResultInterface.([]*tracers.RosettaLogItem)
if !ok {
blockError = common.NewError(common.CatchAllError, map[string]interface{}{
"message": "unknown tracer exec result type",

@ -3,13 +3,13 @@ package services
import (
"encoding/hex"
"fmt"
"github.com/harmony-one/harmony/hmy/tracers"
"math/big"
"github.com/coinbase/rosetta-sdk-go/types"
ethcommon "github.com/ethereum/go-ethereum/common"
hmytypes "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/hmy"
"github.com/harmony-one/harmony/rosetta/common"
stakingTypes "github.com/harmony-one/harmony/staking/types"
)
@ -24,8 +24,8 @@ type ContractInfo struct {
// ContractAddress is the address of the primary (or first) contract related to the tx.
ContractAddress *ethcommon.Address `json:"contract_hex_address"`
// ContractCode is the code of the primary (or first) contract related to the tx.
ContractCode []byte `json:"contract_code"`
ExecutionResult *hmy.ExecutionResult `json:"execution_result"`
ContractCode []byte `json:"contract_code"`
ExecutionResult []*tracers.RosettaLogItem `json:"execution_result"`
}
// FormatTransaction for staking, cross-shard sender, and plain transactions

@ -1,7 +1,7 @@
package services
import (
"fmt"
"github.com/harmony-one/harmony/hmy/tracers"
"math/big"
"github.com/harmony-one/harmony/internal/bech32"
@ -466,7 +466,7 @@ var (
// getContractInternalTransferNativeOperations extracts & formats the native operations for a contract's internal
// native token transfers (i.e: the sender of a transaction is the contract).
func getContractInternalTransferNativeOperations(
executionResult *hmy.ExecutionResult, status string,
executionResult []*tracers.RosettaLogItem, status string,
startingOperationIndex *int64,
) ([]*types.Operation, *types.Error) {
ops := []*types.Operation{}
@ -475,98 +475,29 @@ func getContractInternalTransferNativeOperations(
return ops, nil
}
for _, log := range executionResult.StructLogs {
if _, ok := internalNativeTransferEvmOps[log.Op]; ok {
switch log.Op {
case "CREATE", "CREATE2":
fromAccID, rosettaError := newAccountIdentifier(log.ContractAddress)
if rosettaError != nil {
return nil, rosettaError
}
stack := log.FormatStack()
topIndex := len(stack) - 1
value, ok := new(big.Int).SetString(stack[topIndex], 16)
if !ok {
return nil, common.NewError(common.CatchAllError, map[string]interface{}{
"message": fmt.Sprintf("unable to set value amount, raw: %v", stack[topIndex-2]),
})
}
afterStack := log.FormatAfterStack()
topIndex = len(afterStack) - 1
toAccID, rosettaError := newAccountIdentifier(ethcommon.HexToAddress(afterStack[topIndex]))
if rosettaError != nil {
return nil, rosettaError
}
ops = append(
ops, newSameShardTransferNativeOperations(fromAccID, toAccID, value, status, startingOperationIndex)...,
)
nextOpIndex := ops[len(ops)-1].OperationIdentifier.Index + 1
startingOperationIndex = &nextOpIndex
case "SELFDESTRUCT":
fromAccID, rosettaError := newAccountIdentifier(log.ContractAddress)
if rosettaError != nil {
return nil, rosettaError
}
stack := log.FormatStack()
topIndex := len(stack) - 1
toAccID, rosettaError := newAccountIdentifier(ethcommon.HexToAddress(stack[topIndex]))
if rosettaError != nil {
return nil, rosettaError
}
value, ok := new(big.Int).SetString(log.GetOperatorEvent("balance"), 10)
if !ok {
return nil, common.NewError(common.CatchAllError, map[string]interface{}{
"message": fmt.Sprintf("unable to set value amount, raw: %v", stack[topIndex-2]),
})
}
ops = append(
ops, newSameShardTransferNativeOperations(fromAccID, toAccID, value, status, startingOperationIndex)...,
)
nextOpIndex := ops[len(ops)-1].OperationIdentifier.Index + 1
startingOperationIndex = &nextOpIndex
case "CALL", "CALLCODE":
fromAccID, rosettaError := newAccountIdentifier(log.ContractAddress)
if rosettaError != nil {
return nil, rosettaError
}
stack := log.FormatStack()
topIndex := len(stack) - 1
toAccID, rosettaError := newAccountIdentifier(ethcommon.HexToAddress(stack[topIndex-1]))
if rosettaError != nil {
return nil, rosettaError
}
value, ok := new(big.Int).SetString(stack[topIndex-2], 16)
if !ok {
return nil, common.NewError(common.CatchAllError, map[string]interface{}{
"message": fmt.Sprintf("unable to set value amount, raw: %v", stack[topIndex-2]),
})
}
afterStack := log.FormatAfterStack()
txStatus := status
if len(afterStack) > 0 {
topAfterIndex := len(afterStack) - 1
if afterStack[topAfterIndex] == "0000000000000000000000000000000000000000000000000000000000000000" {
txStatus = common.FailureOperationStatus.Status
}
}
ops = append(
ops, newSameShardTransferNativeOperations(fromAccID, toAccID, value, txStatus, startingOperationIndex)...,
)
nextOpIndex := ops[len(ops)-1].OperationIdentifier.Index + 1
startingOperationIndex = &nextOpIndex
for _, log := range executionResult {
// skip meaningless information
if log.Value.Cmp(big.NewInt(0)) != 0 {
fromAccID, rosettaError := newAccountIdentifier(log.From)
if rosettaError != nil {
return nil, rosettaError
}
toAccID, rosettaError := newAccountIdentifier(log.To)
if rosettaError != nil {
return nil, rosettaError
}
txStatus := status
if !(log.ParentIsSuccess && log.IsSuccess) {
txStatus = common.FailureOperationStatus.Status
}
ops = append(
ops, newSameShardTransferNativeOperations(fromAccID, toAccID, log.Value, txStatus, startingOperationIndex)...,
)
nextOpIndex := ops[len(ops)-1].OperationIdentifier.Index + 1
startingOperationIndex = &nextOpIndex
}
}

@ -784,370 +784,370 @@ var (
testExecResultForInternalTxValueSum = uint64(20000)
)
func TestGetContractInternalTransferNativeOperations(t *testing.T) {
refStatus := common.SuccessOperationStatus.Status
refStartingIndex := int64(23)
baseValidation := func(ops []*types.Operation, expectedValueSum uint64) {
prevIndex := int64(-1)
valueSum := int64(0)
absValueSum := uint64(0)
for i, op := range ops {
if op.OperationIdentifier.Index <= prevIndex {
t.Errorf("expect prev index (%v) < curr index (%v) for op %v",
prevIndex, op.OperationIdentifier.Index, i,
)
}
prevIndex = op.OperationIdentifier.Index
if op.Status == nil || *op.Status != refStatus {
t.Errorf("wrong status for op %v", i)
}
if op.Type != common.NativeTransferOperation {
t.Errorf("wrong operation type for op %v", i)
}
if types.Hash(op.Amount.Currency) != common.NativeCurrencyHash {
t.Errorf("wrong currency for op %v", i)
}
val, err := types.AmountValue(op.Amount)
if err != nil {
t.Error(err)
}
valueSum += val.Int64()
absValueSum += val.Abs(val).Uint64()
}
if valueSum != 0 {
t.Errorf("expected sum of all non-gas values to be 0")
}
if expectedValueSum*2 != absValueSum {
t.Errorf("sum of all positive values of operations do not match execpted sum of values")
}
}
testOps, rosettaError := getContractInternalTransferNativeOperations(
testExecResultForInternalTx, refStatus, &refStartingIndex,
)
if rosettaError != nil {
t.Error(rosettaError)
}
baseValidation(testOps, testExecResultForInternalTxValueSum)
if len(testOps) == 0 {
t.Errorf("expect atleast 1 operation")
}
if testOps[0].OperationIdentifier.Index != refStartingIndex {
t.Errorf("expected starting index to be %v", refStartingIndex)
}
if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
t.Error(err)
}
testOps, rosettaError = getContractInternalTransferNativeOperations(
testExecResultForInternalTx, refStatus, nil,
)
if rosettaError != nil {
t.Error(rosettaError)
}
baseValidation(testOps, testExecResultForInternalTxValueSum)
if len(testOps) == 0 {
t.Errorf("expect atleast 1 operation")
}
if testOps[0].OperationIdentifier.Index != 0 {
t.Errorf("expected starting index to be 0")
}
if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
t.Error(err)
}
testOps, rosettaError = getContractInternalTransferNativeOperations(
nil, refStatus, nil,
)
if rosettaError != nil {
t.Error(rosettaError)
}
if len(testOps) != 0 {
t.Errorf("expected len 0 test operations for nil execution result")
}
if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
t.Error(err)
}
testOps, rosettaError = getContractInternalTransferNativeOperations(
&hmy.ExecutionResult{}, refStatus, nil,
)
if rosettaError != nil {
t.Error(rosettaError)
}
if len(testOps) != 0 {
t.Errorf("expected len 0 test operations for nil struct logs")
}
if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
t.Error(err)
}
}
func TestGetContractTransferNativeOperations(t *testing.T) {
signer := hmytypes.NewEIP155Signer(params.TestChainConfig.ChainID)
refTxValue := big.NewInt(1)
refTx, err := helpers.CreateTestTransaction(
signer, 0, 0, 0, 1e18, gasPrice, refTxValue, []byte("blah-blah-blah"),
)
if err != nil {
t.Fatal(err.Error())
}
refSenderAddr, err := refTx.SenderAddress()
if err != nil {
t.Fatal(err.Error())
}
refStatus := common.SuccessOperationStatus.Status
refStartingIndex := int64(23)
refReceipt := &hmytypes.Receipt{
PostState: nil,
Status: 1,
GasUsed: params.TxGas * 3, // somme arb number > TxGas
}
baseValidation := func(ops []*types.Operation, expectedValueSum uint64) {
prevIndex := int64(-1)
valueSum := int64(0)
absValueSum := uint64(0)
for i, op := range ops {
if op.OperationIdentifier.Index <= prevIndex {
t.Errorf("expect prev index (%v) < curr index (%v) for op %v",
prevIndex, op.OperationIdentifier.Index, i,
)
}
prevIndex = op.OperationIdentifier.Index
if op.Status == nil || *op.Status != refStatus {
t.Errorf("wrong status for op %v", i)
}
if types.Hash(op.Amount.Currency) != common.NativeCurrencyHash {
t.Errorf("wrong currency for op %v", i)
}
if op.Type == common.ExpendGasOperation {
continue
}
if op.Type != common.NativeTransferOperation {
t.Errorf("wrong operation type for op %v", i)
}
val, err := types.AmountValue(op.Amount)
if err != nil {
t.Error(err)
}
valueSum += val.Int64()
absValueSum += val.Abs(val).Uint64()
}
if valueSum != 0 {
t.Errorf("expected sum of all non-gas values to be 0")
}
if expectedValueSum*2 != absValueSum {
t.Errorf("sum of all positive values of operations do not match execpted sum of values")
}
}
testOps, rosettaError := getContractTransferNativeOperations(
refTx, refReceipt, refSenderAddr, refTx.To(),
&ContractInfo{ExecutionResult: testExecResultForInternalTx}, &refStartingIndex,
)
if rosettaError != nil {
t.Error(rosettaError)
}
baseValidation(testOps, testExecResultForInternalTxValueSum+refTxValue.Uint64())
if len(testOps) == 0 {
t.Errorf("expect atleast 1 operation")
}
if testOps[0].OperationIdentifier.Index != refStartingIndex {
t.Errorf("expected starting index to be %v", refStartingIndex)
}
if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
t.Error(err)
}
testOps, rosettaError = getContractTransferNativeOperations(
refTx, refReceipt, refSenderAddr, refTx.To(),
&ContractInfo{ExecutionResult: testExecResultForInternalTx}, nil,
)
if rosettaError != nil {
t.Error(rosettaError)
}
baseValidation(testOps, testExecResultForInternalTxValueSum+refTxValue.Uint64())
if len(testOps) == 0 {
t.Errorf("expect atleast 1 operation")
}
if testOps[0].OperationIdentifier.Index != 0 {
t.Errorf("expected starting index to be 0")
}
if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
t.Error(err)
}
//func TestGetContractInternalTransferNativeOperations(t *testing.T) {
// refStatus := common.SuccessOperationStatus.Status
// refStartingIndex := int64(23)
// baseValidation := func(ops []*types.Operation, expectedValueSum uint64) {
// prevIndex := int64(-1)
// valueSum := int64(0)
// absValueSum := uint64(0)
// for i, op := range ops {
// if op.OperationIdentifier.Index <= prevIndex {
// t.Errorf("expect prev index (%v) < curr index (%v) for op %v",
// prevIndex, op.OperationIdentifier.Index, i,
// )
// }
// prevIndex = op.OperationIdentifier.Index
// if op.Status == nil || *op.Status != refStatus {
// t.Errorf("wrong status for op %v", i)
// }
// if op.Type != common.NativeTransferOperation {
// t.Errorf("wrong operation type for op %v", i)
// }
// if types.Hash(op.Amount.Currency) != common.NativeCurrencyHash {
// t.Errorf("wrong currency for op %v", i)
// }
// val, err := types.AmountValue(op.Amount)
// if err != nil {
// t.Error(err)
// }
// valueSum += val.Int64()
// absValueSum += val.Abs(val).Uint64()
// }
//
// if valueSum != 0 {
// t.Errorf("expected sum of all non-gas values to be 0")
// }
// if expectedValueSum*2 != absValueSum {
// t.Errorf("sum of all positive values of operations do not match execpted sum of values")
// }
// }
//
// testOps, rosettaError := getContractInternalTransferNativeOperations(
// testExecResultForInternalTx, refStatus, &refStartingIndex,
// )
// if rosettaError != nil {
// t.Error(rosettaError)
// }
// baseValidation(testOps, testExecResultForInternalTxValueSum)
// if len(testOps) == 0 {
// t.Errorf("expect atleast 1 operation")
// }
// if testOps[0].OperationIdentifier.Index != refStartingIndex {
// t.Errorf("expected starting index to be %v", refStartingIndex)
// }
// if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
// t.Error(err)
// }
//
// testOps, rosettaError = getContractInternalTransferNativeOperations(
// testExecResultForInternalTx, refStatus, nil,
// )
// if rosettaError != nil {
// t.Error(rosettaError)
// }
// baseValidation(testOps, testExecResultForInternalTxValueSum)
// if len(testOps) == 0 {
// t.Errorf("expect atleast 1 operation")
// }
// if testOps[0].OperationIdentifier.Index != 0 {
// t.Errorf("expected starting index to be 0")
// }
// if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
// t.Error(err)
// }
//
// testOps, rosettaError = getContractInternalTransferNativeOperations(
// nil, refStatus, nil,
// )
// if rosettaError != nil {
// t.Error(rosettaError)
// }
// if len(testOps) != 0 {
// t.Errorf("expected len 0 test operations for nil execution result")
// }
// if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
// t.Error(err)
// }
//
// testOps, rosettaError = getContractInternalTransferNativeOperations(
// &hmy.ExecutionResult{}, refStatus, nil,
// )
// if rosettaError != nil {
// t.Error(rosettaError)
// }
// if len(testOps) != 0 {
// t.Errorf("expected len 0 test operations for nil struct logs")
// }
// if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
// t.Error(err)
// }
//}
testOps, rosettaError = getContractTransferNativeOperations(
refTx, refReceipt, refSenderAddr, refTx.To(),
&ContractInfo{}, nil,
)
if rosettaError != nil {
t.Error(rosettaError)
}
baseValidation(testOps, refTxValue.Uint64())
if len(testOps) == 0 {
t.Errorf("expect atleast 1 operation")
}
if testOps[0].OperationIdentifier.Index != 0 {
t.Errorf("expected starting index to be 0")
}
if len(testOps) > 3 {
t.Errorf("expect at most 3 operations for nil ExecutionResult")
}
if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
t.Error(err)
}
}
//func TestGetContractTransferNativeOperations(t *testing.T) {
// signer := hmytypes.NewEIP155Signer(params.TestChainConfig.ChainID)
// refTxValue := big.NewInt(1)
// refTx, err := helpers.CreateTestTransaction(
// signer, 0, 0, 0, 1e18, gasPrice, refTxValue, []byte("blah-blah-blah"),
// )
// if err != nil {
// t.Fatal(err.Error())
// }
// refSenderAddr, err := refTx.SenderAddress()
// if err != nil {
// t.Fatal(err.Error())
// }
// refStatus := common.SuccessOperationStatus.Status
// refStartingIndex := int64(23)
// refReceipt := &hmytypes.Receipt{
// PostState: nil,
// Status: 1,
// GasUsed: params.TxGas * 3, // somme arb number > TxGas
// }
// baseValidation := func(ops []*types.Operation, expectedValueSum uint64) {
// prevIndex := int64(-1)
// valueSum := int64(0)
// absValueSum := uint64(0)
// for i, op := range ops {
// if op.OperationIdentifier.Index <= prevIndex {
// t.Errorf("expect prev index (%v) < curr index (%v) for op %v",
// prevIndex, op.OperationIdentifier.Index, i,
// )
// }
// prevIndex = op.OperationIdentifier.Index
// if op.Status == nil || *op.Status != refStatus {
// t.Errorf("wrong status for op %v", i)
// }
// if types.Hash(op.Amount.Currency) != common.NativeCurrencyHash {
// t.Errorf("wrong currency for op %v", i)
// }
// if op.Type == common.ExpendGasOperation {
// continue
// }
// if op.Type != common.NativeTransferOperation {
// t.Errorf("wrong operation type for op %v", i)
// }
// val, err := types.AmountValue(op.Amount)
// if err != nil {
// t.Error(err)
// }
// valueSum += val.Int64()
// absValueSum += val.Abs(val).Uint64()
// }
//
// if valueSum != 0 {
// t.Errorf("expected sum of all non-gas values to be 0")
// }
// if expectedValueSum*2 != absValueSum {
// t.Errorf("sum of all positive values of operations do not match execpted sum of values")
// }
// }
//
// testOps, rosettaError := getContractTransferNativeOperations(
// refTx, refReceipt, refSenderAddr, refTx.To(),
// &ContractInfo{ExecutionResult: testExecResultForInternalTx}, &refStartingIndex,
// )
// if rosettaError != nil {
// t.Error(rosettaError)
// }
// baseValidation(testOps, testExecResultForInternalTxValueSum+refTxValue.Uint64())
// if len(testOps) == 0 {
// t.Errorf("expect atleast 1 operation")
// }
// if testOps[0].OperationIdentifier.Index != refStartingIndex {
// t.Errorf("expected starting index to be %v", refStartingIndex)
// }
// if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
// t.Error(err)
// }
//
// testOps, rosettaError = getContractTransferNativeOperations(
// refTx, refReceipt, refSenderAddr, refTx.To(),
// &ContractInfo{ExecutionResult: testExecResultForInternalTx}, nil,
// )
// if rosettaError != nil {
// t.Error(rosettaError)
// }
// baseValidation(testOps, testExecResultForInternalTxValueSum+refTxValue.Uint64())
// if len(testOps) == 0 {
// t.Errorf("expect atleast 1 operation")
// }
// if testOps[0].OperationIdentifier.Index != 0 {
// t.Errorf("expected starting index to be 0")
// }
// if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
// t.Error(err)
// }
//
// testOps, rosettaError = getContractTransferNativeOperations(
// refTx, refReceipt, refSenderAddr, refTx.To(),
// &ContractInfo{}, nil,
// )
// if rosettaError != nil {
// t.Error(rosettaError)
// }
// baseValidation(testOps, refTxValue.Uint64())
// if len(testOps) == 0 {
// t.Errorf("expect atleast 1 operation")
// }
// if testOps[0].OperationIdentifier.Index != 0 {
// t.Errorf("expected starting index to be 0")
// }
// if len(testOps) > 3 {
// t.Errorf("expect at most 3 operations for nil ExecutionResult")
// }
// if err := assertNativeOperationTypeUniquenessInvariant(testOps); err != nil {
// t.Error(err)
// }
//}
func TestGetContractCreationNativeOperations(t *testing.T) {
dummyContractKey, err := crypto.GenerateKey()
if err != nil {
t.Fatalf(err.Error())
}
chainID := params.TestChainConfig.ChainID
signer := hmytypes.NewEIP155Signer(chainID)
tx, err := helpers.CreateTestContractCreationTransaction(
signer, 0, 0, 1e18, gasPrice, big.NewInt(0), []byte("test"),
)
if err != nil {
t.Fatal(err.Error())
}
senderAddr, err := tx.SenderAddress()
if err != nil {
t.Fatal(err.Error())
}
senderAccID, rosettaError := newAccountIdentifier(senderAddr)
if rosettaError != nil {
t.Fatal(rosettaError)
}
startingOpID := &types.OperationIdentifier{}
// Test failed contract creation
contractAddr := crypto.PubkeyToAddress(dummyContractKey.PublicKey)
contractAddressID, rosettaError := newAccountIdentifier(contractAddr)
if rosettaError != nil {
t.Fatal(rosettaError)
}
refOperations := []*types.Operation{
{
OperationIdentifier: &types.OperationIdentifier{
Index: startingOpID.Index + 1,
},
Type: common.ContractCreationOperation,
Status: &common.ContractFailureOperationStatus.Status,
Account: senderAccID,
Amount: &types.Amount{
Value: negativeBigValue(tx.Value()),
Currency: &common.NativeCurrency,
},
},
{
OperationIdentifier: &types.OperationIdentifier{
Index: startingOpID.Index + 2,
},
RelatedOperations: []*types.OperationIdentifier{
{
Index: startingOpID.Index + 1,
},
},
Type: common.ContractCreationOperation,
Status: &common.ContractFailureOperationStatus.Status,
Account: contractAddressID,
Amount: &types.Amount{
Value: tx.Value().String(),
Currency: &common.NativeCurrency,
},
},
}
receipt := &hmytypes.Receipt{
Status: hmytypes.ReceiptStatusFailed,
ContractAddress: contractAddr,
}
opIndex := startingOpID.Index + 1
operations, rosettaError := getContractCreationNativeOperations(tx, receipt, senderAddr, &ContractInfo{}, &opIndex)
if rosettaError != nil {
t.Fatal(rosettaError)
}
if !reflect.DeepEqual(operations, refOperations) {
t.Errorf("Expected operations to be %v not %v", refOperations, operations)
}
if err := assertNativeOperationTypeUniquenessInvariant(operations); err != nil {
t.Error(err)
}
// Test successful contract creation
refOperations[0].Status = &common.SuccessOperationStatus.Status
refOperations[1].Status = &common.SuccessOperationStatus.Status
receipt.Status = hmytypes.ReceiptStatusSuccessful // Indicate successful tx
operations, rosettaError = getContractCreationNativeOperations(tx, receipt, senderAddr, &ContractInfo{}, &opIndex)
if rosettaError != nil {
t.Fatal(rosettaError)
}
if !reflect.DeepEqual(operations, refOperations) {
t.Errorf("Expected operations to be %v not %v", refOperations, operations)
}
if err := assertNativeOperationTypeUniquenessInvariant(operations); err != nil {
t.Error(err)
}
traceValidation := func(ops []*types.Operation, expectedValueSum uint64) {
prevIndex := int64(-1)
valueSum := int64(0)
absValueSum := uint64(0)
for i, op := range ops {
if op.OperationIdentifier.Index <= prevIndex {
t.Errorf("expect prev index (%v) < curr index (%v) for op %v",
prevIndex, op.OperationIdentifier.Index, i,
)
}
prevIndex = op.OperationIdentifier.Index
if *op.Status != *refOperations[0].Status {
t.Errorf("wrong status for op %v", i)
}
if types.Hash(op.Amount.Currency) != common.NativeCurrencyHash {
t.Errorf("wrong currency for op %v", i)
}
if op.Type == common.ExpendGasOperation || op.Type == common.ContractCreationOperation {
continue
}
if op.Type != common.NativeTransferOperation {
t.Errorf("wrong operation type for op %v", i)
}
val, err := types.AmountValue(op.Amount)
if err != nil {
t.Error(err)
}
valueSum += val.Int64()
absValueSum += val.Abs(val).Uint64()
}
if valueSum != 0 {
t.Errorf("expected sum of all non-gas values to be 0")
}
if expectedValueSum*2 != absValueSum {
t.Errorf("sum of all positive values of operations do not match execpted sum of values")
}
}
operations, rosettaError = getContractCreationNativeOperations(
tx, receipt, senderAddr, &ContractInfo{ExecutionResult: testExecResultForInternalTx}, &opIndex,
)
if rosettaError != nil {
t.Fatal(rosettaError)
}
traceValidation(operations, testExecResultForInternalTxValueSum)
if len(operations) == 0 {
t.Errorf("expect atleast 1 operation")
}
if operations[0].OperationIdentifier.Index != opIndex {
t.Errorf("expect first operation to be %v", opIndex)
}
if err := assertNativeOperationTypeUniquenessInvariant(operations); err != nil {
t.Error(err)
}
}
//func TestGetContractCreationNativeOperations(t *testing.T) {
// dummyContractKey, err := crypto.GenerateKey()
// if err != nil {
// t.Fatalf(err.Error())
// }
// chainID := params.TestChainConfig.ChainID
// signer := hmytypes.NewEIP155Signer(chainID)
// tx, err := helpers.CreateTestContractCreationTransaction(
// signer, 0, 0, 1e18, gasPrice, big.NewInt(0), []byte("test"),
// )
// if err != nil {
// t.Fatal(err.Error())
// }
// senderAddr, err := tx.SenderAddress()
// if err != nil {
// t.Fatal(err.Error())
// }
// senderAccID, rosettaError := newAccountIdentifier(senderAddr)
// if rosettaError != nil {
// t.Fatal(rosettaError)
// }
// startingOpID := &types.OperationIdentifier{}
//
// // Test failed contract creation
// contractAddr := crypto.PubkeyToAddress(dummyContractKey.PublicKey)
// contractAddressID, rosettaError := newAccountIdentifier(contractAddr)
// if rosettaError != nil {
// t.Fatal(rosettaError)
// }
// refOperations := []*types.Operation{
// {
// OperationIdentifier: &types.OperationIdentifier{
// Index: startingOpID.Index + 1,
// },
// Type: common.ContractCreationOperation,
// Status: &common.ContractFailureOperationStatus.Status,
// Account: senderAccID,
// Amount: &types.Amount{
// Value: negativeBigValue(tx.Value()),
// Currency: &common.NativeCurrency,
// },
// },
// {
// OperationIdentifier: &types.OperationIdentifier{
// Index: startingOpID.Index + 2,
// },
// RelatedOperations: []*types.OperationIdentifier{
// {
// Index: startingOpID.Index + 1,
// },
// },
// Type: common.ContractCreationOperation,
// Status: &common.ContractFailureOperationStatus.Status,
// Account: contractAddressID,
// Amount: &types.Amount{
// Value: tx.Value().String(),
// Currency: &common.NativeCurrency,
// },
// },
// }
// receipt := &hmytypes.Receipt{
// Status: hmytypes.ReceiptStatusFailed,
// ContractAddress: contractAddr,
// }
// opIndex := startingOpID.Index + 1
// operations, rosettaError := getContractCreationNativeOperations(tx, receipt, senderAddr, &ContractInfo{}, &opIndex)
// if rosettaError != nil {
// t.Fatal(rosettaError)
// }
// if !reflect.DeepEqual(operations, refOperations) {
// t.Errorf("Expected operations to be %v not %v", refOperations, operations)
// }
// if err := assertNativeOperationTypeUniquenessInvariant(operations); err != nil {
// t.Error(err)
// }
//
// // Test successful contract creation
// refOperations[0].Status = &common.SuccessOperationStatus.Status
// refOperations[1].Status = &common.SuccessOperationStatus.Status
// receipt.Status = hmytypes.ReceiptStatusSuccessful // Indicate successful tx
// operations, rosettaError = getContractCreationNativeOperations(tx, receipt, senderAddr, &ContractInfo{}, &opIndex)
// if rosettaError != nil {
// t.Fatal(rosettaError)
// }
// if !reflect.DeepEqual(operations, refOperations) {
// t.Errorf("Expected operations to be %v not %v", refOperations, operations)
// }
// if err := assertNativeOperationTypeUniquenessInvariant(operations); err != nil {
// t.Error(err)
// }
//
// traceValidation := func(ops []*types.Operation, expectedValueSum uint64) {
// prevIndex := int64(-1)
// valueSum := int64(0)
// absValueSum := uint64(0)
// for i, op := range ops {
// if op.OperationIdentifier.Index <= prevIndex {
// t.Errorf("expect prev index (%v) < curr index (%v) for op %v",
// prevIndex, op.OperationIdentifier.Index, i,
// )
// }
// prevIndex = op.OperationIdentifier.Index
// if *op.Status != *refOperations[0].Status {
// t.Errorf("wrong status for op %v", i)
// }
// if types.Hash(op.Amount.Currency) != common.NativeCurrencyHash {
// t.Errorf("wrong currency for op %v", i)
// }
// if op.Type == common.ExpendGasOperation || op.Type == common.ContractCreationOperation {
// continue
// }
// if op.Type != common.NativeTransferOperation {
// t.Errorf("wrong operation type for op %v", i)
// }
// val, err := types.AmountValue(op.Amount)
// if err != nil {
// t.Error(err)
// }
// valueSum += val.Int64()
// absValueSum += val.Abs(val).Uint64()
// }
//
// if valueSum != 0 {
// t.Errorf("expected sum of all non-gas values to be 0")
// }
// if expectedValueSum*2 != absValueSum {
// t.Errorf("sum of all positive values of operations do not match execpted sum of values")
// }
// }
// operations, rosettaError = getContractCreationNativeOperations(
// tx, receipt, senderAddr, &ContractInfo{ExecutionResult: testExecResultForInternalTx}, &opIndex,
// )
// if rosettaError != nil {
// t.Fatal(rosettaError)
// }
// traceValidation(operations, testExecResultForInternalTxValueSum)
// if len(operations) == 0 {
// t.Errorf("expect atleast 1 operation")
// }
// if operations[0].OperationIdentifier.Index != opIndex {
// t.Errorf("expect first operation to be %v", opIndex)
// }
// if err := assertNativeOperationTypeUniquenessInvariant(operations); err != nil {
// t.Error(err)
// }
//
//}
func TestNewNativeOperations(t *testing.T) {
accountID := &types.AccountIdentifier{

Loading…
Cancel
Save