github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/core/vm/ppos_precontracts.go (about)

     1  package vm
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"errors"
     7  	"fmt"
     8  	"github.com/PlatONnetwork/PlatON-Go/common"
     9  	"github.com/PlatONnetwork/PlatON-Go/common/byteutil"
    10  	"github.com/PlatONnetwork/PlatON-Go/log"
    11  	"github.com/PlatONnetwork/PlatON-Go/rlp"
    12  	gerr "github.com/go-errors/errors"
    13  	"reflect"
    14  )
    15  
    16  // Ppos pre-compiled contract address
    17  var PrecompiledContractsPpos = map[common.Address]PrecompiledContract{
    18  	common.CandidatePoolAddr: &CandidateContract{},
    19  	common.TicketPoolAddr:    &TicketContract{},
    20  }
    21  
    22  var (
    23  	ErrParamsRlpDecode = errors.New("Rlp decode fail")
    24  	ErrParamsBaselen   = errors.New("Params Base length does not match")
    25  	ErrParamsLen       = errors.New("Params length does not match")
    26  	ErrUndefFunction   = errors.New("Undefined function")
    27  	ErrTxType          = errors.New("Transaction type does not match the function")
    28  )
    29  
    30  // execute decode input data and call the function.
    31  func execute(input []byte, command map[string]interface{}) ([]byte, error) {
    32  	log.Info("Input to execute==> ", "input: ", hex.EncodeToString(input))
    33  	defer func() {
    34  		if err := recover(); nil != err {
    35  			// catch call panic
    36  			msg := fmt.Sprintf("panic: %v\n", gerr.Wrap(err, 2).ErrorStack())
    37  			log.Error("Failed to execute==> ", "err: ", fmt.Sprint(err), "\nstack: ", msg)
    38  		}
    39  	}()
    40  	var source [][]byte
    41  	if err := rlp.Decode(bytes.NewReader(input), &source); nil != err {
    42  		log.Error("Failed to execute==> ", err.Error())
    43  		return nil, ErrParamsRlpDecode
    44  	}
    45  	if len(source) < 2 {
    46  		log.Error("Failed to execute==> ", "ErrParamsBaselen: ", ErrParamsBaselen.Error())
    47  		return nil, ErrParamsBaselen
    48  	}
    49  	// get func and param list
    50  	if _, ok := command[byteutil.BytesToString(source[1])]; !ok {
    51  		log.Error("Failed to execute==> ", "ErrUndefFunction: ", ErrUndefFunction.Error())
    52  		return nil, ErrUndefFunction
    53  	}
    54  	funcValue := command[byteutil.BytesToString(source[1])]
    55  	// validate transaction type
    56  	var txTypeMap = map[string]uint64{
    57  		"VoteTicket":             1000,
    58  		"CandidateDeposit":       1001,
    59  		"CandidateApplyWithdraw": 1002,
    60  		"CandidateWithdraw":      1003,
    61  		"SetCandidateExtra":      1004,
    62  	}
    63  	if txType, ok := txTypeMap[byteutil.BytesToString(source[1])]; ok {
    64  		if txType != byteutil.BytesTouint64(source[0]) {
    65  			log.Error("Failed to execute==> ", "ErrTxType: ", ErrTxType.Error())
    66  			return nil, ErrTxType
    67  		}
    68  	}
    69  	paramList := reflect.TypeOf(funcValue)
    70  	paramNum := paramList.NumIn()
    71  	params := make([]reflect.Value, paramNum)
    72  	if paramNum != len(source)-2 {
    73  		log.Error("Failed to execute==> ", "ErrParamsLen: ", ErrParamsLen.Error())
    74  		return nil, ErrParamsLen
    75  	}
    76  	for i := 0; i < paramNum; i++ {
    77  		targetType := paramList.In(i).String()
    78  		originByte := []reflect.Value{reflect.ValueOf(source[i+2])}
    79  		params[i] = reflect.ValueOf(byteutil.Command[targetType]).Call(originByte)[0]
    80  	}
    81  	result := reflect.ValueOf(funcValue).Call(params)
    82  	log.Info("Result of execute==> ", "result[0]: ", result[0].Bytes())
    83  	if _, err := result[1].Interface().(error); !err {
    84  		return result[0].Bytes(), nil
    85  	}
    86  	log.Error("Result of execute==> ", "result[1]: err ", result[1].Interface().(error).Error())
    87  	return result[0].Bytes(), result[1].Interface().(error)
    88  }
    89  
    90  // ResultCommon is the struct of transaction event.
    91  type ResultCommon struct {
    92  	Ret    bool
    93  	Data   string
    94  	ErrMsg string
    95  }
    96  
    97  // DecodeResultStr format the string of value to bytes.
    98  func DecodeResultStr(result string) []byte {
    99  	resultBytes := []byte(result)
   100  	strHash := common.BytesToHash(common.Int32ToBytes(32))
   101  	sizeHash := common.BytesToHash(common.Int64ToBytes(int64((len(resultBytes)))))
   102  	var dataRealSize = len(resultBytes)
   103  	if (dataRealSize % 32) != 0 {
   104  		dataRealSize = dataRealSize + (32 - (dataRealSize % 32))
   105  	}
   106  	dataByt := make([]byte, dataRealSize)
   107  	copy(dataByt[0:], resultBytes)
   108  
   109  	finalData := make([]byte, 0)
   110  	finalData = append(finalData, strHash.Bytes()...)
   111  	finalData = append(finalData, sizeHash.Bytes()...)
   112  	finalData = append(finalData, dataByt...)
   113  	return finalData
   114  }