github.com/annchain/OG@v0.0.9/vm/vm_test/common_test.go (about)

     1  package vm_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"encoding/hex"
     7  	"fmt"
     8  	"github.com/annchain/OG/arefactor/og/types"
     9  	"github.com/annchain/OG/common"
    10  	"github.com/annchain/OG/common/math"
    11  	"github.com/annchain/OG/vm/eth/core/vm"
    12  	"github.com/annchain/OG/vm/ovm"
    13  	vmtypes "github.com/annchain/OG/vm/types"
    14  	"github.com/sirupsen/logrus"
    15  
    16  	"github.com/stretchr/testify/assert"
    17  
    18  	"io/ioutil"
    19  	"math/big"
    20  	"reflect"
    21  	"testing"
    22  )
    23  
    24  func readFile(filename string) []byte {
    25  	bytes, err := ioutil.ReadFile(Root + filename)
    26  	if err != nil {
    27  		panic(err)
    28  	}
    29  	bytes, err = hex.DecodeString(string(bytes))
    30  	return bytes
    31  }
    32  
    33  type Runtime struct {
    34  	VmContext *vmtypes.Context
    35  	TxContext *ovm.TxContext
    36  	Tracer    vm.Tracer
    37  }
    38  
    39  func DefaultLDB(from common.Address, coinBase common.Address) *ovm.LayerStateDB {
    40  	mmdb := ovm.NewMemoryStateDB()
    41  	ldb := ovm.NewLayerDB(mmdb)
    42  	ldb.NewLayer()
    43  	ldb.CreateAccount(from)
    44  	ldb.AddBalance(from, math.NewBigInt(10000000))
    45  	ldb.CreateAccount(coinBase)
    46  	ldb.AddBalance(coinBase, math.NewBigInt(10000000))
    47  	logrus.Info("init accounts done")
    48  	return ldb
    49  }
    50  
    51  func DefaultOVM(runtime *Runtime) *ovm.OVM {
    52  	evmInterpreter := vm.NewEVMInterpreter(runtime.VmContext, runtime.TxContext,
    53  		&vm.InterpreterConfig{
    54  			Debug:  true,
    55  			Tracer: runtime.Tracer,
    56  		})
    57  	oovm := ovm.NewOVM(runtime.VmContext, []ovm.Interpreter{evmInterpreter}, &ovm.OVMConfig{NoRecursion: false})
    58  	return oovm
    59  }
    60  
    61  func DeployContract(filename string, from common.Address, coinBase common.Address, rt *Runtime, params []byte) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
    62  	txContext := &ovm.TxContext{
    63  		From:       from,
    64  		Value:      math.NewBigInt(0),
    65  		Data:       readFile(filename),
    66  		GasPrice:   math.NewBigInt(1),
    67  		GasLimit:   DefaultGasLimit,
    68  		Coinbase:   coinBase,
    69  		SequenceID: 0,
    70  	}
    71  
    72  	oovm := DefaultOVM(rt)
    73  	if params != nil && len(params) != 0 {
    74  		txContext.Data = append(txContext.Data, params...)
    75  	}
    76  
    77  	logrus.WithField("filename", filename).Info("Deploying contract")
    78  	ret, contractAddr, leftOverGas, err = oovm.Create(vmtypes.AccountRef(txContext.From), txContext.Data, txContext.GasLimit, txContext.Value.Value)
    79  	// make duplicate
    80  	//ovm.StateDB.SetNonce(coinBase, 0)
    81  	//ret, contractAddr, leftOverGas, err = ovm.Create(&context, vmtypes.AccountRef(coinBase), txContext.Data, txContext.GasLimit, txContext.Value.Value)
    82  	logrus.WithFields(logrus.Fields{
    83  		"filename":     filename,
    84  		"contractAddr": contractAddr.Hex(),
    85  		"err":          err,
    86  		"ret":          common.Bytes2Hex(ret),
    87  	}).Info("Deployed contract")
    88  	//fmt.Println(rt.VmContext.StateDB.String())
    89  	//rt.Tracer.Write(os.Stdout)
    90  	return
    91  }
    92  
    93  func CallContract(contractAddr common.Address, from common.Address, coinBase common.Address, rt *Runtime, value *math.BigInt, functionHash string, params []byte) (ret []byte, leftOverGas uint64, err error) {
    94  	txContext := &ovm.TxContext{
    95  		From:       from,
    96  		To:         contractAddr,
    97  		Value:      value,
    98  		GasPrice:   math.NewBigInt(1),
    99  		GasLimit:   DefaultGasLimit,
   100  		Coinbase:   coinBase,
   101  		SequenceID: 0,
   102  	}
   103  
   104  	logrus.WithField("contract", contractAddr.Hex()).WithField("function", functionHash).Info("Calling contract")
   105  
   106  	var input []byte
   107  	contractAddress, err := hex.DecodeString(functionHash)
   108  	if err != nil {
   109  		return
   110  	}
   111  	input = append(input, contractAddress...)
   112  	if params != nil && len(params) != 0 {
   113  		input = append(input, params...)
   114  	}
   115  
   116  	oovm := DefaultOVM(rt)
   117  	//fmt.Println("Input:")
   118  	//fmt.Println(hex.Dump(input))
   119  	ret, leftOverGas, err = oovm.Call(vmtypes.AccountRef(txContext.From), contractAddr, input, txContext.GasLimit, txContext.Value.Value)
   120  	logrus.Info("Called contract")
   121  	//fmt.Println("CP2", common.Bytes2Hex(ret), contractAddr.String(), leftOverGas, err)
   122  	//fmt.Println(rt.VmContext.StateDB.String())
   123  	//rt.Tracer.Write(os.Stdout)
   124  	return
   125  }
   126  
   127  func pad(r []byte, baseLen int, padLeft bool) []byte {
   128  	l := len(r)
   129  	newl := baseLen
   130  	if len(r) > baseLen {
   131  		newl = ((l + baseLen - 1) / baseLen) * baseLen
   132  	}
   133  	bytes := make([]byte, newl)
   134  	if padLeft {
   135  		copy(bytes[newl-l:], r)
   136  	} else {
   137  		copy(bytes[0:], r)
   138  	}
   139  
   140  	return bytes
   141  }
   142  
   143  // DecodeParamToString decodes bytes to string in return value of a contract call
   144  // Just for debugging. Do not use it in prod code
   145  func DecodeParamToString(b []byte) string {
   146  	if len(b) < 96 {
   147  		// no string possible here
   148  		return ""
   149  	}
   150  	length := binary.BigEndian.Uint64(b[56:64])
   151  	return string(b[64 : 64+length])
   152  }
   153  
   154  func DecodeParamToBigInt(b []byte) *math.BigInt {
   155  	return math.NewBigIntFromBigInt(big.NewInt(0).SetBytes(b))
   156  }
   157  
   158  func DecodeParamToByteString(b []byte) string {
   159  	return hex.EncodeToString(b)
   160  }
   161  
   162  // EncodeParams is for encoding params to ABI bytecode
   163  // Just for debugging. Do not use it in prod code
   164  func EncodeParams(params []interface{}) []byte {
   165  	//300000, test me   ,PPPPPPPPPP
   166  	//00000000000000000000000000000000000000000000000000000000000493e0
   167  	//0000000000000000000000000000000000000000000000000000000000000060
   168  	//00000000000000000000000000000000000000000000000000000000000000a0
   169  	//000000000000000000000000000000000000000000000000000000000000000a
   170  	//74657374206d6520202000000000000000000000000000000000000000000000
   171  	//000000000000000000000000000000000000000000000000000000000000000a
   172  	//5050505050505050505000000000000000000000000000000000000000000000
   173  
   174  	buf := bytes.Buffer{}
   175  	pointer := len(params) * 32
   176  	head := make([]byte, pointer)
   177  	for i, obj := range params {
   178  		var bs []byte
   179  		switch obj.(type) {
   180  		case int:
   181  			bs = make([]byte, 4)
   182  			binary.BigEndian.PutUint32(bs, uint32(obj.(int)))
   183  		case uint:
   184  			bs = make([]byte, 4)
   185  			binary.BigEndian.PutUint32(bs, uint32(obj.(uint)))
   186  		case int64:
   187  			bs = make([]byte, 8)
   188  			binary.BigEndian.PutUint64(bs, uint64(obj.(int64)))
   189  		case uint64:
   190  			bs = make([]byte, 8)
   191  			binary.BigEndian.PutUint64(bs, uint64(obj.(uint64)))
   192  		case bool:
   193  			bs = make([]byte, 4)
   194  			if obj.(bool) {
   195  				binary.BigEndian.PutUint32(bs, 1)
   196  			} else {
   197  				binary.BigEndian.PutUint32(bs, 0)
   198  			}
   199  		case common.Address:
   200  			bsv := obj.(common.Address).Bytes
   201  			bs = bsv[:]
   202  		case types.Hash:
   203  			bsv := obj.(types.Hash).Bytes
   204  			bs = bsv[:]
   205  		case string:
   206  			bs = make([]byte, 4)
   207  			binary.BigEndian.PutUint32(bs, uint32(pointer))
   208  			bsPayloadLength := make([]byte, 4)
   209  			binary.BigEndian.PutUint32(bsPayloadLength, uint32(len(obj.(string))))
   210  
   211  			payLoadLengthBytes := pad(bsPayloadLength, 32, true)
   212  			payLoadBytes := pad([]byte(obj.(string)), 32, false)
   213  
   214  			buf.Write(payLoadLengthBytes)
   215  			buf.Write(payLoadBytes)
   216  			pointer += len(payLoadLengthBytes) + len(payLoadBytes)
   217  		default:
   218  			panic(fmt.Sprintf("not supported: %s", reflect.TypeOf(obj).String()))
   219  		}
   220  		bsWrite := pad(bs, 32, true)
   221  		copy(head[i*32:i*32+32], bsWrite)
   222  
   223  	}
   224  	result := bytes.Buffer{}
   225  	result.Write(head)
   226  	result.Write(buf.Bytes())
   227  
   228  	return result.Bytes()
   229  }
   230  
   231  func TestPad(t *testing.T) {
   232  	v, _ := hex.DecodeString("01")
   233  	fmt.Printf("%x\n", pad(v, 4, true))
   234  	v, _ = hex.DecodeString("0101")
   235  	fmt.Printf("%x\n", pad(v, 4, true))
   236  	v, _ = hex.DecodeString("010101")
   237  	fmt.Printf("%x\n", pad(v, 4, true))
   238  	v, _ = hex.DecodeString("01010101")
   239  	fmt.Printf("%x\n", pad(v, 4, true))
   240  	v, _ = hex.DecodeString("0101010101")
   241  	fmt.Printf("%x\n", pad(v, 4, true))
   242  	v, _ = hex.DecodeString("010101010101")
   243  	fmt.Printf("%x\n", pad(v, 4, true))
   244  	v, _ = hex.DecodeString("01010101010101")
   245  	fmt.Printf("%x\n", pad(v, 4, true))
   246  	v, _ = hex.DecodeString("0101010101010101")
   247  	fmt.Printf("%x\n", pad(v, 4, true))
   248  	v, _ = hex.DecodeString("010101010101010101")
   249  	fmt.Printf("%x\n", pad(v, 4, true))
   250  
   251  }
   252  
   253  func TestEncodeParams(t *testing.T) {
   254  	params := []interface{}{1024, "TTTTTTTTTTT", "PPPPPPPPPP"}
   255  	bs := EncodeParams(params)
   256  	fmt.Println(hex.Dump(bs))
   257  }
   258  
   259  func dump(t *testing.T, ldb *ovm.LayerStateDB, ret []byte, leftGas uint64, err error) {
   260  
   261  	fmt.Println(ldb.String())
   262  	//vm.WriteTrace(os.Stdout, tracer.Logs)
   263  	if ret != nil {
   264  		fmt.Printf("Return value: [%s]\n", DecodeParamToByteString(ret))
   265  		fmt.Printf("Return value: [%s]\n", DecodeParamToBigInt(ret))
   266  		fmt.Printf("Return value: [%s]\n", DecodeParamToString(ret))
   267  	}
   268  	fmt.Printf("Left Gas: [%d]\n", leftGas)
   269  	assert.NoError(t, err)
   270  }