Unverified Commit 7be29e49 authored by vipwzw's avatar vipwzw Committed by GitHub

Merge branch 'master' into upgrade_protobuf

parents 9931f210 71f4916a
...@@ -28,6 +28,7 @@ import ( ...@@ -28,6 +28,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
//EvmCmd 是Evm命令行入口
func EvmCmd() *cobra.Command { func EvmCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "evm", Use: "evm",
...@@ -36,32 +37,32 @@ func EvmCmd() *cobra.Command { ...@@ -36,32 +37,32 @@ func EvmCmd() *cobra.Command {
} }
cmd.AddCommand( cmd.AddCommand(
CreateContractCmd(), createContractCmd(),
CallContractCmd(), callContractCmd(),
EstimateContractCmd(), estimateContractCmd(),
CheckContractAddrCmd(), checkContractAddrCmd(),
EvmDebugCmd(), evmDebugCmd(),
EvmTransferCmd(), evmTransferCmd(),
EvmWithdrawCmd(), evmWithdrawCmd(),
GetEvmBalanceCmd(), getEvmBalanceCmd(),
EvmToolsCmd(), evmToolsCmd(),
) )
return cmd return cmd
} }
// some tools for evm op // some tools for evm op
func EvmToolsCmd() *cobra.Command { func evmToolsCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "tool", Use: "tool",
Short: "Some tools for evm op", Short: "Some tools for evm op",
} }
cmd.AddCommand(EvmToolsAddressCmd()) cmd.AddCommand(evmToolsAddressCmd())
return cmd return cmd
} }
// transfer address format between ethereum and chain33 // transfer address format between ethereum and chain33
func EvmToolsAddressCmd() *cobra.Command { func evmToolsAddressCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "address", Use: "address",
Short: "Transfer address format between ethereum and local (you should input one address of them)", Short: "Transfer address format between ethereum and local (you should input one address of them)",
...@@ -105,7 +106,7 @@ func transferAddress(cmd *cobra.Command, args []string) { ...@@ -105,7 +106,7 @@ func transferAddress(cmd *cobra.Command, args []string) {
addr = *addrP addr = *addrP
fmt.Println(fmt.Sprintf("Local Address: %v", local)) fmt.Println(fmt.Sprintf("Local Address: %v", local))
} }
fmt.Println(fmt.Sprintf("Ethereum Address: %v", ChecksumAddr(addr.Bytes()))) fmt.Println(fmt.Sprintf("Ethereum Address: %v", checksumAddr(addr.Bytes())))
return return
} }
...@@ -113,7 +114,7 @@ func transferAddress(cmd *cobra.Command, args []string) { ...@@ -113,7 +114,7 @@ func transferAddress(cmd *cobra.Command, args []string) {
} }
// get balance of an execer // get balance of an execer
func GetEvmBalanceCmd() *cobra.Command { func getEvmBalanceCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "balance", Use: "balance",
Short: "Get balance of a evm contract address", Short: "Get balance of a evm contract address",
...@@ -161,11 +162,16 @@ func evmBalance(cmd *cobra.Command, args []string) { ...@@ -161,11 +162,16 @@ func evmBalance(cmd *cobra.Command, args []string) {
ctx.Run() ctx.Run()
} }
// AccountResult 账户余额查询出来之后进行单位转换
type AccountResult struct { type AccountResult struct {
Currency int32 `json:"currency,omitempty"` // 货币
Balance string `json:"balance,omitempty"` Currency int32 `json:"currency,omitempty"`
Frozen string `json:"frozen,omitempty"` // 余额
Addr string `json:"addr,omitempty"` Balance string `json:"balance,omitempty"`
// 冻结余额
Frozen string `json:"frozen,omitempty"`
// 账户地址
Addr string `json:"addr,omitempty"`
} }
func parseGetBalanceRes(arg interface{}) (interface{}, error) { func parseGetBalanceRes(arg interface{}) (interface{}, error) {
...@@ -182,7 +188,7 @@ func parseGetBalanceRes(arg interface{}) (interface{}, error) { ...@@ -182,7 +188,7 @@ func parseGetBalanceRes(arg interface{}) (interface{}, error) {
} }
// 创建EVM合约 // 创建EVM合约
func CreateContractCmd() *cobra.Command { func createContractCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "create", Use: "create",
Short: "Create a new EVM contract", Short: "Create a new EVM contract",
...@@ -319,7 +325,7 @@ func createEvmTransferTx(cmd *cobra.Command, caller, execName, expire, rpcLaddr ...@@ -319,7 +325,7 @@ func createEvmTransferTx(cmd *cobra.Command, caller, execName, expire, rpcLaddr
} }
// 调用EVM合约 // 调用EVM合约
func CallContractCmd() *cobra.Command { func callContractCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "call", Use: "call",
Short: "Call the EVM contract", Short: "Call the EVM contract",
...@@ -431,7 +437,7 @@ func addEstimateFlags(cmd *cobra.Command) { ...@@ -431,7 +437,7 @@ func addEstimateFlags(cmd *cobra.Command) {
} }
// 估算合约消耗 // 估算合约消耗
func EstimateContractCmd() *cobra.Command { func estimateContractCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "estimate", Use: "estimate",
Short: "Estimate the gas cost of calling or creating a contract", Short: "Estimate the gas cost of calling or creating a contract",
...@@ -442,7 +448,7 @@ func EstimateContractCmd() *cobra.Command { ...@@ -442,7 +448,7 @@ func EstimateContractCmd() *cobra.Command {
} }
// 检查地址是否为EVM合约 // 检查地址是否为EVM合约
func CheckContractAddrCmd() *cobra.Command { func checkContractAddrCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "check", Use: "check",
Short: "Check if the address is a valid EVM contract", Short: "Check if the address is a valid EVM contract",
...@@ -485,34 +491,34 @@ func checkContractAddr(cmd *cobra.Command, args []string) { ...@@ -485,34 +491,34 @@ func checkContractAddr(cmd *cobra.Command, args []string) {
} }
// 查询或设置EVM调试开关 // 查询或设置EVM调试开关
func EvmDebugCmd() *cobra.Command { func evmDebugCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "debug", Use: "debug",
Short: "Query or set evm debug status", Short: "Query or set evm debug status",
} }
cmd.AddCommand( cmd.AddCommand(
EvmDebugQueryCmd(), evmDebugQueryCmd(),
EvmDebugSetCmd(), evmDebugSetCmd(),
EvmDebugClearCmd()) evmDebugClearCmd())
return cmd return cmd
} }
func EvmDebugQueryCmd() *cobra.Command { func evmDebugQueryCmd() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: "query", Use: "query",
Short: "Query evm debug status", Short: "Query evm debug status",
Run: evmDebugQuery, Run: evmDebugQuery,
} }
} }
func EvmDebugSetCmd() *cobra.Command { func evmDebugSetCmd() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: "set", Use: "set",
Short: "Set evm debug to ON", Short: "Set evm debug to ON",
Run: evmDebugSet, Run: evmDebugSet,
} }
} }
func EvmDebugClearCmd() *cobra.Command { func evmDebugClearCmd() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: "clear", Use: "clear",
Short: "Set evm debug to OFF", Short: "Set evm debug to OFF",
...@@ -521,17 +527,17 @@ func EvmDebugClearCmd() *cobra.Command { ...@@ -521,17 +527,17 @@ func EvmDebugClearCmd() *cobra.Command {
} }
func evmDebugQuery(cmd *cobra.Command, args []string) { func evmDebugQuery(cmd *cobra.Command, args []string) {
evmDebugRpc(cmd, 0) evmDebugRPC(cmd, 0)
} }
func evmDebugSet(cmd *cobra.Command, args []string) { func evmDebugSet(cmd *cobra.Command, args []string) {
evmDebugRpc(cmd, 1) evmDebugRPC(cmd, 1)
} }
func evmDebugClear(cmd *cobra.Command, args []string) { func evmDebugClear(cmd *cobra.Command, args []string) {
evmDebugRpc(cmd, -1) evmDebugRPC(cmd, -1)
} }
func evmDebugRpc(cmd *cobra.Command, flag int32) { func evmDebugRPC(cmd *cobra.Command, flag int32) {
var debugReq = evmtypes.EvmDebugReq{Optype: flag} var debugReq = evmtypes.EvmDebugReq{Optype: flag}
var debugResp evmtypes.EvmDebugResp var debugResp evmtypes.EvmDebugResp
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
...@@ -545,7 +551,7 @@ func evmDebugRpc(cmd *cobra.Command, flag int32) { ...@@ -545,7 +551,7 @@ func evmDebugRpc(cmd *cobra.Command, flag int32) {
} }
// 向EVM合约地址转账 // 向EVM合约地址转账
func EvmTransferCmd() *cobra.Command { func evmTransferCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "transfer", Use: "transfer",
Short: "Transfer to evm contract address", Short: "Transfer to evm contract address",
...@@ -593,7 +599,7 @@ func evmTransfer(cmd *cobra.Command, args []string) { ...@@ -593,7 +599,7 @@ func evmTransfer(cmd *cobra.Command, args []string) {
} }
// 向EVM合约地址转账 // 向EVM合约地址转账
func EvmWithdrawCmd() *cobra.Command { func evmWithdrawCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "withdraw", Use: "withdraw",
Short: "Withdraw from evm contract address to caller's balance", Short: "Withdraw from evm contract address to caller's balance",
...@@ -662,7 +668,7 @@ func sendQuery(rpcAddr, funcName string, request interface{}, result proto.Messa ...@@ -662,7 +668,7 @@ func sendQuery(rpcAddr, funcName string, request interface{}, result proto.Messa
} }
// 这里实现 EIP55中提及的以太坊地址表示方式(增加Checksum) // 这里实现 EIP55中提及的以太坊地址表示方式(增加Checksum)
func ChecksumAddr(address []byte) string { func checksumAddr(address []byte) string {
unchecksummed := hex.EncodeToString(address[:]) unchecksummed := hex.EncodeToString(address[:])
sha := sha3.NewKeccak256() sha := sha3.NewKeccak256()
sha.Write([]byte(unchecksummed)) sha.Write([]byte(unchecksummed))
......
...@@ -24,7 +24,7 @@ import ( ...@@ -24,7 +24,7 @@ import (
var ( var (
evmDebug = false evmDebug = false
// 本合约地址 // EvmAddress 本合约地址
EvmAddress = address.ExecAddress(types.ExecName(evmtypes.ExecutorName)) EvmAddress = address.ExecAddress(types.ExecName(evmtypes.ExecutorName))
) )
...@@ -35,6 +35,7 @@ func init() { ...@@ -35,6 +35,7 @@ func init() {
ety.InitFuncList(types.ListMethod(&EVMExecutor{})) ety.InitFuncList(types.ListMethod(&EVMExecutor{}))
} }
// Init 初始化本合约对象
func Init(name string, sub []byte) { func Init(name string, sub []byte) {
driverName = name driverName = name
drivers.Register(driverName, newEVMDriver, types.GetDappFork(driverName, "Enable")) drivers.Register(driverName, newEVMDriver, types.GetDappFork(driverName, "Enable"))
...@@ -43,6 +44,7 @@ func Init(name string, sub []byte) { ...@@ -43,6 +44,7 @@ func Init(name string, sub []byte) {
state.InitForkData() state.InitForkData()
} }
// GetName 返回本合约名称
func GetName() string { func GetName() string {
return newEVMDriver().GetName() return newEVMDriver().GetName()
} }
...@@ -53,13 +55,14 @@ func newEVMDriver() drivers.Driver { ...@@ -53,13 +55,14 @@ func newEVMDriver() drivers.Driver {
return evm return evm
} }
// EVM执行器结构 // EVMExecutor EVM执行器结构
type EVMExecutor struct { type EVMExecutor struct {
drivers.DriverBase drivers.DriverBase
vmCfg *runtime.Config vmCfg *runtime.Config
mStateDB *state.MemoryStateDB mStateDB *state.MemoryStateDB
} }
// NewEVMExecutor 新创建执行器对象
func NewEVMExecutor() *EVMExecutor { func NewEVMExecutor() *EVMExecutor {
exec := &EVMExecutor{} exec := &EVMExecutor{}
...@@ -70,15 +73,18 @@ func NewEVMExecutor() *EVMExecutor { ...@@ -70,15 +73,18 @@ func NewEVMExecutor() *EVMExecutor {
return exec return exec
} }
// GetFuncMap 获取方法列表
func (evm *EVMExecutor) GetFuncMap() map[string]reflect.Method { func (evm *EVMExecutor) GetFuncMap() map[string]reflect.Method {
ety := types.LoadExecutorType(driverName) ety := types.LoadExecutorType(driverName)
return ety.GetExecFuncMap() return ety.GetExecFuncMap()
} }
// GetDriverName 获取本合约驱动名称
func (evm *EVMExecutor) GetDriverName() string { func (evm *EVMExecutor) GetDriverName() string {
return evmtypes.ExecutorName return evmtypes.ExecutorName
} }
// Allow 允许哪些交易在本命执行器执行
func (evm *EVMExecutor) Allow(tx *types.Transaction, index int) error { func (evm *EVMExecutor) Allow(tx *types.Transaction, index int) error {
err := evm.DriverBase.Allow(tx, index) err := evm.DriverBase.Allow(tx, index)
if err == nil { if err == nil {
...@@ -94,6 +100,7 @@ func (evm *EVMExecutor) Allow(tx *types.Transaction, index int) error { ...@@ -94,6 +100,7 @@ func (evm *EVMExecutor) Allow(tx *types.Transaction, index int) error {
return types.ErrNotAllow return types.ErrNotAllow
} }
// IsFriend 是否允许对应的KEY
func (evm *EVMExecutor) IsFriend(myexec, writekey []byte, othertx *types.Transaction) bool { func (evm *EVMExecutor) IsFriend(myexec, writekey []byte, othertx *types.Transaction) bool {
if othertx == nil { if othertx == nil {
return false return false
...@@ -115,11 +122,12 @@ func (evm *EVMExecutor) getNewAddr(txHash []byte) common.Address { ...@@ -115,11 +122,12 @@ func (evm *EVMExecutor) getNewAddr(txHash []byte) common.Address {
return common.NewAddress(txHash) return common.NewAddress(txHash)
} }
// CheckTx 校验交易
func (evm *EVMExecutor) CheckTx(tx *types.Transaction, index int) error { func (evm *EVMExecutor) CheckTx(tx *types.Transaction, index int) error {
return nil return nil
} }
//获取运行状态名 // GetActionName 获取运行状态名
func (evm *EVMExecutor) GetActionName(tx *types.Transaction) string { func (evm *EVMExecutor) GetActionName(tx *types.Transaction) string {
if bytes.Equal(tx.Execer, []byte(types.ExecName(evmtypes.ExecutorName))) { if bytes.Equal(tx.Execer, []byte(types.ExecName(evmtypes.ExecutorName))) {
return types.ExecName(evmtypes.ExecutorName) return types.ExecName(evmtypes.ExecutorName)
...@@ -127,15 +135,17 @@ func (evm *EVMExecutor) GetActionName(tx *types.Transaction) string { ...@@ -127,15 +135,17 @@ func (evm *EVMExecutor) GetActionName(tx *types.Transaction) string {
return tx.ActionName() return tx.ActionName()
} }
// GetMStateDB 获取内部状态数据库
func (evm *EVMExecutor) GetMStateDB() *state.MemoryStateDB { func (evm *EVMExecutor) GetMStateDB() *state.MemoryStateDB {
return evm.mStateDB return evm.mStateDB
} }
// GetVMConfig 获取VM配置
func (evm *EVMExecutor) GetVMConfig() *runtime.Config { func (evm *EVMExecutor) GetVMConfig() *runtime.Config {
return evm.vmCfg return evm.vmCfg
} }
// 构造一个新的EVM上下文对象 // NewEVMContext 构造一个新的EVM上下文对象
func (evm *EVMExecutor) NewEVMContext(msg *common.Message) runtime.Context { func (evm *EVMExecutor) NewEVMContext(msg *common.Message) runtime.Context {
return runtime.Context{ return runtime.Context{
CanTransfer: CanTransfer, CanTransfer: CanTransfer,
......
...@@ -18,6 +18,7 @@ import ( ...@@ -18,6 +18,7 @@ import (
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types" evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
) )
// Exec 本合约执行逻辑
func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt, error) { func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt, error) {
evm.CheckInit() evm.CheckInit()
// 先转换消息 // 先转换消息
...@@ -33,12 +34,12 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt, ...@@ -33,12 +34,12 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
env := runtime.NewEVM(context, evm.mStateDB, *evm.vmCfg) env := runtime.NewEVM(context, evm.mStateDB, *evm.vmCfg)
isCreate := strings.Compare(msg.To().String(), EvmAddress) == 0 isCreate := strings.Compare(msg.To().String(), EvmAddress) == 0
var ( var (
ret = []byte("") ret []byte
vmerr error vmerr error
leftOverGas = uint64(0) leftOverGas uint64
contractAddr common.Address contractAddr common.Address
snapshot = -1 snapshot int
execName = "" execName string
) )
// 为了方便计费,即使合约为新生成,也将地址的初始化放到外面操作 // 为了方便计费,即使合约为新生成,也将地址的初始化放到外面操作
...@@ -76,17 +77,17 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt, ...@@ -76,17 +77,17 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
if vmerr != nil { if vmerr != nil {
log.Error("evm contract exec error", "error info", vmerr) log.Error("evm contract exec error", "error info", vmerr)
return nil, vmerr return nil, vmerr
} else { }
// 计算消耗了多少费用(实际消耗的费用)
usedFee, overflow := common.SafeMul(usedGas, uint64(msg.GasPrice())) // 计算消耗了多少费用(实际消耗的费用)
// 费用消耗溢出,执行失败 usedFee, overflow := common.SafeMul(usedGas, uint64(msg.GasPrice()))
if overflow || usedFee > uint64(tx.Fee) { // 费用消耗溢出,执行失败
// 如果操作没有回滚,则在这里处理 if overflow || usedFee > uint64(tx.Fee) {
if curVer != nil && snapshot >= curVer.GetId() && curVer.GetId() > -1 { // 如果操作没有回滚,则在这里处理
evm.mStateDB.RevertToSnapshot(snapshot) if curVer != nil && snapshot >= curVer.GetID() && curVer.GetID() > -1 {
} evm.mStateDB.RevertToSnapshot(snapshot)
return nil, model.ErrOutOfGas
} }
return nil, model.ErrOutOfGas
} }
// 打印合约中生成的日志 // 打印合约中生成的日志
...@@ -96,10 +97,10 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt, ...@@ -96,10 +97,10 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
return nil, nil return nil, nil
} }
// 从状态机中获取数据变更和变更日志 // 从状态机中获取数据变更和变更日志
data, logs := evm.mStateDB.GetChangedData(curVer.GetId()) data, logs := evm.mStateDB.GetChangedData(curVer.GetID())
contractReceipt := &evmtypes.ReceiptEVMContract{Caller: msg.From().String(), ContractName: execName, ContractAddr: contractAddr.String(), UsedGas: usedGas, Ret: ret} contractReceipt := &evmtypes.ReceiptEVMContract{Caller: msg.From().String(), ContractName: execName, ContractAddr: contractAddr.String(), UsedGas: usedGas, Ret: ret}
logs = append(logs, &types.ReceiptLog{evmtypes.TyLogCallContract, types.Encode(contractReceipt)}) logs = append(logs, &types.ReceiptLog{Ty: evmtypes.TyLogCallContract, Log: types.Encode(contractReceipt)})
logs = append(logs, evm.mStateDB.GetReceiptLogs(contractAddr.String())...) logs = append(logs, evm.mStateDB.GetReceiptLogs(contractAddr.String())...)
if types.IsDappFork(evm.GetHeight(), "evm", "ForkEVMKVHash") { if types.IsDappFork(evm.GetHeight(), "evm", "ForkEVMKVHash") {
...@@ -124,13 +125,14 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt, ...@@ -124,13 +125,14 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
return receipt, nil return receipt, nil
} }
// CheckInit 检查是否初始化数据库
func (evm *EVMExecutor) CheckInit() { func (evm *EVMExecutor) CheckInit() {
if evm.mStateDB == nil { if evm.mStateDB == nil {
evm.mStateDB = state.NewMemoryStateDB(evm.GetStateDB(), evm.GetLocalDB(), evm.GetCoinsAccount(), evm.GetHeight()) evm.mStateDB = state.NewMemoryStateDB(evm.GetStateDB(), evm.GetLocalDB(), evm.GetCoinsAccount(), evm.GetHeight())
} }
} }
// 目前的交易中,如果是coins交易,金额是放在payload的,但是合约不行,需要修改Transaction结构 // GetMessage 目前的交易中,如果是coins交易,金额是放在payload的,但是合约不行,需要修改Transaction结构
func (evm *EVMExecutor) GetMessage(tx *types.Transaction) (msg *common.Message, err error) { func (evm *EVMExecutor) GetMessage(tx *types.Transaction) (msg *common.Message, err error) {
var action evmtypes.EVMContractAction var action evmtypes.EVMContractAction
err = types.Decode(tx.Payload, &action) err = types.Decode(tx.Payload, &action)
...@@ -189,7 +191,7 @@ func (evm *EVMExecutor) calcKVHash(addr common.Address, logs []*types.ReceiptLog ...@@ -189,7 +191,7 @@ func (evm *EVMExecutor) calcKVHash(addr common.Address, logs []*types.ReceiptLog
if len(hashes) > 0 { if len(hashes) > 0 {
hash := common.ToHash(hashes) hash := common.ToHash(hashes)
return &types.KeyValue{getDataHashKey(addr), hash.Bytes()} return &types.KeyValue{Key: getDataHashKey(addr), Value: hash.Bytes()}
} }
return nil return nil
} }
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types" evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
) )
// ExecDelLocal 处理区块回滚
func (evm *EVMExecutor) ExecDelLocal(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (evm *EVMExecutor) ExecDelLocal(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
set, err := evm.DriverBase.ExecDelLocal(tx, receipt, index) set, err := evm.DriverBase.ExecDelLocal(tx, receipt, index)
if err != nil { if err != nil {
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types" evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
) )
// ExecLocal 处理本地区块新增逻辑
func (evm *EVMExecutor) ExecLocal(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (evm *EVMExecutor) ExecLocal(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
set, err := evm.DriverBase.ExecLocal(tx, receipt, index) set, err := evm.DriverBase.ExecLocal(tx, receipt, index)
if err != nil { if err != nil {
......
...@@ -12,22 +12,22 @@ import ( ...@@ -12,22 +12,22 @@ import (
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/state" "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/state"
) )
// 检查合约调用账户是否有充足的金额进行转账交易操作 // CanTransfer 检查合约调用账户是否有充足的金额进行转账交易操作
func CanTransfer(db state.StateDB, sender, recipient common.Address, amount uint64) bool { func CanTransfer(db state.EVMStateDB, sender, recipient common.Address, amount uint64) bool {
return db.CanTransfer(sender.String(), recipient.String(), amount) return db.CanTransfer(sender.String(), recipient.String(), amount)
} }
// 在内存数据库中执行转账操作(只修改内存中的金额) // Transfer 在内存数据库中执行转账操作(只修改内存中的金额)
// 从外部账户地址到合约账户地址 // 从外部账户地址到合约账户地址
func Transfer(db state.StateDB, sender, recipient common.Address, amount uint64) bool { func Transfer(db state.EVMStateDB, sender, recipient common.Address, amount uint64) bool {
return db.Transfer(sender.String(), recipient.String(), amount) return db.Transfer(sender.String(), recipient.String(), amount)
} }
// 获取制定高度区块的哈希 // GetHashFn 获取制定高度区块的哈希
func GetHashFn(api client.QueueProtocolAPI) func(blockHeight uint64) common.Hash { func GetHashFn(api client.QueueProtocolAPI) func(blockHeight uint64) common.Hash {
return func(blockHeight uint64) common.Hash { return func(blockHeight uint64) common.Hash {
if api != nil { if api != nil {
reply, err := api.GetBlockHash(&types.ReqInt{int64(blockHeight)}) reply, err := api.GetBlockHash(&types.ReqInt{Height: int64(blockHeight)})
if nil != err { if nil != err {
log.Error("Call GetBlockHash Failed.", err) log.Error("Call GetBlockHash Failed.", err)
} }
......
...@@ -17,7 +17,7 @@ import ( ...@@ -17,7 +17,7 @@ import (
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types" evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
) )
// 检查合约地址是否存在,此操作不会改变任何状态,所以可以直接从statedb查询 // Query_CheckAddrExists 检查合约地址是否存在,此操作不会改变任何状态,所以可以直接从statedb查询
func (evm *EVMExecutor) Query_CheckAddrExists(in *evmtypes.CheckEVMAddrReq) (types.Message, error) { func (evm *EVMExecutor) Query_CheckAddrExists(in *evmtypes.CheckEVMAddrReq) (types.Message, error) {
evm.CheckInit() evm.CheckInit()
addrStr := in.Addr addrStr := in.Addr
...@@ -51,7 +51,7 @@ func (evm *EVMExecutor) Query_CheckAddrExists(in *evmtypes.CheckEVMAddrReq) (typ ...@@ -51,7 +51,7 @@ func (evm *EVMExecutor) Query_CheckAddrExists(in *evmtypes.CheckEVMAddrReq) (typ
return ret, nil return ret, nil
} }
// 此方法用来估算合约消耗的Gas,不能修改原有执行器的状态数据 // Query_EstimateGas 此方法用来估算合约消耗的Gas,不能修改原有执行器的状态数据
func (evm *EVMExecutor) Query_EstimateGas(in *evmtypes.EstimateEVMGasReq) (types.Message, error) { func (evm *EVMExecutor) Query_EstimateGas(in *evmtypes.EstimateEVMGasReq) (types.Message, error) {
evm.CheckInit() evm.CheckInit()
var ( var (
...@@ -80,9 +80,9 @@ func (evm *EVMExecutor) Query_EstimateGas(in *evmtypes.EstimateEVMGasReq) (types ...@@ -80,9 +80,9 @@ func (evm *EVMExecutor) Query_EstimateGas(in *evmtypes.EstimateEVMGasReq) (types
var ( var (
vmerr error vmerr error
leftOverGas = uint64(0) leftOverGas uint64
contractAddr common.Address contractAddr common.Address
execName = "estimateGas" execName string
) )
if isCreate { if isCreate {
...@@ -100,7 +100,7 @@ func (evm *EVMExecutor) Query_EstimateGas(in *evmtypes.EstimateEVMGasReq) (types ...@@ -100,7 +100,7 @@ func (evm *EVMExecutor) Query_EstimateGas(in *evmtypes.EstimateEVMGasReq) (types
return result, vmerr return result, vmerr
} }
// 此方法用来估算合约消耗的Gas,不能修改原有执行器的状态数据 // Query_EvmDebug 此方法用来估算合约消耗的Gas,不能修改原有执行器的状态数据
func (evm *EVMExecutor) Query_EvmDebug(in *evmtypes.EvmDebugReq) (types.Message, error) { func (evm *EVMExecutor) Query_EvmDebug(in *evmtypes.EvmDebugReq) (types.Message, error) {
evm.CheckInit() evm.CheckInit()
optype := in.Optype optype := in.Optype
......
...@@ -23,7 +23,7 @@ func TestCreateContract1(t *testing.T) { ...@@ -23,7 +23,7 @@ func TestCreateContract1(t *testing.T) {
gasLimit := gas gasLimit := gas
tx := createTx(privKey, deployCode, gas, 10000000) tx := createTx(privKey, deployCode, gas, 10000000)
mdb := buildStateDB(getAddr(privKey).String(), 500000000) mdb := buildStateDB(getAddr(privKey).String(), 500000000)
ret, addr, leftGas, err, statedb := createContract(mdb, tx, 0) ret, addr, leftGas, statedb, err := createContract(mdb, tx, 0)
test := NewTester(t) test := NewTester(t)
test.assertNil(err) test.assertNil(err)
...@@ -33,7 +33,7 @@ func TestCreateContract1(t *testing.T) { ...@@ -33,7 +33,7 @@ func TestCreateContract1(t *testing.T) {
test.assertNotEqualsI(common.Address(addr), common.EmptyAddress()) test.assertNotEqualsI(common.Address(addr), common.EmptyAddress())
// 检查返回数据是否正确 // 检查返回数据是否正确
test.assertEqualsV(statedb.GetLastSnapshot().GetId(), 0) test.assertEqualsV(statedb.GetLastSnapshot().GetID(), 0)
} }
// 创建合约gas不足 // 创建合约gas不足
...@@ -46,7 +46,7 @@ func TestCreateContract2(t *testing.T) { ...@@ -46,7 +46,7 @@ func TestCreateContract2(t *testing.T) {
gas := uint64(30) gas := uint64(30)
tx := createTx(privKey, deployCode, gas, 0) tx := createTx(privKey, deployCode, gas, 0)
mdb := buildStateDB(getAddr(privKey).String(), 100000000) mdb := buildStateDB(getAddr(privKey).String(), 100000000)
ret, _, leftGas, err, _ := createContract(mdb, tx, 0) ret, _, leftGas, _, err := createContract(mdb, tx, 0)
test := NewTester(t) test := NewTester(t)
...@@ -72,7 +72,7 @@ func TestCreateContract3(t *testing.T) { ...@@ -72,7 +72,7 @@ func TestCreateContract3(t *testing.T) {
gasLimit := gas gasLimit := gas
tx := createTx(privKey, deployCode, gas, 0) tx := createTx(privKey, deployCode, gas, 0)
mdb := buildStateDB(getAddr(privKey).String(), 100000000) mdb := buildStateDB(getAddr(privKey).String(), 100000000)
ret, _, leftGas, err, _ := createContract(mdb, tx, 0) ret, _, leftGas, _, err := createContract(mdb, tx, 0)
test := NewTester(t) test := NewTester(t)
...@@ -98,7 +98,7 @@ func TestCreateContract4(t *testing.T) { ...@@ -98,7 +98,7 @@ func TestCreateContract4(t *testing.T) {
gasLimit := gas gasLimit := gas
tx := createTx(privKey, deployCode, gas, 0) tx := createTx(privKey, deployCode, gas, 0)
mdb := buildStateDB(getAddr(privKey).String(), 100000000) mdb := buildStateDB(getAddr(privKey).String(), 100000000)
ret, _, leftGas, err, _ := createContract(mdb, tx, 50) ret, _, leftGas, _, err := createContract(mdb, tx, 50)
test := NewTester(t) test := NewTester(t)
......
...@@ -144,12 +144,11 @@ func runCase(tt *testing.T, c VMCase, file string) { ...@@ -144,12 +144,11 @@ func runCase(tt *testing.T, c VMCase, file string) {
// 合约执行出错的情况下,判断错误是否相同,如果相同,则返回,不判断post // 合约执行出错的情况下,判断错误是否相同,如果相同,则返回,不判断post
if len(c.err) > 0 && c.err == err.Error() { if len(c.err) > 0 && c.err == err.Error() {
return return
} else {
// 非意料情况下的出错,视为错误
tt.Errorf("test case:%s, failed:%s", c.name, err)
tt.Fail()
return
} }
// 非意料情况下的出错,视为错误
tt.Errorf("test case:%s, failed:%s", c.name, err)
tt.Fail()
return
} }
// 4 检查执行结果 post (注意,这里不检查Gas具体扣费数额,因为计费规则不一样,值检查执行结果是否正确) // 4 检查执行结果 post (注意,这里不检查Gas具体扣费数额,因为计费规则不一样,值检查执行结果是否正确)
t := NewTester(tt) t := NewTester(tt)
......
...@@ -79,11 +79,11 @@ func scanTestData(basePath string) { ...@@ -79,11 +79,11 @@ func scanTestData(basePath string) {
// 检查两个文件是否都存在 // 检查两个文件是否都存在
if _, err := os.Stat(keyFile); os.IsNotExist(err) { if _, err := os.Stat(keyFile); os.IsNotExist(err) {
fmt.Errorf("test template file:%s, not exists!", keyFile) fmt.Println(fmt.Errorf("test template file:%s, not exists", keyFile))
return nil return nil
} }
if _, err := os.Stat(dataFile); os.IsNotExist(err) { if _, err := os.Stat(dataFile); os.IsNotExist(err) {
fmt.Errorf("test data file:%s, not exists!", dataFile) fmt.Println(fmt.Errorf("test data file:%s, not exists", dataFile))
return nil return nil
} }
testmap[keyFile] = dataFile testmap[keyFile] = dataFile
......
...@@ -4,19 +4,21 @@ ...@@ -4,19 +4,21 @@
package tests package tests
// VMCase 一个测试用例
type VMCase struct { type VMCase struct {
name string name string
env EnvJson env EnvJSON
exec ExecJson exec ExecJSON
gas int64 gas int64
logs string logs string
out string out string
err string err string
pre map[string]AccountJson pre map[string]AccountJSON
post map[string]AccountJson post map[string]AccountJSON
} }
type EnvJson struct { // EnvJSON 上下文信息
type EnvJSON struct {
currentCoinbase string currentCoinbase string
currentDifficulty int64 currentDifficulty int64
currentGasLimit int64 currentGasLimit int64
...@@ -24,7 +26,8 @@ type EnvJson struct { ...@@ -24,7 +26,8 @@ type EnvJson struct {
currentTimestamp int64 currentTimestamp int64
} }
type ExecJson struct { // ExecJSON 调用信息
type ExecJSON struct {
address string address string
caller string caller string
code string code string
...@@ -35,7 +38,8 @@ type ExecJson struct { ...@@ -35,7 +38,8 @@ type ExecJson struct {
value int64 value int64
} }
type AccountJson struct { // AccountJSON 账户信息
type AccountJSON struct {
balance int64 balance int64
code string code string
nonce int64 nonce int64
......
...@@ -10,10 +10,12 @@ import ( ...@@ -10,10 +10,12 @@ import (
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common" "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
) )
// Tester 测试执行对象
type Tester struct { type Tester struct {
t *testing.T t *testing.T
} }
// NewTester 新创建测试执行对象
func NewTester(t *testing.T) *Tester { func NewTester(t *testing.T) *Tester {
return &Tester{t: t} return &Tester{t: t}
} }
......
...@@ -68,9 +68,9 @@ func parseVMCase(data interface{}, ut *VMCase) { ...@@ -68,9 +68,9 @@ func parseVMCase(data interface{}, ut *VMCase) {
} }
} }
func parseEnv(data interface{}) EnvJson { func parseEnv(data interface{}) EnvJSON {
m := data.(map[string]interface{}) m := data.(map[string]interface{})
ut := EnvJson{} ut := EnvJSON{}
for k, v := range m { for k, v := range m {
switch k { switch k {
case "currentCoinbase": case "currentCoinbase":
...@@ -90,9 +90,9 @@ func parseEnv(data interface{}) EnvJson { ...@@ -90,9 +90,9 @@ func parseEnv(data interface{}) EnvJson {
return ut return ut
} }
func parseExec(data interface{}) ExecJson { func parseExec(data interface{}) ExecJSON {
m := data.(map[string]interface{}) m := data.(map[string]interface{})
ut := ExecJson{} ut := ExecJSON{}
for k, v := range m { for k, v := range m {
switch k { switch k {
case "address": case "address":
...@@ -118,8 +118,8 @@ func parseExec(data interface{}) ExecJson { ...@@ -118,8 +118,8 @@ func parseExec(data interface{}) ExecJson {
return ut return ut
} }
func parseAccount(data interface{}) map[string]AccountJson { func parseAccount(data interface{}) map[string]AccountJSON {
ret := make(map[string]AccountJson) ret := make(map[string]AccountJSON)
m := data.(map[string]interface{}) m := data.(map[string]interface{})
for k, v := range m { for k, v := range m {
ret[unpre(k)] = parseAccount2(v) ret[unpre(k)] = parseAccount2(v)
...@@ -127,9 +127,9 @@ func parseAccount(data interface{}) map[string]AccountJson { ...@@ -127,9 +127,9 @@ func parseAccount(data interface{}) map[string]AccountJson {
return ret return ret
} }
func parseAccount2(data interface{}) AccountJson { func parseAccount2(data interface{}) AccountJSON {
m := data.(map[string]interface{}) m := data.(map[string]interface{})
ut := AccountJson{} ut := AccountJSON{}
for k, v := range m { for k, v := range m {
switch k { switch k {
case "balance": case "balance":
...@@ -215,7 +215,7 @@ func addAccount(mdb *db.GoMemDB, execAddr string, acc1 *types.Account) { ...@@ -215,7 +215,7 @@ func addAccount(mdb *db.GoMemDB, execAddr string, acc1 *types.Account) {
} }
} }
func addContractAccount(db *state.MemoryStateDB, mdb *db.GoMemDB, addr string, a AccountJson, creator string) { func addContractAccount(db *state.MemoryStateDB, mdb *db.GoMemDB, addr string, a AccountJSON, creator string) {
acc := state.NewContractAccount(addr, db) acc := state.NewContractAccount(addr, db)
acc.SetCreator(creator) acc.SetCreator(creator)
code, err := hex.DecodeString(a.code) code, err := hex.DecodeString(a.code)
...@@ -247,7 +247,7 @@ func buildStateDB(addr string, balance int64) *db.GoMemDB { ...@@ -247,7 +247,7 @@ func buildStateDB(addr string, balance int64) *db.GoMemDB {
return mdb return mdb
} }
func createContract(mdb *db.GoMemDB, tx types.Transaction, maxCodeSize int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error, statedb *state.MemoryStateDB) { func createContract(mdb *db.GoMemDB, tx types.Transaction, maxCodeSize int) (ret []byte, contractAddr common.Address, leftOverGas uint64, statedb *state.MemoryStateDB, err error) {
inst := evm.NewEVMExecutor() inst := evm.NewEVMExecutor()
inst.CheckInit() inst.CheckInit()
msg, _ := inst.GetMessage(&tx) msg, _ := inst.GetMessage(&tx)
...@@ -273,5 +273,5 @@ func createContract(mdb *db.GoMemDB, tx types.Transaction, maxCodeSize int) (ret ...@@ -273,5 +273,5 @@ func createContract(mdb *db.GoMemDB, tx types.Transaction, maxCodeSize int) (ret
addr := *crypto2.RandomContractAddress() addr := *crypto2.RandomContractAddress()
ret, _, leftGas, err := env.Create(runtime.AccountRef(msg.From()), addr, msg.Data(), msg.GasLimit(), fmt.Sprintf("%s%s", evmtypes.EvmPrefix, common.BytesToHash(tx.Hash()).Hex()), "") ret, _, leftGas, err := env.Create(runtime.AccountRef(msg.From()), addr, msg.Data(), msg.GasLimit(), fmt.Sprintf("%s%s", evmtypes.EvmPrefix, common.BytesToHash(tx.Hash()).Hex()), "")
return ret, addr, leftGas, err, statedb return ret, addr, leftGas, statedb, err
} }
...@@ -13,37 +13,43 @@ import ( ...@@ -13,37 +13,43 @@ import (
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types" evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
) )
// 封装地址结构体,并提供各种常用操作封装 // Address 封装地址结构体,并提供各种常用操作封装
// 这里封装的操作主要是为了提供Address<->big.Int, Address<->[]byte 之间的互相转换 // 这里封装的操作主要是为了提供Address<->big.Int, Address<->[]byte 之间的互相转换
// 并且转换的核心是使用地址对象中的Hash160元素,因为在EVM中地址固定为[20]byte,超出此范围的地址无法正确解释执行 // 并且转换的核心是使用地址对象中的Hash160元素,因为在EVM中地址固定为[20]byte,超出此范围的地址无法正确解释执行
type Address struct { type Address struct {
addr *address.Address addr *address.Address
} }
// String 字符串结构
func (a Address) String() string { return a.addr.String() } func (a Address) String() string { return a.addr.String() }
// Bytes 字节数组
func (a Address) Bytes() []byte { func (a Address) Bytes() []byte {
return a.addr.Hash160[:] return a.addr.Hash160[:]
} }
// Big 大数字
func (a Address) Big() *big.Int { func (a Address) Big() *big.Int {
ret := new(big.Int).SetBytes(a.Bytes()) ret := new(big.Int).SetBytes(a.Bytes())
return ret return ret
} }
// txHash生成EVM合约地址 // NewAddress xHash生成EVM合约地址
func NewAddress(txHash []byte) Address { func NewAddress(txHash []byte) Address {
execAddr := address.GetExecAddress(types.ExecName(evmtypes.EvmPrefix) + BytesToHash(txHash).Hex()) execAddr := address.GetExecAddress(types.ExecName(evmtypes.EvmPrefix) + BytesToHash(txHash).Hex())
return Address{addr: execAddr} return Address{addr: execAddr}
} }
// ExecAddress 返回合约地址
func ExecAddress(execName string) Address { func ExecAddress(execName string) Address {
execAddr := address.GetExecAddress(execName) execAddr := address.GetExecAddress(execName)
return Address{addr: execAddr} return Address{addr: execAddr}
} }
// Hash 计算地址哈希
func (a Address) Hash() Hash { return ToHash(a.Bytes()) } func (a Address) Hash() Hash { return ToHash(a.Bytes()) }
// BytesToAddress 字节向地址转换
func BytesToAddress(b []byte) Address { func BytesToAddress(b []byte) Address {
a := new(address.Address) a := new(address.Address)
a.Version = 0 a.Version = 0
...@@ -51,6 +57,7 @@ func BytesToAddress(b []byte) Address { ...@@ -51,6 +57,7 @@ func BytesToAddress(b []byte) Address {
return Address{addr: a} return Address{addr: a}
} }
// StringToAddress 字符串转换为地址
func StringToAddress(s string) *Address { func StringToAddress(s string) *Address {
addr, err := address.NewAddrFromString(s) addr, err := address.NewAddrFromString(s)
if err != nil { if err != nil {
...@@ -70,6 +77,7 @@ func bigBytes(b *big.Int) (out [20]byte) { ...@@ -70,6 +77,7 @@ func bigBytes(b *big.Int) (out [20]byte) {
return return
} }
// BigToAddress 大数字转换为地址
func BigToAddress(b *big.Int) Address { func BigToAddress(b *big.Int) Address {
a := new(address.Address) a := new(address.Address)
a.Version = 0 a.Version = 0
...@@ -77,4 +85,5 @@ func BigToAddress(b *big.Int) Address { ...@@ -77,4 +85,5 @@ func BigToAddress(b *big.Int) Address {
return Address{addr: a} return Address{addr: a}
} }
// EmptyAddress 返回空地址
func EmptyAddress() Address { return BytesToAddress([]byte{0}) } func EmptyAddress() Address { return BytesToAddress([]byte{0}) }
...@@ -11,28 +11,34 @@ import ( ...@@ -11,28 +11,34 @@ import (
// 常用的大整数常量定义 // 常用的大整数常量定义
var ( var (
Big0 = big.NewInt(0) // Big0 大数字0
Big1 = big.NewInt(1) Big0 = big.NewInt(0)
Big32 = big.NewInt(32) // Big1 大数字1
Big1 = big.NewInt(1)
// Big32 大数字32
Big32 = big.NewInt(32)
// Big256 大数字256
Big256 = big.NewInt(256) Big256 = big.NewInt(256)
// Big257 大数字257
Big257 = big.NewInt(257) Big257 = big.NewInt(257)
) )
// 2的各种常用取幂结果 // 2的各种常用取幂结果
var ( var (
// TT255 2的255次幂
TT255 = BigPow(2, 255) TT255 = BigPow(2, 255)
tt256 = BigPow(2, 256) tt256 = BigPow(2, 256)
tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1)) tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1))
) )
const ( const (
// 一个big.Word类型取值占用多少个位 // WordBits 一个big.Word类型取值占用多少个位
WordBits = 32 << (uint64(^big.Word(0)) >> 63) WordBits = 32 << (uint64(^big.Word(0)) >> 63)
// 一个big.Word类型取值占用多少个字节 // WordBytes 一个big.Word类型取值占用多少个字节
WordBytes = WordBits / 8 WordBytes = WordBits / 8
) )
// 返回两者之中的较大值 // BigMax 返回两者之中的较大值
func BigMax(x, y *big.Int) *big.Int { func BigMax(x, y *big.Int) *big.Int {
if x.Cmp(y) < 0 { if x.Cmp(y) < 0 {
return y return y
...@@ -40,7 +46,7 @@ func BigMax(x, y *big.Int) *big.Int { ...@@ -40,7 +46,7 @@ func BigMax(x, y *big.Int) *big.Int {
return x return x
} }
// 返回两者之中的较小值 // BigMin 返回两者之中的较小值
func BigMin(x, y *big.Int) *big.Int { func BigMin(x, y *big.Int) *big.Int {
if x.Cmp(y) > 0 { if x.Cmp(y) > 0 {
return y return y
...@@ -48,13 +54,13 @@ func BigMin(x, y *big.Int) *big.Int { ...@@ -48,13 +54,13 @@ func BigMin(x, y *big.Int) *big.Int {
return x return x
} }
// 返回a的b次幂 // BigPow 返回a的b次幂
func BigPow(a, b int64) *big.Int { func BigPow(a, b int64) *big.Int {
r := big.NewInt(a) r := big.NewInt(a)
return r.Exp(r, big.NewInt(b), nil) return r.Exp(r, big.NewInt(b), nil)
} }
// 求补 // U256 求补
func U256(x *big.Int) *big.Int { func U256(x *big.Int) *big.Int {
return x.And(x, tt256m1) return x.And(x, tt256m1)
} }
...@@ -68,12 +74,11 @@ func U256(x *big.Int) *big.Int { ...@@ -68,12 +74,11 @@ func U256(x *big.Int) *big.Int {
func S256(x *big.Int) *big.Int { func S256(x *big.Int) *big.Int {
if x.Cmp(TT255) < 0 { if x.Cmp(TT255) < 0 {
return x return x
} else {
return new(big.Int).Sub(x, tt256)
} }
return new(big.Int).Sub(x, tt256)
} }
// 指数函数,可以指定底数,结果被截断为256位长度 // Exp 指数函数,可以指定底数,结果被截断为256位长度
func Exp(base, exponent *big.Int) *big.Int { func Exp(base, exponent *big.Int) *big.Int {
result := big.NewInt(1) result := big.NewInt(1)
...@@ -89,7 +94,7 @@ func Exp(base, exponent *big.Int) *big.Int { ...@@ -89,7 +94,7 @@ func Exp(base, exponent *big.Int) *big.Int {
return result return result
} }
// big.Int以小端编码时,第n个位置的字节取值 // Byte big.Int以小端编码时,第n个位置的字节取值
// 例如: bigint '5', padlength 32, n=31 => 5 // 例如: bigint '5', padlength 32, n=31 => 5
func Byte(bigint *big.Int, padlength, n int) byte { func Byte(bigint *big.Int, padlength, n int) byte {
if n >= padlength { if n >= padlength {
...@@ -117,17 +122,7 @@ func bigEndianByteAt(bigint *big.Int, n int) byte { ...@@ -117,17 +122,7 @@ func bigEndianByteAt(bigint *big.Int, n int) byte {
return byte(word >> shift) return byte(word >> shift)
} }
// 以大端方式将big.Int编码为字节数组,结果数组长度为n // ReadBits 以大端方式将big.Int编码为字节数组
func PaddedBigBytes(bigint *big.Int, n int) []byte {
if bigint.BitLen()/8 >= n {
return bigint.Bytes()
}
ret := make([]byte, n)
ReadBits(bigint, ret)
return ret
}
// 以大端方式将big.Int编码为字节数组
func ReadBits(bigint *big.Int, buf []byte) { func ReadBits(bigint *big.Int, buf []byte) {
i := len(buf) i := len(buf)
for _, d := range bigint.Bits() { for _, d := range bigint.Bits() {
...@@ -139,17 +134,12 @@ func ReadBits(bigint *big.Int, buf []byte) { ...@@ -139,17 +134,12 @@ func ReadBits(bigint *big.Int, buf []byte) {
} }
} }
// 减法运算,返回是否溢出 // SafeAdd 加法运算,返回是否溢出
func SafeSub(x, y uint64) (uint64, bool) {
return x - y, x < y
}
// 加法运算,返回是否溢出
func SafeAdd(x, y uint64) (uint64, bool) { func SafeAdd(x, y uint64) (uint64, bool) {
return x + y, y > math.MaxUint64-x return x + y, y > math.MaxUint64-x
} }
// 乘法运算,返回是否溢出 // SafeMul 乘法运算,返回是否溢出
func SafeMul(x, y uint64) (uint64, bool) { func SafeMul(x, y uint64) (uint64, bool) {
if x == 0 || y == 0 { if x == 0 || y == 0 {
return 0, false return 0, false
...@@ -157,6 +147,7 @@ func SafeMul(x, y uint64) (uint64, bool) { ...@@ -157,6 +147,7 @@ func SafeMul(x, y uint64) (uint64, bool) {
return x * y, y > math.MaxUint64/x return x * y, y > math.MaxUint64/x
} }
// Zero 检查数字是否为0
func Zero(value *big.Int) bool { func Zero(value *big.Int) bool {
if value == nil || value.Sign() == 0 { if value == nil || value.Sign() == 0 {
return true return true
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"sort" "sort"
) )
// 右填充字节数组 // RightPadBytes 右填充字节数组
func RightPadBytes(slice []byte, l int) []byte { func RightPadBytes(slice []byte, l int) []byte {
if l <= len(slice) { if l <= len(slice) {
return slice return slice
...@@ -21,7 +21,7 @@ func RightPadBytes(slice []byte, l int) []byte { ...@@ -21,7 +21,7 @@ func RightPadBytes(slice []byte, l int) []byte {
return padded return padded
} }
// 左填充字节数组 // LeftPadBytes 左填充字节数组
func LeftPadBytes(slice []byte, l int) []byte { func LeftPadBytes(slice []byte, l int) []byte {
if l <= len(slice) { if l <= len(slice) {
return slice return slice
...@@ -33,7 +33,7 @@ func LeftPadBytes(slice []byte, l int) []byte { ...@@ -33,7 +33,7 @@ func LeftPadBytes(slice []byte, l int) []byte {
return padded return padded
} }
// 十六进制的字符串转换为字节数组 // FromHex 十六进制的字符串转换为字节数组
func FromHex(s string) []byte { func FromHex(s string) []byte {
if len(s) > 1 { if len(s) > 1 {
if s[0:2] == "0x" || s[0:2] == "0X" { if s[0:2] == "0x" || s[0:2] == "0X" {
...@@ -46,13 +46,13 @@ func FromHex(s string) []byte { ...@@ -46,13 +46,13 @@ func FromHex(s string) []byte {
return Hex2Bytes(s) return Hex2Bytes(s)
} }
// 十六进制字符串转换为字节数组 // Hex2Bytes 十六进制字符串转换为字节数组
func Hex2Bytes(str string) []byte { func Hex2Bytes(str string) []byte {
h, _ := hex.DecodeString(str) h, _ := hex.DecodeString(str)
return h return h
} }
// 将字节数组转换为16进制的字符串表示 // Bytes2Hex 将字节数组转换为16进制的字符串表示
func Bytes2Hex(b []byte) string { func Bytes2Hex(b []byte) string {
enc := make([]byte, len(b)*2+2) enc := make([]byte, len(b)*2+2)
copy(enc, "0x") copy(enc, "0x")
...@@ -60,7 +60,7 @@ func Bytes2Hex(b []byte) string { ...@@ -60,7 +60,7 @@ func Bytes2Hex(b []byte) string {
return string(enc) return string(enc)
} }
// 将字节数组转换为16进制的字符串表示 // Bytes2HexTrim 将字节数组转换为16进制的字符串表示
// 并且将前面多余的0去除 // 并且将前面多余的0去除
func Bytes2HexTrim(b []byte) string { func Bytes2HexTrim(b []byte) string {
// 获取字节数组中第一个非零字节位置 // 获取字节数组中第一个非零字节位置
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"math/big" "math/big"
) )
// 返回从开始位置制定长度的数据 // GetData 返回从开始位置制定长度的数据
// 如果源数据不足,则剩余位置用零填充 // 如果源数据不足,则剩余位置用零填充
func GetData(data []byte, start uint64, size uint64) []byte { func GetData(data []byte, start uint64, size uint64) []byte {
length := uint64(len(data)) length := uint64(len(data))
...@@ -23,7 +23,7 @@ func GetData(data []byte, start uint64, size uint64) []byte { ...@@ -23,7 +23,7 @@ func GetData(data []byte, start uint64, size uint64) []byte {
return RightPadBytes(data[start:end], int(size)) return RightPadBytes(data[start:end], int(size))
} }
// 返回从开始位置制定长度的数据 // GetDataBig 返回从开始位置制定长度的数据
// 如果源数据不足,则剩余位置用零填充 // 如果源数据不足,则剩余位置用零填充
func GetDataBig(data []byte, start *big.Int, size *big.Int) []byte { func GetDataBig(data []byte, start *big.Int, size *big.Int) []byte {
dlen := big.NewInt(int64(len(data))) dlen := big.NewInt(int64(len(data)))
...@@ -33,12 +33,12 @@ func GetDataBig(data []byte, start *big.Int, size *big.Int) []byte { ...@@ -33,12 +33,12 @@ func GetDataBig(data []byte, start *big.Int, size *big.Int) []byte {
return RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64())) return RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64()))
} }
// 将大整数转换为uint64,并判断是否溢出 // BigUint64 将大整数转换为uint64,并判断是否溢出
func BigUint64(v *big.Int) (uint64, bool) { func BigUint64(v *big.Int) (uint64, bool) {
return v.Uint64(), v.BitLen() > 64 return v.Uint64(), v.BitLen() > 64
} }
// 计算制定字节长度所对应的字长度(一个字,对应32个字节,也就是256位) // ToWordSize 计算制定字节长度所对应的字长度(一个字,对应32个字节,也就是256位)
// 如果长度不足一个字长,则补足 // 如果长度不足一个字长,则补足
// EVM在内存中存储时的最小单位是字长(256位),而不是字节 // EVM在内存中存储时的最小单位是字长(256位),而不是字节
func ToWordSize(size uint64) uint64 { func ToWordSize(size uint64) uint64 {
...@@ -49,7 +49,7 @@ func ToWordSize(size uint64) uint64 { ...@@ -49,7 +49,7 @@ func ToWordSize(size uint64) uint64 {
return (size + 31) / 32 return (size + 31) / 32
} }
// 判断字节数组内容是否全为零 // AllZero 判断字节数组内容是否全为零
func AllZero(b []byte) bool { func AllZero(b []byte) bool {
for _, byte := range b { for _, byte := range b {
if byte != 0 { if byte != 0 {
......
...@@ -20,7 +20,7 @@ func bigFromBase10(s string) *big.Int { ...@@ -20,7 +20,7 @@ func bigFromBase10(s string) *big.Int {
// u is the BN parameter that determines the prime: 1868033³. // u is the BN parameter that determines the prime: 1868033³.
var u = bigFromBase10("4965661367192848881") var u = bigFromBase10("4965661367192848881")
// p is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1. // P is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1.
var P = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583") var P = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583")
// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1. // Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1.
......
...@@ -190,14 +190,14 @@ func (c *curvePoint) Double(a *curvePoint, pool *bnPool) { ...@@ -190,14 +190,14 @@ func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
A.Mod(A, P) A.Mod(A, P)
B := pool.Get().Mul(a.y, a.y) B := pool.Get().Mul(a.y, a.y)
B.Mod(B, P) B.Mod(B, P)
C_ := pool.Get().Mul(B, B) C := pool.Get().Mul(B, B)
C_.Mod(C_, P) C.Mod(C, P)
t := pool.Get().Add(a.x, B) t := pool.Get().Add(a.x, B)
t2 := pool.Get().Mul(t, t) t2 := pool.Get().Mul(t, t)
t2.Mod(t2, P) t2.Mod(t2, P)
t.Sub(t2, A) t.Sub(t2, A)
t2.Sub(t, C_) t2.Sub(t, C)
d := pool.Get().Add(t2, t2) d := pool.Get().Add(t2, t2)
t.Add(A, A) t.Add(A, A)
e := pool.Get().Add(t, A) e := pool.Get().Add(t, A)
...@@ -207,7 +207,7 @@ func (c *curvePoint) Double(a *curvePoint, pool *bnPool) { ...@@ -207,7 +207,7 @@ func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
t.Add(d, d) t.Add(d, d)
c.x.Sub(f, t) c.x.Sub(f, t)
t.Add(C_, C_) t.Add(C, C)
t2.Add(t, t) t2.Add(t, t)
t.Add(t2, t2) t.Add(t2, t2)
c.y.Sub(d, c.x) c.y.Sub(d, c.x)
...@@ -221,7 +221,7 @@ func (c *curvePoint) Double(a *curvePoint, pool *bnPool) { ...@@ -221,7 +221,7 @@ func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
pool.Put(A) pool.Put(A)
pool.Put(B) pool.Put(B)
pool.Put(C_) pool.Put(C)
pool.Put(t) pool.Put(t)
pool.Put(t2) pool.Put(t2)
pool.Put(d) pool.Put(d)
......
...@@ -134,7 +134,7 @@ func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 { ...@@ -134,7 +134,7 @@ func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 {
return e return e
} }
func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 { func (e *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 {
sum := newGFp12(pool) sum := newGFp12(pool)
sum.SetOne() sum.SetOne()
t := newGFp12(pool) t := newGFp12(pool)
...@@ -148,12 +148,12 @@ func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 { ...@@ -148,12 +148,12 @@ func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 {
} }
} }
c.Set(sum) e.Set(sum)
sum.Put(pool) sum.Put(pool)
t.Put(pool) t.Put(pool)
return c return e
} }
func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 { func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 {
......
...@@ -106,7 +106,7 @@ func (e *gfP2) Double(a *gfP2) *gfP2 { ...@@ -106,7 +106,7 @@ func (e *gfP2) Double(a *gfP2) *gfP2 {
return e return e
} }
func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 { func (e *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 {
sum := newGFp2(pool) sum := newGFp2(pool)
sum.SetOne() sum.SetOne()
t := newGFp2(pool) t := newGFp2(pool)
...@@ -120,12 +120,12 @@ func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 { ...@@ -120,12 +120,12 @@ func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 {
} }
} }
c.Set(sum) e.Set(sum)
sum.Put(pool) sum.Put(pool)
t.Put(pool) t.Put(pool)
return c return e
} }
// See "Multiplication and Squaring in Pairing-Friendly Fields", // See "Multiplication and Squaring in Pairing-Friendly Fields",
......
...@@ -270,13 +270,13 @@ func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 { ...@@ -270,13 +270,13 @@ func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 {
t1.Mul(a.y, a.z, pool) t1.Mul(a.y, a.z, pool)
B.Sub(B, t1) B.Sub(B, t1)
C_ := newGFp2(pool) C := newGFp2(pool)
C_.Square(a.y, pool) C.Square(a.y, pool)
t1.Mul(a.x, a.z, pool) t1.Mul(a.x, a.z, pool)
C_.Sub(C_, t1) C.Sub(C, t1)
F := newGFp2(pool) F := newGFp2(pool)
F.Mul(C_, a.y, pool) F.Mul(C, a.y, pool)
F.MulXi(F, pool) F.MulXi(F, pool)
t1.Mul(A, a.z, pool) t1.Mul(A, a.z, pool)
F.Add(F, t1) F.Add(F, t1)
...@@ -286,14 +286,14 @@ func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 { ...@@ -286,14 +286,14 @@ func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 {
F.Invert(F, pool) F.Invert(F, pool)
e.x.Mul(C_, F, pool) e.x.Mul(C, F, pool)
e.y.Mul(B, F, pool) e.y.Mul(B, F, pool)
e.z.Mul(A, F, pool) e.z.Mul(A, F, pool)
t1.Put(pool) t1.Put(pool)
A.Put(pool) A.Put(pool)
B.Put(pool) B.Put(pool)
C_.Put(pool) C.Put(pool)
F.Put(pool) F.Put(pool)
return e return e
......
...@@ -92,12 +92,12 @@ func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gf ...@@ -92,12 +92,12 @@ func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gf
A := newGFp2(pool).Square(r.x, pool) A := newGFp2(pool).Square(r.x, pool)
B := newGFp2(pool).Square(r.y, pool) B := newGFp2(pool).Square(r.y, pool)
C_ := newGFp2(pool).Square(B, pool) C := newGFp2(pool).Square(B, pool)
D := newGFp2(pool).Add(r.x, B) D := newGFp2(pool).Add(r.x, B)
D.Square(D, pool) D.Square(D, pool)
D.Sub(D, A) D.Sub(D, A)
D.Sub(D, C_) D.Sub(D, C)
D.Add(D, D) D.Add(D, D)
E := newGFp2(pool).Add(A, A) E := newGFp2(pool).Add(A, A)
...@@ -116,7 +116,7 @@ func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gf ...@@ -116,7 +116,7 @@ func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gf
rOut.y.Sub(D, rOut.x) rOut.y.Sub(D, rOut.x)
rOut.y.Mul(rOut.y, E, pool) rOut.y.Mul(rOut.y, E, pool)
t := newGFp2(pool).Add(C_, C_) t := newGFp2(pool).Add(C, C)
t.Add(t, t) t.Add(t, t)
t.Add(t, t) t.Add(t, t)
rOut.y.Sub(rOut.y, t) rOut.y.Sub(rOut.y, t)
...@@ -146,7 +146,7 @@ func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gf ...@@ -146,7 +146,7 @@ func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gf
A.Put(pool) A.Put(pool)
B.Put(pool) B.Put(pool)
C_.Put(pool) C.Put(pool)
D.Put(pool) D.Put(pool)
E.Put(pool) E.Put(pool)
G.Put(pool) G.Put(pool)
......
...@@ -175,12 +175,12 @@ func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { ...@@ -175,12 +175,12 @@ func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
A := newGFp2(pool).Square(a.x, pool) A := newGFp2(pool).Square(a.x, pool)
B := newGFp2(pool).Square(a.y, pool) B := newGFp2(pool).Square(a.y, pool)
C_ := newGFp2(pool).Square(B, pool) C := newGFp2(pool).Square(B, pool)
t := newGFp2(pool).Add(a.x, B) t := newGFp2(pool).Add(a.x, B)
t2 := newGFp2(pool).Square(t, pool) t2 := newGFp2(pool).Square(t, pool)
t.Sub(t2, A) t.Sub(t2, A)
t2.Sub(t, C_) t2.Sub(t, C)
d := newGFp2(pool).Add(t2, t2) d := newGFp2(pool).Add(t2, t2)
t.Add(A, A) t.Add(A, A)
e := newGFp2(pool).Add(t, A) e := newGFp2(pool).Add(t, A)
...@@ -189,7 +189,7 @@ func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { ...@@ -189,7 +189,7 @@ func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
t.Add(d, d) t.Add(d, d)
c.x.Sub(f, t) c.x.Sub(f, t)
t.Add(C_, C_) t.Add(C, C)
t2.Add(t, t) t2.Add(t, t)
t.Add(t2, t2) t.Add(t2, t2)
c.y.Sub(d, c.x) c.y.Sub(d, c.x)
...@@ -201,7 +201,7 @@ func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { ...@@ -201,7 +201,7 @@ func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
A.Put(pool) A.Put(pool)
B.Put(pool) B.Put(pool)
C_.Put(pool) C.Put(pool)
t.Put(pool) t.Put(pool)
t2.Put(pool) t2.Put(pool)
d.Put(pool) d.Put(pool)
......
...@@ -16,7 +16,7 @@ import ( ...@@ -16,7 +16,7 @@ import (
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
) )
// 校验签名信息是否正确 // ValidateSignatureValues 校验签名信息是否正确
func ValidateSignatureValues(r, s *big.Int) bool { func ValidateSignatureValues(r, s *big.Int) bool {
if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 { if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 {
return false return false
...@@ -24,7 +24,7 @@ func ValidateSignatureValues(r, s *big.Int) bool { ...@@ -24,7 +24,7 @@ func ValidateSignatureValues(r, s *big.Int) bool {
return true return true
} }
// 根据压缩消息和签名,返回未压缩的公钥信息 // Ecrecover 根据压缩消息和签名,返回未压缩的公钥信息
func Ecrecover(hash, sig []byte) ([]byte, error) { func Ecrecover(hash, sig []byte) ([]byte, error) {
pub, err := SigToPub(hash, sig) pub, err := SigToPub(hash, sig)
if err != nil { if err != nil {
...@@ -34,7 +34,7 @@ func Ecrecover(hash, sig []byte) ([]byte, error) { ...@@ -34,7 +34,7 @@ func Ecrecover(hash, sig []byte) ([]byte, error) {
return bytes, err return bytes, err
} }
// 根据签名返回公钥信息 // SigToPub 根据签名返回公钥信息
func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
btcsig := make([]byte, 65) btcsig := make([]byte, 65)
btcsig[0] = sig[64] + 27 btcsig[0] = sig[64] + 27
...@@ -44,7 +44,7 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { ...@@ -44,7 +44,7 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
return (*ecdsa.PublicKey)(pub), err return (*ecdsa.PublicKey)(pub), err
} }
// 随机生成一个新的地址,给新创建的合约地址使用 // RandomContractAddress 随机生成一个新的地址,给新创建的合约地址使用
func RandomContractAddress() *common.Address { func RandomContractAddress() *common.Address {
c, err := crypto.New(types.GetSignName("", types.SECP256K1)) c, err := crypto.New(types.GetSignName("", types.SECP256K1))
if err != nil { if err != nil {
......
...@@ -11,17 +11,26 @@ import ( ...@@ -11,17 +11,26 @@ import (
) )
const ( const (
// HashLength 哈希长度
HashLength = 32 HashLength = 32
) )
// Hash 重定义哈希类型
type Hash common.Hash type Hash common.Hash
func (h Hash) Str() string { return string(h[:]) } // Str 字符串形式
func (h Hash) Str() string { return string(h[:]) }
// Bytes 二进制形式
func (h Hash) Bytes() []byte { return h[:] } func (h Hash) Bytes() []byte { return h[:] }
// Big 大数字形式
func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) }
func (h Hash) Hex() string { return Bytes2Hex(h[:]) }
// 设置哈希中的字节值,如果字节数组长度超过哈希长度,则被截断,只保留后面的部分 // Hex 十六进制形式
func (h Hash) Hex() string { return Bytes2Hex(h[:]) }
// SetBytes 设置哈希中的字节值,如果字节数组长度超过哈希长度,则被截断,只保留后面的部分
func (h *Hash) SetBytes(b []byte) { func (h *Hash) SetBytes(b []byte) {
if len(b) > len(h) { if len(b) > len(h) {
b = b[len(b)-HashLength:] b = b[len(b)-HashLength:]
...@@ -30,20 +39,17 @@ func (h *Hash) SetBytes(b []byte) { ...@@ -30,20 +39,17 @@ func (h *Hash) SetBytes(b []byte) {
copy(h[HashLength-len(b):], b) copy(h[HashLength-len(b):], b)
} }
// BigToHash 大数字转换为哈希
func BigToHash(b *big.Int) Hash { func BigToHash(b *big.Int) Hash {
return Hash(common.BigToHash(b)) return Hash(common.BigToHash(b))
} }
// 将[]byte直接当做哈希处理 // BytesToHash 将[]byte直接当做哈希处理
func BytesToHash(b []byte) Hash { func BytesToHash(b []byte) Hash {
return Hash(common.BytesToHash(b)) return Hash(common.BytesToHash(b))
} }
func EmptyHash(h Hash) bool { // ToHash 将[]byte经过哈希计算后转化为哈希对象
return h == Hash{}
}
// 将[]byte经过哈希计算后转化为哈希对象
func ToHash(data []byte) Hash { func ToHash(data []byte) Hash {
return BytesToHash(common.Sha256(data)) return BytesToHash(common.Sha256(data))
} }
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
package common package common
// 合约交易消息模型 // Message 合约交易消息模型
// 在EVM执行器中传递此消息,由外部Tx等价构造 // 在EVM执行器中传递此消息,由外部Tx等价构造
type Message struct { type Message struct {
to *Address to *Address
...@@ -17,6 +17,7 @@ type Message struct { ...@@ -17,6 +17,7 @@ type Message struct {
data []byte data []byte
} }
// NewMessage 新建消息结构
func NewMessage(from Address, to *Address, nonce int64, amount uint64, gasLimit uint64, gasPrice uint32, data []byte, alias string) *Message { func NewMessage(from Address, to *Address, nonce int64, amount uint64, gasLimit uint64, gasPrice uint32, data []byte, alias string) *Message {
return &Message{ return &Message{
from: from, from: from,
...@@ -30,11 +31,26 @@ func NewMessage(from Address, to *Address, nonce int64, amount uint64, gasLimit ...@@ -30,11 +31,26 @@ func NewMessage(from Address, to *Address, nonce int64, amount uint64, gasLimit
} }
} }
func (m Message) From() Address { return m.from } // From 来源
func (m Message) To() *Address { return m.to } func (m Message) From() Address { return m.from }
// To 目的地址
func (m Message) To() *Address { return m.to }
// GasPrice Gas价格
func (m Message) GasPrice() uint32 { return m.gasPrice } func (m Message) GasPrice() uint32 { return m.gasPrice }
func (m Message) Value() uint64 { return m.amount }
func (m Message) Nonce() int64 { return m.nonce } // Value 转账金额
func (m Message) Data() []byte { return m.data } func (m Message) Value() uint64 { return m.amount }
// Nonce nonce值
func (m Message) Nonce() int64 { return m.nonce }
// Data 附带数据
func (m Message) Data() []byte { return m.data }
// GasLimit Gas限制
func (m Message) GasLimit() uint64 { return m.gasLimit } func (m Message) GasLimit() uint64 { return m.gasLimit }
func (m Message) Alias() string { return m.alias }
// Alias 合约别名
func (m Message) Alias() string { return m.alias }
...@@ -11,20 +11,26 @@ import ( ...@@ -11,20 +11,26 @@ import (
) )
const ( const (
GasQuickStep uint64 = 2 // GasQuickStep 计费
GasQuickStep uint64 = 2
// GasFastestStep 计费
GasFastestStep uint64 = 3 GasFastestStep uint64 = 3
GasFastStep uint64 = 5 // GasFastStep 计费
GasMidStep uint64 = 8 GasFastStep uint64 = 5
GasSlowStep uint64 = 10 // GasMidStep 计费
GasExtStep uint64 = 20 GasMidStep uint64 = 8
// GasSlowStep 计费
// 允许开辟的最大内存空间大小,超过此值时将会导致溢出 GasSlowStep uint64 = 10
// GasExtStep 计费
GasExtStep uint64 = 20
// MaxNewMemSize 允许开辟的最大内存空间大小,超过此值时将会导致溢出
MaxNewMemSize uint64 = 0xffffffffe0 MaxNewMemSize uint64 = 0xffffffffe0
) )
// 返回真实花费的Gas // 返回真实花费的Gas
// availableGas - base * 63 / 64. // availableGas - base * 63 / 64.
func callGas(gasTable GasTable, availableGas, base uint64, callCost *big.Int) (uint64, error) { func callGas(gasTable Table, availableGas, base uint64, callCost *big.Int) (uint64, error) {
if availableGas == callCost.Uint64() { if availableGas == callCost.Uint64() {
availableGas = availableGas - base availableGas = availableGas - base
gas := availableGas - availableGas/64 gas := availableGas - availableGas/64
......
...@@ -12,15 +12,17 @@ import ( ...@@ -12,15 +12,17 @@ import (
// 整数池允许的最大长度 // 整数池允许的最大长度
const poolLimit = 256 const poolLimit = 256
// big.Int组成的内存池 // IntPool big.Int组成的内存池
type IntPool struct { type IntPool struct {
pool *Stack pool *Stack
} }
// NewIntPool 创建新的内存池
func NewIntPool() *IntPool { func NewIntPool() *IntPool {
return &IntPool{pool: NewStack()} return &IntPool{pool: NewStack()}
} }
// Get 取数据
func (p *IntPool) Get() *big.Int { func (p *IntPool) Get() *big.Int {
if p.pool.Len() > 0 { if p.pool.Len() > 0 {
return p.pool.Pop() return p.pool.Pop()
...@@ -28,6 +30,7 @@ func (p *IntPool) Get() *big.Int { ...@@ -28,6 +30,7 @@ func (p *IntPool) Get() *big.Int {
return new(big.Int) return new(big.Int)
} }
// Put 存数据
func (p *IntPool) Put(is ...*big.Int) { func (p *IntPool) Put(is ...*big.Int) {
if len(p.pool.Items) > poolLimit { if len(p.pool.Items) > poolLimit {
return return
...@@ -38,7 +41,7 @@ func (p *IntPool) Put(is ...*big.Int) { ...@@ -38,7 +41,7 @@ func (p *IntPool) Put(is ...*big.Int) {
} }
} }
// 返回一个零值的big.Int // GetZero 返回一个零值的big.Int
func (p *IntPool) GetZero() *big.Int { func (p *IntPool) GetZero() *big.Int {
if p.pool.Len() > 0 { if p.pool.Len() > 0 {
return p.pool.Pop().SetUint64(0) return p.pool.Pop().SetUint64(0)
...@@ -49,17 +52,18 @@ func (p *IntPool) GetZero() *big.Int { ...@@ -49,17 +52,18 @@ func (p *IntPool) GetZero() *big.Int {
// 默认容量 // 默认容量
const poolDefaultCap = 25 const poolDefaultCap = 25
// 用于管理IntPool的Pool // IntPoolPool 用于管理IntPool的Pool
type IntPoolPool struct { type IntPoolPool struct {
pools []*IntPool pools []*IntPool
lock sync.Mutex lock sync.Mutex
} }
// PoolOfIntPools 内存缓冲池
var PoolOfIntPools = &IntPoolPool{ var PoolOfIntPools = &IntPoolPool{
pools: make([]*IntPool, 0, poolDefaultCap), pools: make([]*IntPool, 0, poolDefaultCap),
} }
// get is looking for an available pool to return. // Get 返回一个可用的内存池
func (ipp *IntPoolPool) Get() *IntPool { func (ipp *IntPoolPool) Get() *IntPool {
ipp.lock.Lock() ipp.lock.Lock()
defer ipp.lock.Unlock() defer ipp.lock.Unlock()
...@@ -72,7 +76,7 @@ func (ipp *IntPoolPool) Get() *IntPool { ...@@ -72,7 +76,7 @@ func (ipp *IntPoolPool) Get() *IntPool {
return NewIntPool() return NewIntPool()
} }
// put a pool that has been allocated with get. // Put 放入一个初始化过的内存池
func (ipp *IntPoolPool) Put(ip *IntPool) { func (ipp *IntPoolPool) Put(ip *IntPool) {
ipp.lock.Lock() ipp.lock.Lock()
defer ipp.lock.Unlock() defer ipp.lock.Unlock()
......
...@@ -12,19 +12,20 @@ import ( ...@@ -12,19 +12,20 @@ import (
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common" "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
) )
// 内存操作封装,在EVM中使用此对象模拟物理内存 // Memory 内存操作封装,在EVM中使用此对象模拟物理内存
type Memory struct { type Memory struct {
// 内存中存储的数据 // Store 内存中存储的数据
Store []byte Store []byte
// 上次开辟内存消耗的Gas // LastGasCost 上次开辟内存消耗的Gas
LastGasCost uint64 LastGasCost uint64
} }
// NewMemory 创建内存对象结构
func NewMemory() *Memory { func NewMemory() *Memory {
return &Memory{} return &Memory{}
} }
// 设置内存中的值, value => offset:offset + size // Set 设置内存中的值, value => offset:offset + size
func (m *Memory) Set(offset, size uint64, value []byte) (err error) { func (m *Memory) Set(offset, size uint64, value []byte) (err error) {
if size > 0 { if size > 0 {
// 偏移量+大小一定不会大于内存长度 // 偏移量+大小一定不会大于内存长度
...@@ -39,7 +40,7 @@ func (m *Memory) Set(offset, size uint64, value []byte) (err error) { ...@@ -39,7 +40,7 @@ func (m *Memory) Set(offset, size uint64, value []byte) (err error) {
return nil return nil
} }
// 从offset开始设置32个字节的内存值,如果值长度不足32个字节,左零值填充 // Set32 从offset开始设置32个字节的内存值,如果值长度不足32个字节,左零值填充
func (m *Memory) Set32(offset uint64, val *big.Int) (err error) { func (m *Memory) Set32(offset uint64, val *big.Int) (err error) {
// 确保长度足够设置值 // 确保长度足够设置值
...@@ -58,14 +59,14 @@ func (m *Memory) Set32(offset uint64, val *big.Int) (err error) { ...@@ -58,14 +59,14 @@ func (m *Memory) Set32(offset uint64, val *big.Int) (err error) {
return nil return nil
} }
// 扩充内存到指定大小 // Resize 扩充内存到指定大小
func (m *Memory) Resize(size uint64) { func (m *Memory) Resize(size uint64) {
if uint64(m.Len()) < size { if uint64(m.Len()) < size {
m.Store = append(m.Store, make([]byte, size-uint64(m.Len()))...) m.Store = append(m.Store, make([]byte, size-uint64(m.Len()))...)
} }
} }
// 获取内存中制定偏移量开始的指定长度的数据,返回数据的拷贝而非引用 // Get 获取内存中制定偏移量开始的指定长度的数据,返回数据的拷贝而非引用
func (m *Memory) Get(offset, size int64) (cpy []byte) { func (m *Memory) Get(offset, size int64) (cpy []byte) {
if size == 0 { if size == 0 {
return nil return nil
...@@ -81,7 +82,7 @@ func (m *Memory) Get(offset, size int64) (cpy []byte) { ...@@ -81,7 +82,7 @@ func (m *Memory) Get(offset, size int64) (cpy []byte) {
return return
} }
// 同Get操作,不过这里返回的是数据引用 // GetPtr 同Get操作,不过这里返回的是数据引用
func (m *Memory) GetPtr(offset, size int64) []byte { func (m *Memory) GetPtr(offset, size int64) []byte {
if size == 0 { if size == 0 {
return nil return nil
...@@ -94,17 +95,17 @@ func (m *Memory) GetPtr(offset, size int64) []byte { ...@@ -94,17 +95,17 @@ func (m *Memory) GetPtr(offset, size int64) []byte {
return nil return nil
} }
// 返回内存中已开辟空间的大小(以字节计算) // Len 返回内存中已开辟空间的大小(以字节计算)
func (m *Memory) Len() int { func (m *Memory) Len() int {
return len(m.Store) return len(m.Store)
} }
// 返回内存中的原始数据引用 // Data 返回内存中的原始数据引用
func (m *Memory) Data() []byte { func (m *Memory) Data() []byte {
return m.Store return m.Store
} }
// 打印内存中的数据(调试用) // Print 打印内存中的数据(调试用)
func (m *Memory) Print() { func (m *Memory) Print() {
fmt.Printf("### mem %d bytes ###\n", len(m.Store)) fmt.Printf("### mem %d bytes ###\n", len(m.Store))
if len(m.Store) > 0 { if len(m.Store) > 0 {
......
...@@ -13,46 +13,56 @@ import ( ...@@ -13,46 +13,56 @@ import (
// 本文件中定义各种操作下计算内存大小的逻辑 // 本文件中定义各种操作下计算内存大小的逻辑
type ( type (
// 计算所需内存大小 // MemorySizeFunc 计算所需内存大小
MemorySizeFunc func(*Stack) *big.Int MemorySizeFunc func(*Stack) *big.Int
) )
// MemorySha3 sha3计算所需内存大小
func MemorySha3(stack *Stack) *big.Int { func MemorySha3(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), stack.Back(1)) return calcMemSize(stack.Back(0), stack.Back(1))
} }
//MemoryCallDataCopy callDataCopy所需内存大小
func MemoryCallDataCopy(stack *Stack) *big.Int { func MemoryCallDataCopy(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), stack.Back(2)) return calcMemSize(stack.Back(0), stack.Back(2))
} }
//MemoryReturnDataCopy returnDataCopy所需内存大小
func MemoryReturnDataCopy(stack *Stack) *big.Int { func MemoryReturnDataCopy(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), stack.Back(2)) return calcMemSize(stack.Back(0), stack.Back(2))
} }
//MemoryCodeCopy codeCopy所需内存大小
func MemoryCodeCopy(stack *Stack) *big.Int { func MemoryCodeCopy(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), stack.Back(2)) return calcMemSize(stack.Back(0), stack.Back(2))
} }
//MemoryExtCodeCopy extCodeCopy所需内存大小
func MemoryExtCodeCopy(stack *Stack) *big.Int { func MemoryExtCodeCopy(stack *Stack) *big.Int {
return calcMemSize(stack.Back(1), stack.Back(3)) return calcMemSize(stack.Back(1), stack.Back(3))
} }
//MemoryMLoad mload所需内存大小
func MemoryMLoad(stack *Stack) *big.Int { func MemoryMLoad(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), big.NewInt(32)) return calcMemSize(stack.Back(0), big.NewInt(32))
} }
//MemoryMStore8 mstore8所需内存大小
func MemoryMStore8(stack *Stack) *big.Int { func MemoryMStore8(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), big.NewInt(1)) return calcMemSize(stack.Back(0), big.NewInt(1))
} }
//MemoryMStore mstore所需内存大小
func MemoryMStore(stack *Stack) *big.Int { func MemoryMStore(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), big.NewInt(32)) return calcMemSize(stack.Back(0), big.NewInt(32))
} }
//MemoryCreate create所需内存大小
func MemoryCreate(stack *Stack) *big.Int { func MemoryCreate(stack *Stack) *big.Int {
return calcMemSize(stack.Back(1), stack.Back(2)) return calcMemSize(stack.Back(1), stack.Back(2))
} }
//MemoryCall call所需内存大小
func MemoryCall(stack *Stack) *big.Int { func MemoryCall(stack *Stack) *big.Int {
x := calcMemSize(stack.Back(5), stack.Back(6)) x := calcMemSize(stack.Back(5), stack.Back(6))
y := calcMemSize(stack.Back(3), stack.Back(4)) y := calcMemSize(stack.Back(3), stack.Back(4))
...@@ -60,6 +70,7 @@ func MemoryCall(stack *Stack) *big.Int { ...@@ -60,6 +70,7 @@ func MemoryCall(stack *Stack) *big.Int {
return common.BigMax(x, y) return common.BigMax(x, y)
} }
//MemoryDelegateCall delegateCall所需内存大小
func MemoryDelegateCall(stack *Stack) *big.Int { func MemoryDelegateCall(stack *Stack) *big.Int {
x := calcMemSize(stack.Back(4), stack.Back(5)) x := calcMemSize(stack.Back(4), stack.Back(5))
y := calcMemSize(stack.Back(2), stack.Back(3)) y := calcMemSize(stack.Back(2), stack.Back(3))
...@@ -67,6 +78,7 @@ func MemoryDelegateCall(stack *Stack) *big.Int { ...@@ -67,6 +78,7 @@ func MemoryDelegateCall(stack *Stack) *big.Int {
return common.BigMax(x, y) return common.BigMax(x, y)
} }
//MemoryStaticCall staticCall所需内存大小
func MemoryStaticCall(stack *Stack) *big.Int { func MemoryStaticCall(stack *Stack) *big.Int {
x := calcMemSize(stack.Back(4), stack.Back(5)) x := calcMemSize(stack.Back(4), stack.Back(5))
y := calcMemSize(stack.Back(2), stack.Back(3)) y := calcMemSize(stack.Back(2), stack.Back(3))
...@@ -74,14 +86,17 @@ func MemoryStaticCall(stack *Stack) *big.Int { ...@@ -74,14 +86,17 @@ func MemoryStaticCall(stack *Stack) *big.Int {
return common.BigMax(x, y) return common.BigMax(x, y)
} }
//MemoryReturn return所需内存大小
func MemoryReturn(stack *Stack) *big.Int { func MemoryReturn(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), stack.Back(1)) return calcMemSize(stack.Back(0), stack.Back(1))
} }
//MemoryRevert revert所需内存大小
func MemoryRevert(stack *Stack) *big.Int { func MemoryRevert(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), stack.Back(1)) return calcMemSize(stack.Back(0), stack.Back(1))
} }
//MemoryLog log所需内存大小
func MemoryLog(stack *Stack) *big.Int { func MemoryLog(stack *Stack) *big.Int {
mSize, mStart := stack.Back(1), stack.Back(0) mSize, mStart := stack.Back(1), stack.Back(0)
return calcMemSize(mStart, mSize) return calcMemSize(mStart, mSize)
......
...@@ -11,63 +11,64 @@ import ( ...@@ -11,63 +11,64 @@ import (
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/params" "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/params"
) )
// 栈对象封装,提供常用的栈操作 // Stack 栈对象封装,提供常用的栈操作
type Stack struct { type Stack struct {
Items []*big.Int Items []*big.Int
} }
// NewStack 新创建栈对象
func NewStack() *Stack { func NewStack() *Stack {
return &Stack{Items: make([]*big.Int, 0, params.StackLimit)} return &Stack{Items: make([]*big.Int, 0, params.StackLimit)}
} }
// 返回栈中的所有底层数据 // Data 返回栈中的所有底层数据
func (st *Stack) Data() []*big.Int { func (st *Stack) Data() []*big.Int {
return st.Items return st.Items
} }
// 数据入栈 // Push 数据入栈
func (st *Stack) Push(d *big.Int) { func (st *Stack) Push(d *big.Int) {
st.Items = append(st.Items, d) st.Items = append(st.Items, d)
} }
// 同时压栈多个数据 // PushN 同时压栈多个数据
func (st *Stack) PushN(ds ...*big.Int) { func (st *Stack) PushN(ds ...*big.Int) {
st.Items = append(st.Items, ds...) st.Items = append(st.Items, ds...)
} }
// 弹出栈顶数据 // Pop 弹出栈顶数据
func (st *Stack) Pop() (ret *big.Int) { func (st *Stack) Pop() (ret *big.Int) {
ret = st.Items[len(st.Items)-1] ret = st.Items[len(st.Items)-1]
st.Items = st.Items[:len(st.Items)-1] st.Items = st.Items[:len(st.Items)-1]
return return
} }
// 栈长度 // Len 栈长度
func (st *Stack) Len() int { func (st *Stack) Len() int {
return len(st.Items) return len(st.Items)
} }
// 将栈顶数据和栈中指定位置的数据互换位置 // Swap 将栈顶数据和栈中指定位置的数据互换位置
func (st *Stack) Swap(n int) { func (st *Stack) Swap(n int) {
st.Items[st.Len()-n], st.Items[st.Len()-1] = st.Items[st.Len()-1], st.Items[st.Len()-n] st.Items[st.Len()-n], st.Items[st.Len()-1] = st.Items[st.Len()-1], st.Items[st.Len()-n]
} }
// 复制栈中指定位置的数据的栈顶 // Dup 复制栈中指定位置的数据的栈顶
func (st *Stack) Dup(pool *IntPool, n int) { func (st *Stack) Dup(pool *IntPool, n int) {
st.Push(pool.Get().Set(st.Items[st.Len()-n])) st.Push(pool.Get().Set(st.Items[st.Len()-n]))
} }
// 返回顶端数据 // Peek 返回顶端数据
func (st *Stack) Peek() *big.Int { func (st *Stack) Peek() *big.Int {
return st.Items[st.Len()-1] return st.Items[st.Len()-1]
} }
// 返回第n个取值 // Back 返回第n个取值
func (st *Stack) Back(n int) *big.Int { func (st *Stack) Back(n int) *big.Int {
return st.Items[st.Len()-n-1] return st.Items[st.Len()-n-1]
} }
// 检查栈是否满足长度要求 // Require 检查栈是否满足长度要求
func (st *Stack) Require(n int) error { func (st *Stack) Require(n int) error {
if st.Len() < n { if st.Len() < n {
return fmt.Errorf("stack underflow (%d <=> %d)", len(st.Items), n) return fmt.Errorf("stack underflow (%d <=> %d)", len(st.Items), n)
...@@ -75,7 +76,7 @@ func (st *Stack) Require(n int) error { ...@@ -75,7 +76,7 @@ func (st *Stack) Require(n int) error {
return nil return nil
} }
// 印栈对象(调试用) // Print 印栈对象(调试用)
func (st *Stack) Print() { func (st *Stack) Print() {
fmt.Println("### stack ###") fmt.Println("### stack ###")
if len(st.Items) > 0 { if len(st.Items) > 0 {
......
...@@ -11,11 +11,11 @@ import ( ...@@ -11,11 +11,11 @@ import (
) )
type ( type (
// 校验栈中数据是否满足计算要求 // StackValidationFunc 校验栈中数据是否满足计算要求
StackValidationFunc func(*Stack) error StackValidationFunc func(*Stack) error
) )
// 栈校验的通用逻辑封装(主要就是检查栈的深度和空间是否够用) // MakeStackFunc 栈校验的通用逻辑封装(主要就是检查栈的深度和空间是否够用)
func MakeStackFunc(pop, push int) StackValidationFunc { func MakeStackFunc(pop, push int) StackValidationFunc {
return func(stack *Stack) error { return func(stack *Stack) error {
if err := stack.Require(pop); err != nil { if err := stack.Require(pop); err != nil {
...@@ -29,10 +29,12 @@ func MakeStackFunc(pop, push int) StackValidationFunc { ...@@ -29,10 +29,12 @@ func MakeStackFunc(pop, push int) StackValidationFunc {
} }
} }
// MakeDupStackFunc 创建栈大小计算方法对象
func MakeDupStackFunc(n int) StackValidationFunc { func MakeDupStackFunc(n int) StackValidationFunc {
return MakeStackFunc(n, n+1) return MakeStackFunc(n, n+1)
} }
// MakeSwapStackFunc 创建栈大小计算方法对象
func MakeSwapStackFunc(n int) StackValidationFunc { func MakeSwapStackFunc(n int) StackValidationFunc {
return MakeStackFunc(n, n) return MakeStackFunc(n, n)
} }
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
package model package model
const ( const (
// 内存中存储的字,占用多少位 // WordBitSize 内存中存储的字,占用多少位
WordBitSize = 256 WordBitSize = 256
// 内存中存储的字,占用多少字节 // WordByteSize 内存中存储的字,占用多少字节
WordByteSize = WordBitSize / 8 WordByteSize = WordBitSize / 8
) )
...@@ -7,24 +7,38 @@ package model ...@@ -7,24 +7,38 @@ package model
import "errors" import "errors"
var ( var (
ErrOutOfGas = errors.New("out of gas") // ErrOutOfGas out of gas
ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas") ErrOutOfGas = errors.New("out of gas")
ErrDepth = errors.New("max call depth exceeded") // ErrCodeStoreOutOfGas contract creation code storage out of gas
ErrTraceLimitReached = errors.New("the number of logs reached the specified limit") ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas")
ErrInsufficientBalance = errors.New("insufficient balance for transfer") // ErrDepth max call depth exceeded
ErrDepth = errors.New("max call depth exceeded")
// ErrInsufficientBalance insufficient balance for transfer
ErrInsufficientBalance = errors.New("insufficient balance for transfer")
// ErrContractAddressCollision contract address collision
ErrContractAddressCollision = errors.New("contract address collision") ErrContractAddressCollision = errors.New("contract address collision")
ErrGasLimitReached = errors.New("gas limit reached") // ErrGasUintOverflow gas uint64 overflow
ErrGasUintOverflow = errors.New("gas uint64 overflow") ErrGasUintOverflow = errors.New("gas uint64 overflow")
ErrAddrNotExists = errors.New("address not exists") // ErrAddrNotExists address not exists
ErrAddrNotExists = errors.New("address not exists")
// ErrTransferBetweenContracts transferring between contracts not supports
ErrTransferBetweenContracts = errors.New("transferring between contracts not supports") ErrTransferBetweenContracts = errors.New("transferring between contracts not supports")
ErrTransferBetweenEOA = errors.New("transferring between external accounts not supports") // ErrTransferBetweenEOA transferring between external accounts not supports
ErrNoCreator = errors.New("contract has no creator information") ErrTransferBetweenEOA = errors.New("transferring between external accounts not supports")
ErrDestruct = errors.New("contract has been destructed") // ErrNoCreator contract has no creator information
ErrNoCreator = errors.New("contract has no creator information")
// ErrDestruct contract has been destructed
ErrDestruct = errors.New("contract has been destructed")
ErrWriteProtection = errors.New("evm: write protection") // ErrWriteProtection evm: write protection
ErrWriteProtection = errors.New("evm: write protection")
// ErrReturnDataOutOfBounds evm: return data out of bounds
ErrReturnDataOutOfBounds = errors.New("evm: return data out of bounds") ErrReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
ErrExecutionReverted = errors.New("evm: execution reverted") // ErrExecutionReverted evm: execution reverted
ErrMaxCodeSizeExceeded = errors.New("evm: max code size exceeded") ErrExecutionReverted = errors.New("evm: execution reverted")
// ErrMaxCodeSizeExceeded evm: max code size exceeded
ErrMaxCodeSizeExceeded = errors.New("evm: max code size exceeded")
NoCoinsAccount = errors.New("no coins account in executor!") // ErrNoCoinsAccount no coins account in executor!
ErrNoCoinsAccount = errors.New("no coins account in executor")
) )
...@@ -9,26 +9,26 @@ import ( ...@@ -9,26 +9,26 @@ import (
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common" "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
) )
// 合约在日志,对应EVM中的Log指令,可以生成指定的日志信息 // ContractLog 合约在日志,对应EVM中的Log指令,可以生成指定的日志信息
// 目前这些日志只是在合约执行完成时进行打印,没有其它用途 // 目前这些日志只是在合约执行完成时进行打印,没有其它用途
type ContractLog struct { type ContractLog struct {
// 合约地址 // Address 合约地址
Address common.Address Address common.Address
// 对应交易哈希 // TxHash 对应交易哈希
TxHash common.Hash TxHash common.Hash
// 日志序号 // Index 日志序号
Index int Index int
// 此合约提供的主题信息 // Topics 此合约提供的主题信息
Topics []common.Hash Topics []common.Hash
// 日志数据 // Data 日志数据
Data []byte Data []byte
} }
// 合约日志打印格式 // PrintLog 合约日志打印格式
func (log *ContractLog) PrintLog() { func (log *ContractLog) PrintLog() {
log15.Debug("!Contract Log!", "Contract address", log.Address.String(), "TxHash", log.TxHash.Hex(), "Log Index", log.Index, "Log Topics", log.Topics, "Log Data", common.Bytes2Hex(log.Data)) log15.Debug("!Contract Log!", "Contract address", log.Address.String(), "TxHash", log.TxHash.Hex(), "Log Index", log.Index, "Log Topics", log.Topics, "Log Data", common.Bytes2Hex(log.Data))
} }
...@@ -11,19 +11,19 @@ import ( ...@@ -11,19 +11,19 @@ import (
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/state" "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/state"
) )
// 解释器中调用Gas计算时所传递的合约中和Gas相关的参数结构 // GasParam 解释器中调用Gas计算时所传递的合约中和Gas相关的参数结构
// 之所以单独封装,是为了将解释器、指令集、Gas计算三者解耦 // 之所以单独封装,是为了将解释器、指令集、Gas计算三者解耦
// 此结构包含的属性均为只读 // 此结构包含的属性均为只读
type GasParam struct { type GasParam struct {
// 此合约对象的可用Gas(合约执行过程中会修改此值) // Gas 此合约对象的可用Gas(合约执行过程中会修改此值)
Gas uint64 Gas uint64
// 上下文中合约自身的地址 // Address 上下文中合约自身的地址
// 注意,当合约通过CallCode调用时,这个地址并不是当前合约代码对应的地址,而是调用者的地址 // 注意,当合约通过CallCode调用时,这个地址并不是当前合约代码对应的地址,而是调用者的地址
Address common.Address Address common.Address
} }
// 解释器中调用Gas计算时所传递的合约中和EVM相关的参数结构 // EVMParam 解释器中调用Gas计算时所传递的合约中和EVM相关的参数结构
// 之所以单独封装,是为了将解释器、Gas计算两者解耦 // 之所以单独封装,是为了将解释器、Gas计算两者解耦
// 此结构包含的属性中StateDB和CallGasTemp可写,解释器调用Gas计算的步骤如下: // 此结构包含的属性中StateDB和CallGasTemp可写,解释器调用Gas计算的步骤如下:
// 1. 使用EVM构造EVMParam(属性除CallGasTemp外,全部传递引用); // 1. 使用EVM构造EVMParam(属性除CallGasTemp外,全部传递引用);
...@@ -31,14 +31,14 @@ type GasParam struct { ...@@ -31,14 +31,14 @@ type GasParam struct {
// 3. 计算结束后,使用EVMParam中的值回填到EVM中; // 3. 计算结束后,使用EVMParam中的值回填到EVM中;
type EVMParam struct { type EVMParam struct {
// 状态数据操作入口 // EVMStateDB 状态数据操作入口
StateDB state.StateDB StateDB state.EVMStateDB
// 此属性用于临时存储计算出来的Gas消耗值 // CallGasTemp 此属性用于临时存储计算出来的Gas消耗值
// 在指令执行时,会调用指令的gasCost方法,计算出此指令需要消耗的Gas,并存放在此临时属性中 // 在指令执行时,会调用指令的gasCost方法,计算出此指令需要消耗的Gas,并存放在此临时属性中
// 然后在执行opCall时,从此属性获取消耗的Gas值 // 然后在执行opCall时,从此属性获取消耗的Gas值
CallGasTemp uint64 CallGasTemp uint64
// NUMBER 指令,当前区块高度 // BlockNumber NUMBER 指令,当前区块高度
BlockNumber *big.Int BlockNumber *big.Int
} }
...@@ -5,43 +5,75 @@ ...@@ -5,43 +5,75 @@
package params package params
const ( const (
MaxCodeSize = 24576 // 合约允许的最大字节数 // MaxCodeSize 合约允许的最大字节数
CallCreateDepth uint64 = 1024 // 合约递归调用最大深度 MaxCodeSize = 24576
StackLimit uint64 = 1024 // 栈允许的最大深度 // CallCreateDepth 合约递归调用最大深度
CallCreateDepth uint64 = 1024
// StackLimit 栈允许的最大深度
StackLimit uint64 = 1024
// 各种操作对应的Gas定价 // CreateDataGas 创建合约时,按字节计费
CreateDataGas uint64 = 200 // 创建合约时,按字节计费 CreateDataGas uint64 = 200
CallStipend uint64 = 2300 // 每次CALL调用之前,给予一定额度的免费Gas // CallStipend 每次CALL调用之前,给予一定额度的免费Gas
CallValueTransferGas uint64 = 9000 // 转账操作 CallStipend uint64 = 2300
CallNewAccountGas uint64 = 25000 // 操作目标地址事先不存在 // CallValueTransferGas 转账操作
QuadCoeffDiv uint64 = 512 // 计算开辟内存花费时,在计算出的内存大小平方基础上除此值 CallValueTransferGas uint64 = 9000
CopyGas uint64 = 3 // 内存数据复制时,按字计费 // CallNewAccountGas 操作目标地址事先不存在
CallNewAccountGas uint64 = 25000
// QuadCoeffDiv 计算开辟内存花费时,在计算出的内存大小平方基础上除此值
QuadCoeffDiv uint64 = 512
// CopyGas 内存数据复制时,按字计费
CopyGas uint64 = 3
Sha3Gas uint64 = 30 // SHA3操作 // Sha3Gas SHA3操作
Sha3WordGas uint64 = 6 // SHA3操作的数据按字计费 Sha3Gas uint64 = 30
SstoreSetGas uint64 = 20000 // SSTORE 从零值地址到非零值地址存储 // Sha3WordGas SHA3操作的数据按字计费
SstoreResetGas uint64 = 5000 // SSTORE 从非零值地址到非零值地址存储 Sha3WordGas uint64 = 6
SstoreClearGas uint64 = 5000 // SSTORE 从非零值地址到零值地址存储 // SstoreSetGas SSTORE 从零值地址到非零值地址存储
SstoreRefundGas uint64 = 15000 // SSTORE 删除值时给予的奖励 SstoreSetGas uint64 = 20000
JumpdestGas uint64 = 1 // JUMPDEST 指令 // SstoreResetGas SSTORE 从非零值地址到非零值地址存储
LogGas uint64 = 375 // LOGN 操作计费 SstoreResetGas uint64 = 5000
LogDataGas uint64 = 8 // LOGN生成的数据,每个字节的计费价格 // SstoreClearGas SSTORE 从非零值地址到零值地址存储
LogTopicGas uint64 = 375 // LOGN 生成日志时,使用N*此值计费 SstoreClearGas uint64 = 5000
CreateGas uint64 = 32000 // CREATE 指令 // SstoreRefundGas SSTORE 删除值时给予的奖励
SuicideRefundGas uint64 = 24000 // SUICIDE 操作时给予的奖励 SstoreRefundGas uint64 = 15000
MemoryGas uint64 = 3 // 开辟新内存时按字收费 // JumpdestGas JUMPDEST 指令
JumpdestGas uint64 = 1
// LogGas LOGN 操作计费
LogGas uint64 = 375
// LogDataGas LOGN生成的数据,每个字节的计费价格
LogDataGas uint64 = 8
// LogTopicGas LOGN 生成日志时,使用N*此值计费
LogTopicGas uint64 = 375
// CreateGas CREATE 指令
CreateGas uint64 = 32000
// SuicideRefundGas SUICIDE 操作时给予的奖励
SuicideRefundGas uint64 = 24000
// MemoryGas 开辟新内存时按字收费
MemoryGas uint64 = 3
// 预编译合约的Gas定价 // EcrecoverGas ecrecover 指令
EcrecoverGas uint64 = 3000 // ecrecover 指令 EcrecoverGas uint64 = 3000
Sha256BaseGas uint64 = 60 // SHA256 基础计费 // Sha256BaseGas SHA256 基础计费
Sha256PerWordGas uint64 = 12 // SHA256 按字长计费 (总计费等于两者相加) Sha256BaseGas uint64 = 60
Ripemd160BaseGas uint64 = 600 // RIPEMD160 基础计费 // Sha256PerWordGas SHA256 按字长计费 (总计费等于两者相加)
Ripemd160PerWordGas uint64 = 120 // RIPEMD160 按字长计费 (总计费等于两者相加) Sha256PerWordGas uint64 = 12
IdentityBaseGas uint64 = 15 // dataCopy 基础计费 // Ripemd160BaseGas RIPEMD160 基础计费
IdentityPerWordGas uint64 = 3 // dataCopy 按字长计费(总计费等于两者相加) Ripemd160BaseGas uint64 = 600
ModExpQuadCoeffDiv uint64 = 20 // 大整数取模运算时计算出的费用除此数 // Ripemd160PerWordGas RIPEMD160 按字长计费 (总计费等于两者相加)
Bn256AddGas uint64 = 500 // Bn256Add 计费 Ripemd160PerWordGas uint64 = 120
Bn256ScalarMulGas uint64 = 40000 // Bn256ScalarMul 计费 // IdentityBaseGas dataCopy 基础计费
Bn256PairingBaseGas uint64 = 100000 // bn256Pairing 基础计费 IdentityBaseGas uint64 = 15
Bn256PairingPerPointGas uint64 = 80000 // bn256Pairing 按point计费(总计费等于两者相加) // IdentityPerWordGas dataCopy 按字长计费(总计费等于两者相加)
IdentityPerWordGas uint64 = 3
// ModExpQuadCoeffDiv 大整数取模运算时计算出的费用除此数
ModExpQuadCoeffDiv uint64 = 20
// Bn256AddGas Bn256Add 计费
Bn256AddGas uint64 = 500
// Bn256ScalarMulGas Bn256ScalarMul 计费
Bn256ScalarMulGas uint64 = 40000
// Bn256PairingBaseGas bn256Pairing 基础计费
Bn256PairingBaseGas uint64 = 100000
// Bn256PairingPerPointGas bn256Pairing 按point计费(总计费等于两者相加)
Bn256PairingPerPointGas uint64 = 80000
) )
...@@ -15,7 +15,7 @@ import ( ...@@ -15,7 +15,7 @@ import (
// JUMPDEST指令会使用此对象进行跳转位置判断 // JUMPDEST指令会使用此对象进行跳转位置判断
type Destinations map[common.Hash]bitvec type Destinations map[common.Hash]bitvec
// 检查PC只想的代码是否存在JUMPDEST指令,并且跳转目标有效 // Has 检查PC只想的代码是否存在JUMPDEST指令,并且跳转目标有效
func (d Destinations) Has(codehash common.Hash, code []byte, dest *big.Int) bool { func (d Destinations) Has(codehash common.Hash, code []byte, dest *big.Int) bool {
// 首先需要检查PC(指令指针),它不可能比代码长度还大,也不可能大于63位 // 首先需要检查PC(指令指针),它不可能比代码长度还大,也不可能大于63位
// 注意,这里的参数dest就是PC指针 // 注意,这里的参数dest就是PC指针
......
...@@ -8,22 +8,22 @@ import ( ...@@ -8,22 +8,22 @@ import (
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common" "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
) )
// 合约对象引用 // ContractRef 合约对象引用
type ContractRef interface { type ContractRef interface {
Address() common.Address Address() common.Address
} }
// 账户对象引用 (实现了合约对象引用ContractRef接口) // AccountRef 账户对象引用 (实现了合约对象引用ContractRef接口)
// 因为在合约调用过程中,调用者有可能是外部账户,也有可能是合约账户,所以两者的结构是互通的 // 因为在合约调用过程中,调用者有可能是外部账户,也有可能是合约账户,所以两者的结构是互通的
type AccountRef common.Address type AccountRef common.Address
// 将账户引用转换为普通地址对象 // Address 将账户引用转换为普通地址对象
func (ar AccountRef) Address() common.Address { return (common.Address)(ar) } func (ar AccountRef) Address() common.Address { return (common.Address)(ar) }
// 合约对象,它在内存中表示一个合约账户的代码即地址信息实体 // Contract 合约对象,它在内存中表示一个合约账户的代码即地址信息实体
// 每次合约调用都会创建一个新的合约对象 // 每次合约调用都会创建一个新的合约对象
type Contract struct { type Contract struct {
// 调用者地址,应该为外部账户的地址 // CallerAddress 调用者地址,应该为外部账户的地址
// 如果是通过合约再调用合约时,会从上级合约中获取调用者地址进行赋值 // 如果是通过合约再调用合约时,会从上级合约中获取调用者地址进行赋值
CallerAddress common.Address CallerAddress common.Address
...@@ -34,28 +34,30 @@ type Contract struct { ...@@ -34,28 +34,30 @@ type Contract struct {
// 但是,二般情况下(外部账户通过CallCode直接调用合约代码时,此地址会设置为外部账户的地址,就是和caller一样) // 但是,二般情况下(外部账户通过CallCode直接调用合约代码时,此地址会设置为外部账户的地址,就是和caller一样)
self ContractRef self ContractRef
// 存储跳转信息,供JUMP和JUMPI指令使用 // Jumpdests 存储跳转信息,供JUMP和JUMPI指令使用
Jumpdests Destinations Jumpdests Destinations
// 合约代码和代码哈希 // Code合约代码
Code []byte Code []byte
// CodeHash 代码哈希
CodeHash common.Hash CodeHash common.Hash
// 合约地址以及输入参数 // CodeAddr 合约地址
CodeAddr *common.Address CodeAddr *common.Address
Input []byte // Input 输入参数
Input []byte
// 此合约对象的可用Gas(合约执行过程中会修改此值) // Gas 此合约对象的可用Gas(合约执行过程中会修改此值)
Gas uint64 Gas uint64
// 合约调用的同时,如果包含转账逻辑,则此处为转账金额 // value 合约调用的同时,如果包含转账逻辑,则此处为转账金额
value uint64 value uint64
// 委托调用时,此属性会被设置为true // DelegateCall 委托调用时,此属性会被设置为true
DelegateCall bool DelegateCall bool
} }
// 创建一个新的合约调用对象 // NewContract 创建一个新的合约调用对象
// 不管合约是否存在,每次调用时都会新创建一个合约对象交给解释器执行,对象持有合约代码和合约地址 // 不管合约是否存在,每次调用时都会新创建一个合约对象交给解释器执行,对象持有合约代码和合约地址
func NewContract(caller ContractRef, object ContractRef, value uint64, gas uint64) *Contract { func NewContract(caller ContractRef, object ContractRef, value uint64, gas uint64) *Contract {
...@@ -76,7 +78,7 @@ func NewContract(caller ContractRef, object ContractRef, value uint64, gas uint6 ...@@ -76,7 +78,7 @@ func NewContract(caller ContractRef, object ContractRef, value uint64, gas uint6
return c return c
} }
// 设置当前的合约对象为被委托调用 // AsDelegate 设置当前的合约对象为被委托调用
// 返回当前合约对象的指针,以便在多层调用链模式下使用 // 返回当前合约对象的指针,以便在多层调用链模式下使用
func (c *Contract) AsDelegate() *Contract { func (c *Contract) AsDelegate() *Contract {
c.DelegateCall = true c.DelegateCall = true
...@@ -92,12 +94,12 @@ func (c *Contract) AsDelegate() *Contract { ...@@ -92,12 +94,12 @@ func (c *Contract) AsDelegate() *Contract {
return c return c
} }
// 获取合约代码中制定位置的操作码 // GetOp 获取合约代码中制定位置的操作码
func (c *Contract) GetOp(n uint64) OpCode { func (c *Contract) GetOp(n uint64) OpCode {
return OpCode(c.GetByte(n)) return OpCode(c.GetByte(n))
} }
// 获取合约代码中制定位置的字节值 // GetByte 获取合约代码中制定位置的字节值
func (c *Contract) GetByte(n uint64) byte { func (c *Contract) GetByte(n uint64) byte {
if n < uint64(len(c.Code)) { if n < uint64(len(c.Code)) {
return c.Code[n] return c.Code[n]
...@@ -106,14 +108,14 @@ func (c *Contract) GetByte(n uint64) byte { ...@@ -106,14 +108,14 @@ func (c *Contract) GetByte(n uint64) byte {
return 0 return 0
} }
// 返回合约的调用者 // Caller 返回合约的调用者
// 如果当前合约为委托调用,则调用它的不是外部账户,而是合约账户,所以此时的caller为调用此合约的合约的caller // 如果当前合约为委托调用,则调用它的不是外部账户,而是合约账户,所以此时的caller为调用此合约的合约的caller
// 这个关系可以一直递归向上,直到定位到caller为外部账户地址 // 这个关系可以一直递归向上,直到定位到caller为外部账户地址
func (c *Contract) Caller() common.Address { func (c *Contract) Caller() common.Address {
return c.CallerAddress return c.CallerAddress
} }
// 从合约的可用gas中进行gas消费 // UseGas 从合约的可用gas中进行gas消费
func (c *Contract) UseGas(gas uint64) (ok bool) { func (c *Contract) UseGas(gas uint64) (ok bool) {
if c.Gas < gas { if c.Gas < gas {
return false return false
...@@ -122,26 +124,26 @@ func (c *Contract) UseGas(gas uint64) (ok bool) { ...@@ -122,26 +124,26 @@ func (c *Contract) UseGas(gas uint64) (ok bool) {
return true return true
} }
// 返回上下文中合约自身的地址 // Address 返回上下文中合约自身的地址
// 注意,当合约通过CallCode调用时,这个地址并不是当前合约代码对应的地址,而是调用者的地址 // 注意,当合约通过CallCode调用时,这个地址并不是当前合约代码对应的地址,而是调用者的地址
func (c *Contract) Address() common.Address { func (c *Contract) Address() common.Address {
return c.self.Address() return c.self.Address()
} }
// 合约包含转账逻辑时,转账的金额 // Value 合约包含转账逻辑时,转账的金额
func (c *Contract) Value() uint64 { func (c *Contract) Value() uint64 {
return c.value return c.value
} }
// 设置合约代码内容 // SetCode 设置合约代码内容
func (self *Contract) SetCode(hash common.Hash, code []byte) { func (c *Contract) SetCode(hash common.Hash, code []byte) {
self.Code = code c.Code = code
self.CodeHash = hash c.CodeHash = hash
} }
// 设置合约代码和代码哈希 // SetCallCode 设置合约代码和代码哈希
func (self *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) { func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
self.Code = code c.Code = code
self.CodeHash = hash c.CodeHash = hash
self.CodeAddr = addr c.CodeAddr = addr
} }
...@@ -17,7 +17,7 @@ import ( ...@@ -17,7 +17,7 @@ import (
"golang.org/x/crypto/ripemd160" "golang.org/x/crypto/ripemd160"
) )
// 系统内置合约实现的接口,只包含两个操作: // PrecompiledContract 系统内置合约实现的接口,只包含两个操作:
// 1 根据合约自身逻辑和入参,计算所需Gas; // 1 根据合约自身逻辑和入参,计算所需Gas;
// 2 执行合约。 // 2 执行合约。
type PrecompiledContract interface { type PrecompiledContract interface {
...@@ -28,7 +28,7 @@ type PrecompiledContract interface { ...@@ -28,7 +28,7 @@ type PrecompiledContract interface {
Run(input []byte) ([]byte, error) Run(input []byte) ([]byte, error)
} }
// chain33平台支持君士坦丁堡版本支持的所有预编译合约指令,并从此版本开始同步支持EVM黄皮书中的新增指令; // PrecompiledContractsByzantium chain33平台支持君士坦丁堡版本支持的所有预编译合约指令,并从此版本开始同步支持EVM黄皮书中的新增指令;
// 保存拜占庭版本支持的所有预编译合约(包括之前版本的合约); // 保存拜占庭版本支持的所有预编译合约(包括之前版本的合约);
// 后面如果有硬分叉,需要在此处考虑分叉逻辑,根据区块高度分别处理; // 后面如果有硬分叉,需要在此处考虑分叉逻辑,根据区块高度分别处理;
// 下面的8个预编译指令,直接引用go-ethereum中的EVM实现 // 下面的8个预编译指令,直接引用go-ethereum中的EVM实现
...@@ -46,7 +46,7 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ ...@@ -46,7 +46,7 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{8}): &bn256Pairing{}, common.BytesToAddress([]byte{8}): &bn256Pairing{},
} }
// 调用预编译的合约逻辑并返回结果 // RunPrecompiledContract 调用预编译的合约逻辑并返回结果
func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) { func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) {
gas := p.RequiredGas(input) gas := p.RequiredGas(input)
if contract.UseGas(gas) { if contract.UseGas(gas) {
...@@ -58,10 +58,12 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contr ...@@ -58,10 +58,12 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contr
// 预编译合约 ECRECOVER 椭圆曲线算法支持 // 预编译合约 ECRECOVER 椭圆曲线算法支持
type ecrecover struct{} type ecrecover struct{}
// RequiredGas 需要消耗多少Gas
func (c *ecrecover) RequiredGas(input []byte) uint64 { func (c *ecrecover) RequiredGas(input []byte) uint64 {
return params.EcrecoverGas return params.EcrecoverGas
} }
// Run 运算
func (c *ecrecover) Run(input []byte) ([]byte, error) { func (c *ecrecover) Run(input []byte) ([]byte, error) {
const ecRecoverInputLength = 128 const ecRecoverInputLength = 128
...@@ -98,6 +100,8 @@ type sha256hash struct{} ...@@ -98,6 +100,8 @@ type sha256hash struct{}
func (c *sha256hash) RequiredGas(input []byte) uint64 { func (c *sha256hash) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
} }
// Run run
func (c *sha256hash) Run(input []byte) ([]byte, error) { func (c *sha256hash) Run(input []byte) ([]byte, error) {
h := sha256.Sum256(input) h := sha256.Sum256(input)
return h[:], nil return h[:], nil
...@@ -113,6 +117,8 @@ type ripemd160hash struct{} ...@@ -113,6 +117,8 @@ type ripemd160hash struct{}
func (c *ripemd160hash) RequiredGas(input []byte) uint64 { func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas
} }
// Run run
func (c *ripemd160hash) Run(input []byte) ([]byte, error) { func (c *ripemd160hash) Run(input []byte) ([]byte, error) {
ripemd := ripemd160.New() ripemd := ripemd160.New()
ripemd.Write(input) ripemd.Write(input)
...@@ -129,6 +135,8 @@ type dataCopy struct{} ...@@ -129,6 +135,8 @@ type dataCopy struct{}
func (c *dataCopy) RequiredGas(input []byte) uint64 { func (c *dataCopy) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas
} }
// Run run
func (c *dataCopy) Run(in []byte) ([]byte, error) { func (c *dataCopy) Run(in []byte) ([]byte, error) {
return in, nil return in, nil
} }
...@@ -210,6 +218,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { ...@@ -210,6 +218,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
return gas.Uint64() return gas.Uint64()
} }
// Run run
func (c *bigModExp) Run(input []byte) ([]byte, error) { func (c *bigModExp) Run(input []byte) ([]byte, error) {
var ( var (
baseLen = new(big.Int).SetBytes(common.GetData(input, 0, 32)).Uint64() baseLen = new(big.Int).SetBytes(common.GetData(input, 0, 32)).Uint64()
......
This diff is collapsed.
...@@ -397,7 +397,7 @@ func opSha3(pc *uint64, evm *EVM, contract *Contract, memory *mm.Memory, stack * ...@@ -397,7 +397,7 @@ func opSha3(pc *uint64, evm *EVM, contract *Contract, memory *mm.Memory, stack *
data := memory.Get(offset.Int64(), size.Int64()) data := memory.Get(offset.Int64(), size.Int64())
hash := crypto.Keccak256(data) hash := crypto.Keccak256(data)
if evm.VmConfig.EnablePreimageRecording { if evm.VMConfig.EnablePreimageRecording {
evm.StateDB.AddPreimage(common.BytesToHash(hash), data) evm.StateDB.AddPreimage(common.BytesToHash(hash), data)
} }
......
...@@ -15,26 +15,27 @@ import ( ...@@ -15,26 +15,27 @@ import (
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/params" "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/params"
) )
// 解释器的配置模型 // Config 解释器的配置模型
type Config struct { type Config struct {
// 调试开关 // Debug 调试开关
Debug bool Debug bool
// 记录操作日志 // Tracer 记录操作日志
Tracer Tracer Tracer Tracer
// 不允许使用Call, CallCode, DelegateCall // NoRecursion 不允许使用Call, CallCode, DelegateCall
NoRecursion bool NoRecursion bool
// SHA3/keccak 操作时是否保存数据 // EnablePreimageRecording SHA3/keccak 操作时是否保存数据
EnablePreimageRecording bool EnablePreimageRecording bool
// 指令跳转表 // JumpTable 指令跳转表
JumpTable [256]Operation JumpTable [256]Operation
} }
// 解释器接结构定义 // Interpreter 解释器接结构定义
type Interpreter struct { type Interpreter struct {
evm *EVM evm *EVM
cfg Config cfg Config
gasTable gas.GasTable gasTable gas.Table
IntPool *mm.IntPool // IntPool 整数内存池
IntPool *mm.IntPool
// 是否允许修改数据 // 是否允许修改数据
readOnly bool readOnly bool
...@@ -42,6 +43,7 @@ type Interpreter struct { ...@@ -42,6 +43,7 @@ type Interpreter struct {
ReturnData []byte ReturnData []byte
} }
// NewInterpreter 新创建一个解释器
func NewInterpreter(evm *EVM, cfg Config) *Interpreter { func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
// 使用是否包含第一个STOP指令判断jump table是否完成初始化 // 使用是否包含第一个STOP指令判断jump table是否完成初始化
// 需要注意,后继如果新增指令,需要在这里判断硬分叉,指定不同的指令集 // 需要注意,后继如果新增指令,需要在这里判断硬分叉,指定不同的指令集
...@@ -67,7 +69,7 @@ func (in *Interpreter) enforceRestrictions(op OpCode, operation Operation, stack ...@@ -67,7 +69,7 @@ func (in *Interpreter) enforceRestrictions(op OpCode, operation Operation, stack
return nil return nil
} }
// 合约代码的解释执行主逻辑 // Run 合约代码的解释执行主逻辑
// 需要注意的是,如果返回执行出错,依然会扣除剩余的Gas // 需要注意的是,如果返回执行出错,依然会扣除剩余的Gas
// (除非返回的是ErrExecutionReverted,这种情况下会保留剩余的Gas) // (除非返回的是ErrExecutionReverted,这种情况下会保留剩余的Gas)
func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err error) { func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err error) {
...@@ -201,7 +203,7 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er ...@@ -201,7 +203,7 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er
// 目前只按需构造必要的参数,理论上GasFun进行Gas计算时可以使用Contract中的所有参数 // 目前只按需构造必要的参数,理论上GasFun进行Gas计算时可以使用Contract中的所有参数
// 后继视需要修改GasParam结构 // 后继视需要修改GasParam结构
func buildGasParam(contract *Contract) *params.GasParam { func buildGasParam(contract *Contract) *params.GasParam {
return &params.GasParam{contract.Gas, contract.Address()} return &params.GasParam{Gas: contract.Gas, Address: contract.Address()}
} }
// 从EVM构造参数传递给GasFunc逻辑使用 // 从EVM构造参数传递给GasFunc逻辑使用
......
...@@ -15,44 +15,60 @@ import ( ...@@ -15,44 +15,60 @@ import (
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/mm" "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/mm"
) )
// Tracer接口用来在合约执行过程中收集跟踪数据。 // Tracer 接口用来在合约执行过程中收集跟踪数据。
// CaptureState 会在EVM解释每条指令时调用。 // CaptureState 会在EVM解释每条指令时调用。
// 需要注意的是,传入的引用参数不允许修改,否则会影响EVM解释执行;如果需要使用其中的数据,请复制后使用。 // 需要注意的是,传入的引用参数不允许修改,否则会影响EVM解释执行;如果需要使用其中的数据,请复制后使用。
type Tracer interface { type Tracer interface {
// CaptureStart 开始记录
CaptureStart(from common.Address, to common.Address, call bool, input []byte, gas uint64, value uint64) error CaptureStart(from common.Address, to common.Address, call bool, input []byte, gas uint64, value uint64) error
// CaptureState 保存状态
CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, stack *mm.Stack, contract *Contract, depth int, err error) error CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, stack *mm.Stack, contract *Contract, depth int, err error) error
// CaptureFault 保存错误
CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, stack *mm.Stack, contract *Contract, depth int, err error) error CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, stack *mm.Stack, contract *Contract, depth int, err error) error
// CaptureEnd 结束记录
CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error
} }
// 使用json格式打印日志 // JSONLogger 使用json格式打印日志
type JSONLogger struct { type JSONLogger struct {
encoder *json.Encoder encoder *json.Encoder
} }
// 指令执行状态信息 // StructLog 指令执行状态信息
type StructLog struct { type StructLog struct {
Pc uint64 `json:"pc"` // Pc pc指针
Op string `json:"op"` Pc uint64 `json:"pc"`
Gas uint64 `json:"gas"` // Op 操作码
GasCost uint64 `json:"gasCost"` Op string `json:"op"`
Memory []string `json:"memory"` // Gas gas
MemorySize int `json:"memSize"` Gas uint64 `json:"gas"`
Stack []string `json:"stack"` // GasCost 花费
Storage map[common.Hash]common.Hash `json:"-"` GasCost uint64 `json:"gasCost"`
Depth int `json:"depth"` // Memory 内存对象
Err error `json:"-"` Memory []string `json:"memory"`
// MemorySize 内存大小
MemorySize int `json:"memSize"`
// Stack 栈对象
Stack []string `json:"stack"`
// Storage 存储对象
Storage map[common.Hash]common.Hash `json:"-"`
// Depth 调用深度
Depth int `json:"depth"`
// Err 错误信息
Err error `json:"-"`
} }
// NewJSONLogger 创建新的日志记录器
func NewJSONLogger(writer io.Writer) *JSONLogger { func NewJSONLogger(writer io.Writer) *JSONLogger {
return &JSONLogger{json.NewEncoder(writer)} return &JSONLogger{json.NewEncoder(writer)}
} }
// CaptureStart 开始记录
func (logger *JSONLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value uint64) error { func (logger *JSONLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value uint64) error {
return nil return nil
} }
// CaptureState outputs state information on the logger. // CaptureState 输出当前虚拟机状态
func (logger *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, stack *mm.Stack, contract *Contract, depth int, err error) error { func (logger *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, stack *mm.Stack, contract *Contract, depth int, err error) error {
log := StructLog{ log := StructLog{
Pc: pc, Pc: pc,
...@@ -72,7 +88,6 @@ func (logger *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ...@@ -72,7 +88,6 @@ func (logger *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost
func formatStack(data []*big.Int) (res []string) { func formatStack(data []*big.Int) (res []string) {
for _, v := range data { for _, v := range data {
res = append(res, v.Text(16)) res = append(res, v.Text(16))
v.String()
} }
return return
} }
...@@ -84,12 +99,12 @@ func formatMemory(data []byte) (res []string) { ...@@ -84,12 +99,12 @@ func formatMemory(data []byte) (res []string) {
return return
} }
// CaptureFault outputs state information on the logger. // CaptureFault 目前实现为空
func (logger *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, stack *mm.Stack, contract *Contract, depth int, err error) error { func (logger *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, stack *mm.Stack, contract *Contract, depth int, err error) error {
return nil return nil
} }
// CaptureEnd is triggered at end of execution. // CaptureEnd 结束记录
func (logger *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error { func (logger *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error {
type endLog struct { type endLog struct {
Output string `json:"output"` Output string `json:"output"`
......
...@@ -4,10 +4,10 @@ ...@@ -4,10 +4,10 @@
package runtime package runtime
// EVM操作码定义,本质上就是一个字节,所以操作码最多只支持256个 // OpCode EVM操作码定义,本质上就是一个字节,所以操作码最多只支持256个
type OpCode byte type OpCode byte
// 是否为压栈操作 // IsPush 是否为压栈操作
func (op OpCode) IsPush() bool { func (op OpCode) IsPush() bool {
if op >= PUSH1 && op <= PUSH32 { if op >= PUSH1 && op <= PUSH32 {
return true return true
...@@ -15,14 +15,14 @@ func (op OpCode) IsPush() bool { ...@@ -15,14 +15,14 @@ func (op OpCode) IsPush() bool {
return false return false
} }
// 是否为跳转操作 // IsStaticJump 是否为跳转操作
func (op OpCode) IsStaticJump() bool { func (op OpCode) IsStaticJump() bool {
return op == JUMP return op == JUMP
} }
var opmap map[OpCode]string var opmap map[OpCode]string
// 是否为跳转操作 // String 打印字符串形式
func (op OpCode) String() string { func (op OpCode) String() string {
if opmap == nil { if opmap == nil {
initMap() initMap()
...@@ -197,178 +197,310 @@ func initMap() { ...@@ -197,178 +197,310 @@ func initMap() {
// unofficial opcodes used for parsing // unofficial opcodes used for parsing
const ( const (
// PUSH 压栈操作
PUSH OpCode = 0xb0 + iota PUSH OpCode = 0xb0 + iota
// DUP 操作
DUP DUP
// SWAP 操作
SWAP SWAP
) )
const ( const (
// 0x0 算术操作 // STOP 0x0 算术操作
STOP OpCode = iota STOP OpCode = iota
// ADD 操作
ADD ADD
// MUL op
MUL MUL
// SUB op
SUB SUB
// DIV op
DIV DIV
// SDIV op
SDIV SDIV
// MOD op
MOD MOD
// SMOD op
SMOD SMOD
// ADDMOD op
ADDMOD ADDMOD
// MULMOD op
MULMOD MULMOD
// EXP op
EXP EXP
// SIGNEXTEND op
SIGNEXTEND SIGNEXTEND
) )
const ( const (
// 比较、位操作 // LT 比较、位操作
LT OpCode = iota + 0x10 LT OpCode = iota + 0x10
// GT op
GT GT
// SLT op
SLT SLT
// SGT op
SGT SGT
// EQ op
EQ EQ
// ISZERO op
ISZERO ISZERO
// AND op
AND AND
// OR op
OR OR
// XOR op
XOR XOR
// NOT op
NOT NOT
// BYTE op
BYTE BYTE
// SHL op
SHL SHL
// SHR op
SHR SHR
// SAR op
SAR SAR
// SHA3 op
SHA3 = 0x20 SHA3 = 0x20
) )
const ( const (
// 0x30 合约数据操作 // ADDRESS 0x30 合约数据操作
ADDRESS OpCode = 0x30 + iota ADDRESS OpCode = 0x30 + iota
// BALANCE op
BALANCE BALANCE
// ORIGIN op
ORIGIN ORIGIN
// CALLER op
CALLER CALLER
// CALLVALUE op
CALLVALUE CALLVALUE
// CALLDATALOAD op
CALLDATALOAD CALLDATALOAD
// CALLDATASIZE op
CALLDATASIZE CALLDATASIZE
// CALLDATACOPY op
CALLDATACOPY CALLDATACOPY
// CODESIZE op
CODESIZE CODESIZE
// CODECOPY op
CODECOPY CODECOPY
// GASPRICE op
GASPRICE GASPRICE
// EXTCODESIZE op
EXTCODESIZE EXTCODESIZE
// EXTCODECOPY op
EXTCODECOPY EXTCODECOPY
// RETURNDATASIZE op
RETURNDATASIZE RETURNDATASIZE
// RETURNDATACOPY op
RETURNDATACOPY RETURNDATACOPY
) )
const ( const (
// 0x40 区块相关操作 // BLOCKHASH 0x40 区块相关操作
BLOCKHASH OpCode = 0x40 + iota BLOCKHASH OpCode = 0x40 + iota
// COINBASE op
COINBASE COINBASE
// TIMESTAMP op
TIMESTAMP TIMESTAMP
// NUMBER op
NUMBER NUMBER
// DIFFICULTY op
DIFFICULTY DIFFICULTY
// GASLIMIT op
GASLIMIT GASLIMIT
) )
const ( const (
// 0x50 存储相关操作 // POP 0x50 存储相关操作
POP OpCode = 0x50 + iota POP OpCode = 0x50 + iota
// MLOAD op
MLOAD MLOAD
// MSTORE op
MSTORE MSTORE
// MSTORE8 op
MSTORE8 MSTORE8
// SLOAD op
SLOAD SLOAD
// SSTORE op
SSTORE SSTORE
// JUMP op
JUMP JUMP
// JUMPI op
JUMPI JUMPI
// PC op
PC PC
// MSIZE op
MSIZE MSIZE
// GAS op
GAS GAS
// JUMPDEST op
JUMPDEST JUMPDEST
) )
const ( const (
// 0x60 栈操作 // PUSH1 0x60 栈操作
PUSH1 OpCode = 0x60 + iota PUSH1 OpCode = 0x60 + iota
// PUSH2 op
PUSH2 PUSH2
// PUSH3 op
PUSH3 PUSH3
// PUSH4 op
PUSH4 PUSH4
// PUSH5 op
PUSH5 PUSH5
// PUSH6 op
PUSH6 PUSH6
// PUSH7 op
PUSH7 PUSH7
// PUSH8 op
PUSH8 PUSH8
// PUSH9 op
PUSH9 PUSH9
// PUSH10 op
PUSH10 PUSH10
// PUSH11 op
PUSH11 PUSH11
// PUSH12 op
PUSH12 PUSH12
// PUSH13 op
PUSH13 PUSH13
// PUSH14 op
PUSH14 PUSH14
// PUSH15 op
PUSH15 PUSH15
// PUSH16 op
PUSH16 PUSH16
// PUSH17 op
PUSH17 PUSH17
// PUSH18 op
PUSH18 PUSH18
// PUSH19 op
PUSH19 PUSH19
// PUSH20 op
PUSH20 PUSH20
// PUSH21 op
PUSH21 PUSH21
// PUSH22 op
PUSH22 PUSH22
// PUSH23 op
PUSH23 PUSH23
// PUSH24 op
PUSH24 PUSH24
// PUSH25 op
PUSH25 PUSH25
// PUSH26 op
PUSH26 PUSH26
// PUSH27 op
PUSH27 PUSH27
// PUSH28 op
PUSH28 PUSH28
// PUSH29 op
PUSH29 PUSH29
// PUSH30 op
PUSH30 PUSH30
// PUSH31 op
PUSH31 PUSH31
// PUSH32 op
PUSH32 PUSH32
// DUP1 op
DUP1 DUP1
// DUP2 op
DUP2 DUP2
// DUP3 op
DUP3 DUP3
// DUP4 op
DUP4 DUP4
// DUP5 op
DUP5 DUP5
// DUP6 op
DUP6 DUP6
// DUP7 op
DUP7 DUP7
// DUP8 op
DUP8 DUP8
// DUP9 op
DUP9 DUP9
// DUP10 op
DUP10 DUP10
// DUP11 op
DUP11 DUP11
// DUP12 op
DUP12 DUP12
// DUP13 op
DUP13 DUP13
// DUP14 op
DUP14 DUP14
// DUP15 op
DUP15 DUP15
// DUP16 op
DUP16 DUP16
// SWAP1 op
SWAP1 SWAP1
// SWAP2 op
SWAP2 SWAP2
// SWAP3 op
SWAP3 SWAP3
// SWAP4 op
SWAP4 SWAP4
// SWAP5 op
SWAP5 SWAP5
// SWAP6 op
SWAP6 SWAP6
// SWAP7 op
SWAP7 SWAP7
// SWAP8 op
SWAP8 SWAP8
// SWAP9 op
SWAP9 SWAP9
// SWAP10 op
SWAP10 SWAP10
// SWAP11 op
SWAP11 SWAP11
// SWAP12 op
SWAP12 SWAP12
// SWAP13 op
SWAP13 SWAP13
// SWAP14 op
SWAP14 SWAP14
// SWAP15 op
SWAP15 SWAP15
// SWAP16 op
SWAP16 SWAP16
) )
const ( const (
// 生成日志 // LOG0 生成日志
LOG0 OpCode = 0xa0 + iota LOG0 OpCode = 0xa0 + iota
// LOG1 op
LOG1 LOG1
// LOG2 op
LOG2 LOG2
// LOG3 op
LOG3 LOG3
// LOG4 op
LOG4 LOG4
) )
const ( const (
// 过程调用 // CREATE 过程调用
CREATE OpCode = 0xf0 + iota CREATE OpCode = 0xf0 + iota
// CALL op
CALL CALL
// CALLCODE op
CALLCODE CALLCODE
// RETURN op
RETURN RETURN
// DELEGATECALL op
DELEGATECALL DELEGATECALL
// STATICCALL op
STATICCALL = 0xfa STATICCALL = 0xfa
REVERT = 0xfd // REVERT op
REVERT = 0xfd
// SELFDESTRUCT op
SELFDESTRUCT = 0xff SELFDESTRUCT = 0xff
) )
...@@ -12,8 +12,7 @@ import ( ...@@ -12,8 +12,7 @@ import (
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types" evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
) )
// 本文件用来存储硬分叉中需要用到的数据 // BlockData 本文件用来存储硬分叉中需要用到的数据
type BlockData struct { type BlockData struct {
blockHeight int64 blockHeight int64
testnet bool testnet bool
...@@ -21,9 +20,11 @@ type BlockData struct { ...@@ -21,9 +20,11 @@ type BlockData struct {
txs map[string]*TxData txs map[string]*TxData
} }
// TxData 交易数据
type TxData struct { type TxData struct {
// KV 交易生成的KV数据
KV map[string][]byte KV map[string][]byte
// Key 为logType_logIndex // Logs Key 为logType_logIndex
Logs map[string][]byte Logs map[string][]byte
} }
...@@ -47,6 +48,7 @@ func makeLogReceiptKey(logType int32, logIndex int) string { ...@@ -47,6 +48,7 @@ func makeLogReceiptKey(logType int32, logIndex int) string {
return fmt.Sprintf("%v_%v", logType, logIndex) return fmt.Sprintf("%v_%v", logType, logIndex)
} }
// InitForkData 初始化硬分叉数据
func InitForkData() { func InitForkData() {
forkData = make(map[int64]*BlockData) forkData = make(map[int64]*BlockData)
...@@ -72,6 +74,7 @@ func InitForkData() { ...@@ -72,6 +74,7 @@ func InitForkData() {
forkData[556294] = data forkData[556294] = data
} }
// ProcessFork 处理硬分叉逻辑
func ProcessFork(blockHeight int64, txHash []byte, receipt *types.Receipt) { func ProcessFork(blockHeight int64, txHash []byte, receipt *types.Receipt) {
if types.IsLocal() { if types.IsLocal() {
return return
......
...@@ -9,69 +9,69 @@ import ( ...@@ -9,69 +9,69 @@ import (
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/model" "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/model"
) )
// 状态数据库封装,面向EVM业务执行逻辑; // EVMStateDB 状态数据库封装,面向EVM业务执行逻辑;
// 生命周期为一个区块,在同一个区块内多个交易执行时使用的是同一个StateDB实例; // 生命周期为一个区块,在同一个区块内多个交易执行时使用的是同一个StateDB实例;
// StateDB包含区块的状态和交易的状态(当前上下文),所以不支持并发操作,区块内的多个交易只能按顺序单线程执行; // StateDB包含区块的状态和交易的状态(当前上下文),所以不支持并发操作,区块内的多个交易只能按顺序单线程执行;
// StateDB除了查询状态数据,还会保留在交易执行时对数据的变更信息,每个交易完成之后会返回变更影响的数据给执行器; // StateDB除了查询状态数据,还会保留在交易执行时对数据的变更信息,每个交易完成之后会返回变更影响的数据给执行器;
type StateDB interface { type EVMStateDB interface {
// 创建新的合约对象 // CreateAccount 创建新的合约对象
CreateAccount(string, string, string, string) CreateAccount(string, string, string, string)
// 从指定地址扣除金额 // SubBalance 从指定地址扣除金额
SubBalance(string, string, uint64) SubBalance(string, string, uint64)
// 向指定地址增加金额 // AddBalance 向指定地址增加金额
AddBalance(string, string, uint64) AddBalance(string, string, uint64)
// 获取指定地址的余额 // GetBalance 获取指定地址的余额
GetBalance(string) uint64 GetBalance(string) uint64
// 获取nonce值(只有合约对象有,外部对象为0) // GetNonce 获取nonce值(只有合约对象有,外部对象为0)
GetNonce(string) uint64 GetNonce(string) uint64
// 设置nonce值(只有合约对象有,外部对象为0) // SetNonce 设置nonce值(只有合约对象有,外部对象为0)
SetNonce(string, uint64) SetNonce(string, uint64)
// 获取指定地址合约的代码哈希 // GetCodeHash 获取指定地址合约的代码哈希
GetCodeHash(string) common.Hash GetCodeHash(string) common.Hash
// 获取指定地址合约代码 // GetCode 获取指定地址合约代码
GetCode(string) []byte GetCode(string) []byte
// 设置指定地址合约代码 // SetCode 设置指定地址合约代码
SetCode(string, []byte) SetCode(string, []byte)
// 获取指定地址合约代码大小 // GetCodeSize 获取指定地址合约代码大小
GetCodeSize(string) int GetCodeSize(string) int
// 合约Gas奖励回馈 // AddRefund 合约Gas奖励回馈
AddRefund(uint64) AddRefund(uint64)
// 获取合约Gas奖励 // GetRefund 获取合约Gas奖励
GetRefund() uint64 GetRefund() uint64
// 获取合约状态数据 // GetState 获取合约状态数据
GetState(string, common.Hash) common.Hash GetState(string, common.Hash) common.Hash
// 设置合约状态数据 // SetState 设置合约状态数据
SetState(string, common.Hash, common.Hash) SetState(string, common.Hash, common.Hash)
// 合约自销毁 // Suicide 合约自销毁
Suicide(string) bool Suicide(string) bool
// 合约是否已经销毁 // HasSuicided 合约是否已经销毁
HasSuicided(string) bool HasSuicided(string) bool
// 判断一个合约地址是否存在(已经销毁的合约地址对象依然存在) // Exist 判断一个合约地址是否存在(已经销毁的合约地址对象依然存在)
Exist(string) bool Exist(string) bool
// 判断一个合约地址是否为空(不包含任何代码、也没有余额的合约为空) // Empty 判断一个合约地址是否为空(不包含任何代码、也没有余额的合约为空)
Empty(string) bool Empty(string) bool
// 回滚到制定版本(从当前版本到回滚版本之间的数据变更全部撤销) // RevertToSnapshot 回滚到制定版本(从当前版本到回滚版本之间的数据变更全部撤销)
RevertToSnapshot(int) RevertToSnapshot(int)
// 生成一个新版本号(递增操作) // Snapshot 生成一个新版本号(递增操作)
Snapshot() int Snapshot() int
// 转换合约状态数据存储 // TransferStateData 转换合约状态数据存储
TransferStateData(addr string) TransferStateData(addr string)
// 添加新的日志信息 // AddLog 添加新的日志信息
AddLog(*model.ContractLog) AddLog(*model.ContractLog)
// 添加sha3记录 // AddPreimage 添加sha3记录
AddPreimage(common.Hash, []byte) AddPreimage(common.Hash, []byte)
// 当前账户余额是否足够转账 // CanTransfer 当前账户余额是否足够转账
CanTransfer(sender, recipient string, amount uint64) bool CanTransfer(sender, recipient string, amount uint64) bool
// 转账交易 // Transfer 转账交易
Transfer(sender, recipient string, amount uint64) bool Transfer(sender, recipient string, amount uint64) bool
} }
...@@ -12,7 +12,7 @@ import ( ...@@ -12,7 +12,7 @@ import (
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types" evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
) )
// 数据状态变更接口 // DataChange 数据状态变更接口
// 所有的数据状态变更事件实现此接口,并且封装各自的变更数据以及回滚动作 // 所有的数据状态变更事件实现此接口,并且封装各自的变更数据以及回滚动作
// 在调用合约时(具体的Tx执行时),会根据操作生成对应的变更对象并缓存下来 // 在调用合约时(具体的Tx执行时),会根据操作生成对应的变更对象并缓存下来
// 如果合约执行出错,会按生成顺序的倒序,依次调用变更对象的回滚接口进行数据回滚,并同步删除变更对象缓存 // 如果合约执行出错,会按生成顺序的倒序,依次调用变更对象的回滚接口进行数据回滚,并同步删除变更对象缓存
...@@ -23,14 +23,15 @@ type DataChange interface { ...@@ -23,14 +23,15 @@ type DataChange interface {
getLog(mdb *MemoryStateDB) []*types.ReceiptLog getLog(mdb *MemoryStateDB) []*types.ReceiptLog
} }
// 版本结构,包含版本号以及当前版本包含的变更对象在变更序列中的开始序号 // Snapshot 版本结构,包含版本号以及当前版本包含的变更对象在变更序列中的开始序号
type Snapshot struct { type Snapshot struct {
id int id int
entries []DataChange entries []DataChange
statedb *MemoryStateDB statedb *MemoryStateDB
} }
func (ver *Snapshot) GetId() int { // GetID 获取ID
func (ver *Snapshot) GetID() int {
return ver.id return ver.id
} }
......
...@@ -32,35 +32,39 @@ func init() { ...@@ -32,35 +32,39 @@ func init() {
types.RegisterDappFork(ExecutorName, "Enable", 500000) types.RegisterDappFork(ExecutorName, "Enable", 500000)
} }
// EvmType EVM类型定义
type EvmType struct { type EvmType struct {
types.ExecTypeBase types.ExecTypeBase
} }
// NewType 新建EVM类型对象
func NewType() *EvmType { func NewType() *EvmType {
c := &EvmType{} c := &EvmType{}
c.SetChild(c) c.SetChild(c)
return c return c
} }
// GetPayload 获取消息负载结构
func (evm *EvmType) GetPayload() types.Message { func (evm *EvmType) GetPayload() types.Message {
return &EVMContractAction{} return &EVMContractAction{}
} }
// ActionName 获取ActionName
func (evm EvmType) ActionName(tx *types.Transaction) string { func (evm EvmType) ActionName(tx *types.Transaction) string {
// 这个需要通过合约交易目标地址来判断Action // 这个需要通过合约交易目标地址来判断Action
// 如果目标地址为空,或为evm的固定合约地址,则为创建合约,否则为调用合约 // 如果目标地址为空,或为evm的固定合约地址,则为创建合约,否则为调用合约
if strings.EqualFold(tx.To, address.ExecAddress(types.ExecName(ExecutorName))) { if strings.EqualFold(tx.To, address.ExecAddress(types.ExecName(ExecutorName))) {
return "createEvmContract" return "createEvmContract"
} else {
return "callEvmContract"
} }
return "unknown" return "callEvmContract"
} }
// GetTypeMap 获取类型映射
func (evm *EvmType) GetTypeMap() map[string]int32 { func (evm *EvmType) GetTypeMap() map[string]int32 {
return actionName return actionName
} }
// GetRealToAddr 获取实际地址
func (evm EvmType) GetRealToAddr(tx *types.Transaction) string { func (evm EvmType) GetRealToAddr(tx *types.Transaction) string {
if string(tx.Execer) == ExecutorName { if string(tx.Execer) == ExecutorName {
return tx.To return tx.To
...@@ -73,13 +77,14 @@ func (evm EvmType) GetRealToAddr(tx *types.Transaction) string { ...@@ -73,13 +77,14 @@ func (evm EvmType) GetRealToAddr(tx *types.Transaction) string {
return tx.To return tx.To
} }
// Amount 获取金额
func (evm EvmType) Amount(tx *types.Transaction) (int64, error) { func (evm EvmType) Amount(tx *types.Transaction) (int64, error) {
return 0, nil return 0, nil
} }
// CreateTx 创建交易对象
func (evm EvmType) CreateTx(action string, message json.RawMessage) (*types.Transaction, error) { func (evm EvmType) CreateTx(action string, message json.RawMessage) (*types.Transaction, error) {
elog.Debug("evm.CreateTx", "action", action) elog.Debug("evm.CreateTx", "action", action)
var tx *types.Transaction
if action == "CreateCall" { if action == "CreateCall" {
var param CreateCallTx var param CreateCallTx
err := json.Unmarshal(message, &param) err := json.Unmarshal(message, &param)
...@@ -87,76 +92,25 @@ func (evm EvmType) CreateTx(action string, message json.RawMessage) (*types.Tran ...@@ -87,76 +92,25 @@ func (evm EvmType) CreateTx(action string, message json.RawMessage) (*types.Tran
elog.Error("CreateTx", "Error", err) elog.Error("CreateTx", "Error", err)
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
return CreateRawEvmCreateCallTx(&param) return createRawEvmCreateCallTx(&param)
} else {
return nil, types.ErrNotSupport
} }
return nil, types.ErrNotSupport
return tx, nil
} }
// GetLogMap 获取日志类型映射
func (evm *EvmType) GetLogMap() map[int64]*types.LogInfo { func (evm *EvmType) GetLogMap() map[int64]*types.LogInfo {
return logInfo return logInfo
} }
type EvmCheckAddrExists struct { func createRawEvmCreateCallTx(parm *CreateCallTx) (*types.Transaction, error) {
}
func (t *EvmCheckAddrExists) JsonToProto(message json.RawMessage) ([]byte, error) {
var req CheckEVMAddrReq
err := json.Unmarshal(message, &req)
if err != nil {
return nil, err
}
return types.Encode(&req), nil
}
func (t *EvmCheckAddrExists) ProtoToJson(reply *types.Message) (interface{}, error) {
return reply, nil
}
type EvmEstimateGas struct {
}
func (t *EvmEstimateGas) JsonToProto(message json.RawMessage) ([]byte, error) {
var req EstimateEVMGasReq
err := json.Unmarshal(message, &req)
if err != nil {
return nil, err
}
return types.Encode(&req), nil
}
func (t *EvmEstimateGas) ProtoToJson(reply *types.Message) (interface{}, error) {
return reply, nil
}
type EvmDebug struct {
}
func (t *EvmDebug) JsonToProto(message json.RawMessage) ([]byte, error) {
var req EvmDebugReq
err := json.Unmarshal(message, &req)
if err != nil {
return nil, err
}
return types.Encode(&req), nil
}
func (t *EvmDebug) ProtoToJson(reply *types.Message) (interface{}, error) {
return reply, nil
}
//different with other exector, the name is defined by parm
func CreateRawEvmCreateCallTx(parm *CreateCallTx) (*types.Transaction, error) {
if parm == nil { if parm == nil {
elog.Error("CreateRawEvmCreateCallTx", "parm", parm) elog.Error("createRawEvmCreateCallTx", "parm", parm)
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
bCode, err := common.FromHex(parm.Code) bCode, err := common.FromHex(parm.Code)
if err != nil { if err != nil {
elog.Error("CreateRawEvmCreateCallTx", "parm.Code", parm.Code) elog.Error("createRawEvmCreateCallTx", "parm.Code", parm.Code)
return nil, err return nil, err
} }
......
...@@ -4,14 +4,24 @@ ...@@ -4,14 +4,24 @@
package types package types
// CreateCallTx 创建或调用合约交易结构
type CreateCallTx struct { type CreateCallTx struct {
Amount uint64 `json:"amount"` // Amount 金额
Code string `json:"code"` Amount uint64 `json:"amount"`
// Code 合约代码
Code string `json:"code"`
// GasLimit gas限制
GasLimit uint64 `json:"gasLimit"` GasLimit uint64 `json:"gasLimit"`
// GasPrice gas定价
GasPrice uint32 `json:"gasPrice"` GasPrice uint32 `json:"gasPrice"`
Note string `json:"note"` // Note 备注
Alias string `json:"alias"` Note string `json:"note"`
Fee int64 `json:"fee"` // Alias 合约别名
Name string `json:"name"` Alias string `json:"alias"`
IsCreate bool `json:"isCreate"` // Fee 交易手续费
Fee int64 `json:"fee"`
// Name 交易名称
Name string `json:"name"`
// IsCreate 是否创建合约
IsCreate bool `json:"isCreate"`
} }
...@@ -11,40 +11,39 @@ import ( ...@@ -11,40 +11,39 @@ import (
) )
const ( const (
// EvmCreateAction 创建合约
EvmCreateAction = 1 EvmCreateAction = 1
EvmCallAction = 2 // EvmCallAction 调用合约
EvmCallAction = 2
// 合约代码变更日志 // TyLogContractData 合约代码变更日志
TyLogContractData = 601 TyLogContractData = 601
// 合约状态数据变更日志 // TyLogContractState 合约状态数据变更日志
TyLogContractState = 602 TyLogContractState = 602
// 合约状态数据变更日志 // TyLogCallContract 合约状态数据变更日志
TyLogCallContract = 603 TyLogCallContract = 603
// 合约状态数据变更项日志 // TyLogEVMStateChangeItem 合约状态数据变更项日志
TyLogEVMStateChangeItem = 604 TyLogEVMStateChangeItem = 604
// 查询方法 // MaxGasLimit 最大Gas消耗上限
FuncCheckAddrExists = "CheckAddrExists"
FuncEstimateGas = "EstimateGas"
FuncEvmDebug = "EvmDebug"
// 最大Gas消耗上限
MaxGasLimit = 10000000 MaxGasLimit = 10000000
) )
var ( var (
// 本执行器前缀 // EvmPrefix 本执行器前缀
EvmPrefix = "user.evm." EvmPrefix = "user.evm."
// 本执行器名称 // ExecutorName 本执行器名称
ExecutorName = "evm" ExecutorName = "evm"
ExecerEvm = []byte(ExecutorName) // ExecerEvm EVM执行器名称
ExecerEvm = []byte(ExecutorName)
// UserPrefix 执行器前缀
UserPrefix = []byte(EvmPrefix) UserPrefix = []byte(EvmPrefix)
logInfo = map[int64]*types.LogInfo{ logInfo = map[int64]*types.LogInfo{
TyLogCallContract: {reflect.TypeOf(ReceiptEVMContract{}), "LogCallContract"}, TyLogCallContract: {Ty: reflect.TypeOf(ReceiptEVMContract{}), Name: "LogCallContract"},
TyLogContractData: {reflect.TypeOf(EVMContractData{}), "LogContractData"}, TyLogContractData: {Ty: reflect.TypeOf(EVMContractData{}), Name: "LogContractData"},
TyLogContractState: {reflect.TypeOf(EVMContractState{}), "LogContractState"}, TyLogContractState: {Ty: reflect.TypeOf(EVMContractState{}), Name: "LogContractState"},
TyLogEVMStateChangeItem: {reflect.TypeOf(EVMStateChangeItem{}), "LogEVMStateChangeItem"}, TyLogEVMStateChangeItem: {Ty: reflect.TypeOf(EVMStateChangeItem{}), Name: "LogEVMStateChangeItem"},
} }
) )
...@@ -6,6 +6,7 @@ package commands ...@@ -6,6 +6,7 @@ package commands
import "github.com/spf13/cobra" import "github.com/spf13/cobra"
// Cmd The command line is not used.
func Cmd() *cobra.Command { func Cmd() *cobra.Command {
return nil return nil
} }
...@@ -26,3 +26,8 @@ status: Create 1 -> Match 2 -> Cancel 3 -> Close 4 ...@@ -26,3 +26,8 @@ status: Create 1 -> Match 2 -> Cancel 3 -> Close 4
//1. 我的所有赌局,按照状态进行分类 (按照地址查询) //1. 我的所有赌局,按照状态进行分类 (按照地址查询)
//2. 系统所有正在进行的赌局 (按照时间进行排序) //2. 系统所有正在进行的赌局 (按照时间进行排序)
*/ */
//game 的状态变化:
// staus == 1 (创建,开始猜拳游戏)
// status == 2 (匹配,参与)
// status == 3 (取消)
// status == 4 (Close的情况)
...@@ -9,21 +9,25 @@ import ( ...@@ -9,21 +9,25 @@ import (
gt "github.com/33cn/plugin/plugin/dapp/game/types" gt "github.com/33cn/plugin/plugin/dapp/game/types"
) )
// Exec_Create Create game
func (g *Game) Exec_Create(payload *gt.GameCreate, tx *types.Transaction, index int) (*types.Receipt, error) { func (g *Game) Exec_Create(payload *gt.GameCreate, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(g, tx, index) action := NewAction(g, tx, index)
return action.GameCreate(payload) return action.GameCreate(payload)
} }
// Exec_Cancel Cancel game
func (g *Game) Exec_Cancel(payload *gt.GameCancel, tx *types.Transaction, index int) (*types.Receipt, error) { func (g *Game) Exec_Cancel(payload *gt.GameCancel, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(g, tx, index) action := NewAction(g, tx, index)
return action.GameCancel(payload) return action.GameCancel(payload)
} }
// Exec_Close Close game
func (g *Game) Exec_Close(payload *gt.GameClose, tx *types.Transaction, index int) (*types.Receipt, error) { func (g *Game) Exec_Close(payload *gt.GameClose, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(g, tx, index) action := NewAction(g, tx, index)
return action.GameClose(payload) return action.GameClose(payload)
} }
// Exec_Match Match game
func (g *Game) Exec_Match(payload *gt.GameMatch, tx *types.Transaction, index int) (*types.Receipt, error) { func (g *Game) Exec_Match(payload *gt.GameMatch, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(g, tx, index) action := NewAction(g, tx, index)
return action.GameMatch(payload) return action.GameMatch(payload)
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
gt "github.com/33cn/plugin/plugin/dapp/game/types" gt "github.com/33cn/plugin/plugin/dapp/game/types"
) )
// roll back local db data
func (g *Game) execDelLocal(receiptData *types.ReceiptData) (*types.LocalDBSet, error) { func (g *Game) execDelLocal(receiptData *types.ReceiptData) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{} dbSet := &types.LocalDBSet{}
if receiptData.GetTy() != types.ExecOk { if receiptData.GetTy() != types.ExecOk {
...@@ -28,18 +29,22 @@ func (g *Game) execDelLocal(receiptData *types.ReceiptData) (*types.LocalDBSet, ...@@ -28,18 +29,22 @@ func (g *Game) execDelLocal(receiptData *types.ReceiptData) (*types.LocalDBSet,
return dbSet, nil return dbSet, nil
} }
// ExecDelLocal_Create roll back local db data for create
func (g *Game) ExecDelLocal_Create(payload *gt.GameCreate, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (g *Game) ExecDelLocal_Create(payload *gt.GameCreate, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execDelLocal(receiptData) return g.execDelLocal(receiptData)
} }
// ExecDelLocal_Cancel roll back local db data for cancel
func (g *Game) ExecDelLocal_Cancel(payload *gt.GameCancel, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (g *Game) ExecDelLocal_Cancel(payload *gt.GameCancel, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execDelLocal(receiptData) return g.execDelLocal(receiptData)
} }
// ExecDelLocal_Close roll back local db data for close
func (g *Game) ExecDelLocal_Close(payload *gt.GameClose, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (g *Game) ExecDelLocal_Close(payload *gt.GameClose, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execDelLocal(receiptData) return g.execDelLocal(receiptData)
} }
// ExecDelLocal_Match roll back local db data for match
func (g *Game) ExecDelLocal_Match(payload *gt.GameMatch, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (g *Game) ExecDelLocal_Match(payload *gt.GameMatch, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execDelLocal(receiptData) return g.execDelLocal(receiptData)
} }
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
gt "github.com/33cn/plugin/plugin/dapp/game/types" gt "github.com/33cn/plugin/plugin/dapp/game/types"
) )
// save receiptData to local db
func (g *Game) execLocal(receiptData *types.ReceiptData) (*types.LocalDBSet, error) { func (g *Game) execLocal(receiptData *types.ReceiptData) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{} dbSet := &types.LocalDBSet{}
if receiptData.GetTy() != types.ExecOk { if receiptData.GetTy() != types.ExecOk {
...@@ -28,18 +29,22 @@ func (g *Game) execLocal(receiptData *types.ReceiptData) (*types.LocalDBSet, err ...@@ -28,18 +29,22 @@ func (g *Game) execLocal(receiptData *types.ReceiptData) (*types.LocalDBSet, err
return dbSet, nil return dbSet, nil
} }
// ExecLocal_Create save receiptData for create
func (g *Game) ExecLocal_Create(payload *gt.GameCreate, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (g *Game) ExecLocal_Create(payload *gt.GameCreate, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execLocal(receiptData) return g.execLocal(receiptData)
} }
// ExecLocal_Cancel save receiptData for cancel
func (g *Game) ExecLocal_Cancel(payload *gt.GameCancel, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (g *Game) ExecLocal_Cancel(payload *gt.GameCancel, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execLocal(receiptData) return g.execLocal(receiptData)
} }
// ExecLocal_Close save receiptData for close
func (g *Game) ExecLocal_Close(payload *gt.GameClose, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (g *Game) ExecLocal_Close(payload *gt.GameClose, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execLocal(receiptData) return g.execLocal(receiptData)
} }
// ExecLocal_Match save receiptData for Match
func (g *Game) ExecLocal_Match(payload *gt.GameMatch, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (g *Game) ExecLocal_Match(payload *gt.GameMatch, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execLocal(receiptData) return g.execLocal(receiptData)
} }
...@@ -22,32 +22,36 @@ func init() { ...@@ -22,32 +22,36 @@ func init() {
ety.InitFuncList(types.ListMethod(&Game{})) ety.InitFuncList(types.ListMethod(&Game{}))
} }
// Init register dapp
func Init(name string, sub []byte) { func Init(name string, sub []byte) {
drivers.Register(GetName(), newGame, types.GetDappFork(driverName, "Enable")) drivers.Register(GetName(), newGame, types.GetDappFork(driverName, "Enable"))
} }
// Game the game inherits all the attributes of the driverBase.
type Game struct { type Game struct {
drivers.DriverBase drivers.DriverBase
} }
func newGame() drivers.Driver { func newGame() drivers.Driver {
t := &Game{} g := &Game{}
t.SetChild(t) g.SetChild(g)
t.SetExecutorType(types.LoadExecutorType(driverName)) g.SetExecutorType(types.LoadExecutorType(driverName))
return t return g
} }
// GetName get name
func GetName() string { func GetName() string {
return newGame().GetName() return newGame().GetName()
} }
// GetDriverName get driver name
func (g *Game) GetDriverName() string { func (g *Game) GetDriverName() string {
return driverName return driverName
} }
//更新索引 // update Index
func (g *Game) updateIndex(log *gt.ReceiptGame) (kvs []*types.KeyValue) { func (g *Game) updateIndex(log *gt.ReceiptGame) (kvs []*types.KeyValue) {
//先保存本次Action产生的索引 // save the index generated by this action first.
kvs = append(kvs, addGameAddrIndex(log.Status, log.GameId, log.Addr, log.Index)) kvs = append(kvs, addGameAddrIndex(log.Status, log.GameId, log.Addr, log.Index))
kvs = append(kvs, addGameStatusIndex(log.Status, log.GameId, log.Index)) kvs = append(kvs, addGameStatusIndex(log.Status, log.GameId, log.Index))
if log.Status == gt.GameActionMatch { if log.Status == gt.GameActionMatch {
...@@ -69,9 +73,9 @@ func (g *Game) updateIndex(log *gt.ReceiptGame) (kvs []*types.KeyValue) { ...@@ -69,9 +73,9 @@ func (g *Game) updateIndex(log *gt.ReceiptGame) (kvs []*types.KeyValue) {
return kvs return kvs
} }
//回滚索引 // rollback Index
func (g *Game) rollbackIndex(log *gt.ReceiptGame) (kvs []*types.KeyValue) { func (g *Game) rollbackIndex(log *gt.ReceiptGame) (kvs []*types.KeyValue) {
//先删除本次Action产生的索引
kvs = append(kvs, delGameAddrIndex(log.Status, log.Addr, log.Index)) kvs = append(kvs, delGameAddrIndex(log.Status, log.Addr, log.Index))
kvs = append(kvs, delGameStatusIndex(log.Status, log.Index)) kvs = append(kvs, delGameStatusIndex(log.Status, log.Index))
...@@ -112,21 +116,21 @@ func calcGameAddrIndexPrefix(status int32, addr string) []byte { ...@@ -112,21 +116,21 @@ func calcGameAddrIndexPrefix(status int32, addr string) []byte {
key := fmt.Sprintf("LODB-game-addr:%d:%s:", status, addr) key := fmt.Sprintf("LODB-game-addr:%d:%s:", status, addr)
return []byte(key) return []byte(key)
} }
func addGameStatusIndex(status int32, gameId string, index int64) *types.KeyValue { func addGameStatusIndex(status int32, gameID string, index int64) *types.KeyValue {
kv := &types.KeyValue{} kv := &types.KeyValue{}
kv.Key = calcGameStatusIndexKey(status, index) kv.Key = calcGameStatusIndexKey(status, index)
record := &gt.GameRecord{ record := &gt.GameRecord{
GameId: gameId, GameId: gameID,
Index: index, Index: index,
} }
kv.Value = types.Encode(record) kv.Value = types.Encode(record)
return kv return kv
} }
func addGameAddrIndex(status int32, gameId, addr string, index int64) *types.KeyValue { func addGameAddrIndex(status int32, gameID, addr string, index int64) *types.KeyValue {
kv := &types.KeyValue{} kv := &types.KeyValue{}
kv.Key = calcGameAddrIndexKey(status, addr, index) kv.Key = calcGameAddrIndexKey(status, addr, index)
record := &gt.GameRecord{ record := &gt.GameRecord{
GameId: gameId, GameId: gameID,
Index: index, Index: index,
} }
kv.Value = types.Encode(record) kv.Value = types.Encode(record)
...@@ -146,19 +150,23 @@ func delGameAddrIndex(status int32, addr string, index int64) *types.KeyValue { ...@@ -146,19 +150,23 @@ func delGameAddrIndex(status int32, addr string, index int64) *types.KeyValue {
return kv return kv
} }
// ReplyGameList the data structure returned when querying the game list.
type ReplyGameList struct { type ReplyGameList struct {
Games []*Game `json:"games"` Games []*Game `json:"games"`
} }
// ReplyGame the data structure returned when querying a single game.
type ReplyGame struct { type ReplyGame struct {
Game *Game `json:"game"` Game *Game `json:"game"`
} }
func (c *Game) GetPayloadValue() types.Message { // GetPayloadValue get payload value
func (g *Game) GetPayloadValue() types.Message {
return &gt.GameAction{} return &gt.GameAction{}
} }
func (c *Game) GetTypeMap() map[string]int32 { // GetTypeMap get TypeMap
func (g *Game) GetTypeMap() map[string]int32 {
return map[string]int32{ return map[string]int32{
"Create": gt.GameActionCreate, "Create": gt.GameActionCreate,
"Match": gt.GameActionMatch, "Match": gt.GameActionMatch,
......
This diff is collapsed.
...@@ -9,18 +9,22 @@ import ( ...@@ -9,18 +9,22 @@ import (
gt "github.com/33cn/plugin/plugin/dapp/game/types" gt "github.com/33cn/plugin/plugin/dapp/game/types"
) )
// Query_QueryGameListByIds query game list by gameIDs
func (g *Game) Query_QueryGameListByIds(in *gt.QueryGameInfos) (types.Message, error) { func (g *Game) Query_QueryGameListByIds(in *gt.QueryGameInfos) (types.Message, error) {
return Infos(g.GetStateDB(), in) return QueryGameListByIds(g.GetStateDB(), in)
} }
// Query_QueryGameListCount query game count by status and addr
func (g *Game) Query_QueryGameListCount(in *gt.QueryGameListCount) (types.Message, error) { func (g *Game) Query_QueryGameListCount(in *gt.QueryGameListCount) (types.Message, error) {
return QueryGameListCount(g.GetStateDB(), in) return QueryGameListCount(g.GetStateDB(), in)
} }
// Query_QueryGameListByStatusAndAddr query game list by status and addr
func (g *Game) Query_QueryGameListByStatusAndAddr(in *gt.QueryGameListByStatusAndAddr) (types.Message, error) { func (g *Game) Query_QueryGameListByStatusAndAddr(in *gt.QueryGameListByStatusAndAddr) (types.Message, error) {
return List(g.GetLocalDB(), g.GetStateDB(), in) return List(g.GetLocalDB(), g.GetStateDB(), in)
} }
// Query_QueryGameById query game by gameID
func (g *Game) Query_QueryGameById(in *gt.QueryGameInfo) (types.Message, error) { func (g *Game) Query_QueryGameById(in *gt.QueryGameInfo) (types.Message, error) {
game, err := readGame(g.GetStateDB(), in.GetGameId()) game, err := readGame(g.GetStateDB(), in.GetGameId())
if err != nil { if err != nil {
......
...@@ -26,16 +26,18 @@ var ( ...@@ -26,16 +26,18 @@ var (
ExecerGame = []byte(GameX) ExecerGame = []byte(GameX)
) )
// action name
const ( const (
Action_CreateGame = "createGame" ActionCreateGame = "createGame"
Action_MatchGame = "matchGame" ActionMatchGame = "matchGame"
Action_CancelGame = "cancelGame" ActionCancelGame = "cancelGame"
Action_CloseGame = "closeGame" ActionCloseGame = "closeGame"
) )
// query func name
const ( const (
FuncName_QueryGameListByIds = "QueryGameListByIds" FuncNameQueryGameListByIds = "QueryGameListByIds"
FuncName_QueryGameListCount = "QueryGameListCount" FuncNameQueryGameListCount = "QueryGameListCount"
FuncName_QueryGameListByStatusAndAddr = "QueryGameListByStatusAndAddr" FuncNameQueryGameListByStatusAndAddr = "QueryGameListByStatusAndAddr"
FuncName_QueryGameById = "QueryGameById" FuncNameQueryGameByID = "QueryGameById"
) )
...@@ -4,15 +4,16 @@ ...@@ -4,15 +4,16 @@
package types package types
import "errors" import "fmt"
// some errors definition
var ( var (
ErrGameCreateAmount = errors.New("You fill in more than the maximum number of games.") ErrGameCreateAmount = fmt.Errorf("%s", "You fill in more than the maximum number of games.")
ErrGameCancleAddr = errors.New("You don't have permission to cancel someone else's game.") ErrGameCancleAddr = fmt.Errorf("%s", "You don't have permission to cancel someone else's game.")
ErrGameCloseAddr = errors.New("The game time has not yet expired,You don't have permission to call yet.") ErrGameCloseAddr = fmt.Errorf("%s", "The game time has not yet expired,You don't have permission to call yet.")
ErrGameTimeOut = errors.New("The game has expired.,You don't have permission to call.") ErrGameTimeOut = fmt.Errorf("%s", "The game has expired.,You don't have permission to call.")
ErrGameMatchStatus = errors.New("can't join the game, the game has matched or finished!") ErrGameMatchStatus = fmt.Errorf("%s", "can't join the game, the game has matched or finished!")
ErrGameMatch = errors.New("can't join the game, You can't match the game you created!") ErrGameMatch = fmt.Errorf("%s", "can't join the game, You can't match the game you created!")
ErrGameCancleStatus = errors.New("can't cancle the game, the game has matched!") ErrGameCancleStatus = fmt.Errorf("%s", "can't cancle the game, the game has matched!")
ErrGameCloseStatus = errors.New("can't close the game again, the game has finished!") ErrGameCloseStatus = fmt.Errorf("%s", "can't close the game again, the game has finished!")
) )
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package types package types
// GamePreCreateTx pre create game,unused
type GamePreCreateTx struct { type GamePreCreateTx struct {
//Secret string `json:"secret"` //Secret string `json:"secret"`
//下注必须时偶数,不能时级数 //下注必须时偶数,不能时级数
...@@ -14,59 +15,23 @@ type GamePreCreateTx struct { ...@@ -14,59 +15,23 @@ type GamePreCreateTx struct {
Fee int64 `json:"fee"` Fee int64 `json:"fee"`
} }
// GamePreMatchTx pre match game,unused
type GamePreMatchTx struct { type GamePreMatchTx struct {
GameId string `json:"gameId"` GameID string `json:"gameID"`
Guess int32 `json:"guess"` Guess int32 `json:"guess"`
Fee int64 `json:"fee"` Fee int64 `json:"fee"`
} }
// GamePreCancelTx pre cancel tx,unused
type GamePreCancelTx struct { type GamePreCancelTx struct {
GameId string `json:"gameId"` GameID string `json:"gameID"`
Fee int64 `json:"fee"` Fee int64 `json:"fee"`
} }
// GamePreCloseTx pre close game, unused
type GamePreCloseTx struct { type GamePreCloseTx struct {
GameId string `json:"gameId"` GameID string `json:"gameID"`
Secret string `json:"secret"` Secret string `json:"secret"`
Result int32 `json:"result"` Result int32 `json:"result"`
Fee int64 `json:"fee"` Fee int64 `json:"fee"`
} }
type GameData struct {
// 默认是由创建这局游戏的txHash作为gameId
GameId string `json:"gameId"`
// create 1 -> Match 2 -> Cancel 3 -> Close 4 Pending 5 //表示有人参与游戏,但还未打包
Status int32 `json:"status"`
// 创建时间
CreateTime int64 `json:"createTime"`
// 匹配时间(何时参与对赌)
MatchTime int64 `json:"matchTime"`
// 状态close的时间(包括cancel)
Closetime int64 `json:"closetime"`
// 赌注
Value int64 `json:"value"`
// 发起者账号地址
CreateAddress string `json:"createAddress"`
// 对赌者账号地址
MatchAddress string `json:"matchAddress"`
// hash 类型,预留字段
HashType string `json:"hashType"`
// 庄家创建游戏时,庄家自己出拳结果加密后的hash值
HashValue []byte `json:"hashValue"`
// 用来公布庄家出拳结果的私钥
Secret string `json:"secret"`
// 1平局,2 庄家获胜,3 matcher获胜,4 庄家开奖超时,matcher获胜,并获得本局所有赌资
Result int32 `json:"result"`
// matcher 出拳结果
MatcherGuess int32 `json:"matcherGuess"`
// create txHash
CreateTxHash string `json:"createTxHash"`
// matche交易hash
MatchTxHash string `json:"matchTxHash"`
// close txhash
CloseTxHash string `json:"closeTxHash"`
// cancel txhash
CancelTxHash string `json:"cancelTxHash"`
CreatorGuess int32 `json:"creatorGuess"`
Index int64 `json:"index"`
}
...@@ -30,18 +30,20 @@ func getRealExecName(paraName string) string { ...@@ -30,18 +30,20 @@ func getRealExecName(paraName string) string {
return types.ExecName(paraName + GameX) return types.ExecName(paraName + GameX)
} }
// NewType new type
func NewType() *GameType { func NewType() *GameType {
c := &GameType{} c := &GameType{}
c.SetChild(c) c.SetChild(c)
return c return c
} }
// exec // GameType execType
type GameType struct { type GameType struct {
types.ExecTypeBase types.ExecTypeBase
} }
func (at *GameType) GetLogMap() map[int64]*types.LogInfo { // GetLogMap get log
func (gt *GameType) GetLogMap() map[int64]*types.LogInfo {
return map[int64]*types.LogInfo{ return map[int64]*types.LogInfo{
TyLogCreateGame: {reflect.TypeOf(ReceiptGame{}), "LogLotteryCreate"}, TyLogCreateGame: {reflect.TypeOf(ReceiptGame{}), "LogLotteryCreate"},
TyLogCancleGame: {reflect.TypeOf(ReceiptGame{}), "LogCancleGame"}, TyLogCancleGame: {reflect.TypeOf(ReceiptGame{}), "LogCancleGame"},
...@@ -50,11 +52,13 @@ func (at *GameType) GetLogMap() map[int64]*types.LogInfo { ...@@ -50,11 +52,13 @@ func (at *GameType) GetLogMap() map[int64]*types.LogInfo {
} }
} }
func (g *GameType) GetPayload() types.Message { // GetPayload get payload
func (gt *GameType) GetPayload() types.Message {
return &GameAction{} return &GameAction{}
} }
func (g *GameType) GetTypeMap() map[string]int32 { // GetTypeMap get typeMap
func (gt *GameType) GetTypeMap() map[string]int32 {
return map[string]int32{ return map[string]int32{
"Create": GameActionCreate, "Create": GameActionCreate,
"Cancel": GameActionCancel, "Cancel": GameActionCancel,
...@@ -63,11 +67,10 @@ func (g *GameType) GetTypeMap() map[string]int32 { ...@@ -63,11 +67,10 @@ func (g *GameType) GetTypeMap() map[string]int32 {
} }
} }
// TODO createTx接口暂时没法用,作为一个预留接口 // CreateTx unused,just empty implementation
func (game GameType) CreateTx(action string, message json.RawMessage) (*types.Transaction, error) { func (gt GameType) CreateTx(action string, message json.RawMessage) (*types.Transaction, error) {
tlog.Debug("Game.CreateTx", "action", action) tlog.Debug("Game.CreateTx", "action", action)
var tx *types.Transaction if action == ActionCreateGame {
if action == Action_CreateGame {
var param GamePreCreateTx var param GamePreCreateTx
err := json.Unmarshal(message, &param) err := json.Unmarshal(message, &param)
if err != nil { if err != nil {
...@@ -76,7 +79,7 @@ func (game GameType) CreateTx(action string, message json.RawMessage) (*types.Tr ...@@ -76,7 +79,7 @@ func (game GameType) CreateTx(action string, message json.RawMessage) (*types.Tr
} }
return CreateRawGamePreCreateTx(&param) return CreateRawGamePreCreateTx(&param)
} else if action == Action_MatchGame { } else if action == ActionMatchGame {
var param GamePreMatchTx var param GamePreMatchTx
err := json.Unmarshal(message, &param) err := json.Unmarshal(message, &param)
if err != nil { if err != nil {
...@@ -85,7 +88,7 @@ func (game GameType) CreateTx(action string, message json.RawMessage) (*types.Tr ...@@ -85,7 +88,7 @@ func (game GameType) CreateTx(action string, message json.RawMessage) (*types.Tr
} }
return CreateRawGamePreMatchTx(&param) return CreateRawGamePreMatchTx(&param)
} else if action == Action_CancelGame { } else if action == ActionCancelGame {
var param GamePreCancelTx var param GamePreCancelTx
err := json.Unmarshal(message, &param) err := json.Unmarshal(message, &param)
if err != nil { if err != nil {
...@@ -94,7 +97,7 @@ func (game GameType) CreateTx(action string, message json.RawMessage) (*types.Tr ...@@ -94,7 +97,7 @@ func (game GameType) CreateTx(action string, message json.RawMessage) (*types.Tr
} }
return CreateRawGamePreCancelTx(&param) return CreateRawGamePreCancelTx(&param)
} else if action == Action_CloseGame { } else if action == ActionCloseGame {
var param GamePreCloseTx var param GamePreCloseTx
err := json.Unmarshal(message, &param) err := json.Unmarshal(message, &param)
if err != nil { if err != nil {
...@@ -103,13 +106,11 @@ func (game GameType) CreateTx(action string, message json.RawMessage) (*types.Tr ...@@ -103,13 +106,11 @@ func (game GameType) CreateTx(action string, message json.RawMessage) (*types.Tr
} }
return CreateRawGamePreCloseTx(&param) return CreateRawGamePreCloseTx(&param)
} else {
return nil, types.ErrNotSupport
} }
return nil, types.ErrNotSupport
return tx, nil
} }
// CreateRawGamePreCreateTx unused,just empty implementation
func CreateRawGamePreCreateTx(parm *GamePreCreateTx) (*types.Transaction, error) { func CreateRawGamePreCreateTx(parm *GamePreCreateTx) (*types.Transaction, error) {
if parm == nil { if parm == nil {
tlog.Error("CreateRawGamePreCreateTx", "parm", parm) tlog.Error("CreateRawGamePreCreateTx", "parm", parm)
...@@ -139,13 +140,14 @@ func CreateRawGamePreCreateTx(parm *GamePreCreateTx) (*types.Transaction, error) ...@@ -139,13 +140,14 @@ func CreateRawGamePreCreateTx(parm *GamePreCreateTx) (*types.Transaction, error)
return tx, nil return tx, nil
} }
// CreateRawGamePreMatchTx unused,just empty implementation
func CreateRawGamePreMatchTx(parm *GamePreMatchTx) (*types.Transaction, error) { func CreateRawGamePreMatchTx(parm *GamePreMatchTx) (*types.Transaction, error) {
if parm == nil { if parm == nil {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
v := &GameMatch{ v := &GameMatch{
GameId: parm.GameId, GameId: parm.GameID,
Guess: parm.Guess, Guess: parm.Guess,
} }
game := &GameAction{ game := &GameAction{
...@@ -166,12 +168,13 @@ func CreateRawGamePreMatchTx(parm *GamePreMatchTx) (*types.Transaction, error) { ...@@ -166,12 +168,13 @@ func CreateRawGamePreMatchTx(parm *GamePreMatchTx) (*types.Transaction, error) {
return tx, nil return tx, nil
} }
// CreateRawGamePreCancelTx unused,just empty implementation
func CreateRawGamePreCancelTx(parm *GamePreCancelTx) (*types.Transaction, error) { func CreateRawGamePreCancelTx(parm *GamePreCancelTx) (*types.Transaction, error) {
if parm == nil { if parm == nil {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
v := &GameCancel{ v := &GameCancel{
GameId: parm.GameId, GameId: parm.GameID,
} }
cancel := &GameAction{ cancel := &GameAction{
Ty: GameActionCancel, Ty: GameActionCancel,
...@@ -191,13 +194,13 @@ func CreateRawGamePreCancelTx(parm *GamePreCancelTx) (*types.Transaction, error) ...@@ -191,13 +194,13 @@ func CreateRawGamePreCancelTx(parm *GamePreCancelTx) (*types.Transaction, error)
return tx, nil return tx, nil
} }
//CreateRawGamePreCloseTx // CreateRawGamePreCloseTx unused,just empty implementation
func CreateRawGamePreCloseTx(parm *GamePreCloseTx) (*types.Transaction, error) { func CreateRawGamePreCloseTx(parm *GamePreCloseTx) (*types.Transaction, error) {
if parm == nil { if parm == nil {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
v := &GameClose{ v := &GameClose{
GameId: parm.GameId, GameId: parm.GameID,
Secret: parm.Secret, Secret: parm.Secret,
} }
close := &GameAction{ close := &GameAction{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment