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,10 +162,15 @@ func evmBalance(cmd *cobra.Command, args []string) { ...@@ -161,10 +162,15 @@ func evmBalance(cmd *cobra.Command, args []string) {
ctx.Run() ctx.Run()
} }
// AccountResult 账户余额查询出来之后进行单位转换
type AccountResult struct { type AccountResult struct {
// 货币
Currency int32 `json:"currency,omitempty"` Currency int32 `json:"currency,omitempty"`
// 余额
Balance string `json:"balance,omitempty"` Balance string `json:"balance,omitempty"`
// 冻结余额
Frozen string `json:"frozen,omitempty"` Frozen string `json:"frozen,omitempty"`
// 账户地址
Addr string `json:"addr,omitempty"` Addr string `json:"addr,omitempty"`
} }
...@@ -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,18 +77,18 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt, ...@@ -76,18 +77,18 @@ 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 { if curVer != nil && snapshot >= curVer.GetID() && curVer.GetID() > -1 {
evm.mStateDB.RevertToSnapshot(snapshot) evm.mStateDB.RevertToSnapshot(snapshot)
} }
return nil, model.ErrOutOfGas return nil, model.ErrOutOfGas
} }
}
// 打印合约中生成的日志 // 打印合约中生成的日志
evm.mStateDB.PrintLogs() evm.mStateDB.PrintLogs()
...@@ -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,13 +144,12 @@ func runCase(tt *testing.T, c VMCase, file string) { ...@@ -144,13 +144,12 @@ 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.Errorf("test case:%s, failed:%s", c.name, err)
tt.Fail() tt.Fail()
return return
} }
}
// 4 检查执行结果 post (注意,这里不检查Gas具体扣费数额,因为计费规则不一样,值检查执行结果是否正确) // 4 检查执行结果 post (注意,这里不检查Gas具体扣费数额,因为计费规则不一样,值检查执行结果是否正确)
t := NewTester(tt) t := NewTester(tt)
// 4.1 返回结果 // 4.1 返回结果
......
...@@ -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 大数字0
Big0 = big.NewInt(0) Big0 = big.NewInt(0)
// Big1 大数字1
Big1 = big.NewInt(1) Big1 = big.NewInt(1)
// Big32 大数字32
Big32 = big.NewInt(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 {
......
...@@ -59,54 +59,54 @@ func (g *G1) String() string { ...@@ -59,54 +59,54 @@ func (g *G1) String() string {
} }
// CurvePoints returns p's curve points in big integer // CurvePoints returns p's curve points in big integer
func (e *G1) CurvePoints() (*big.Int, *big.Int, *big.Int, *big.Int) { func (g *G1) CurvePoints() (*big.Int, *big.Int, *big.Int, *big.Int) {
return e.p.x, e.p.y, e.p.z, e.p.t return g.p.x, g.p.y, g.p.z, g.p.t
} }
// ScalarBaseMult sets e to g*k where g is the generator of the group and // ScalarBaseMult sets e to g*k where g is the generator of the group and
// then returns e. // then returns e.
func (e *G1) ScalarBaseMult(k *big.Int) *G1 { func (g *G1) ScalarBaseMult(k *big.Int) *G1 {
if e.p == nil { if g.p == nil {
e.p = newCurvePoint(nil) g.p = newCurvePoint(nil)
} }
e.p.Mul(curveGen, k, new(bnPool)) g.p.Mul(curveGen, k, new(bnPool))
return e return g
} }
// ScalarMult sets e to a*k and then returns e. // ScalarMult sets e to a*k and then returns e.
func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { func (g *G1) ScalarMult(a *G1, k *big.Int) *G1 {
if e.p == nil { if g.p == nil {
e.p = newCurvePoint(nil) g.p = newCurvePoint(nil)
} }
e.p.Mul(a.p, k, new(bnPool)) g.p.Mul(a.p, k, new(bnPool))
return e return g
} }
// Add sets e to a+b and then returns e. // Add sets e to a+b and then returns e.
// BUG(agl): this function is not complete: a==b fails. // BUG(agl): this function is not complete: a==b fails.
func (e *G1) Add(a, b *G1) *G1 { func (g *G1) Add(a, b *G1) *G1 {
if e.p == nil { if g.p == nil {
e.p = newCurvePoint(nil) g.p = newCurvePoint(nil)
} }
e.p.Add(a.p, b.p, new(bnPool)) g.p.Add(a.p, b.p, new(bnPool))
return e return g
} }
// Neg sets e to -a and then returns e. // Neg sets e to -a and then returns e.
func (e *G1) Neg(a *G1) *G1 { func (g *G1) Neg(a *G1) *G1 {
if e.p == nil { if g.p == nil {
e.p = newCurvePoint(nil) g.p = newCurvePoint(nil)
} }
e.p.Negative(a.p) g.p.Negative(a.p)
return e return g
} }
// Marshal converts n to a byte slice. // Marshal converts n to a byte slice.
func (n *G1) Marshal() []byte { func (g *G1) Marshal() []byte {
n.p.MakeAffine(nil) g.p.MakeAffine(nil)
xBytes := new(big.Int).Mod(n.p.x, P).Bytes() xBytes := new(big.Int).Mod(g.p.x, P).Bytes()
yBytes := new(big.Int).Mod(n.p.y, P).Bytes() yBytes := new(big.Int).Mod(g.p.y, P).Bytes()
// Each value is a 256-bit number. // Each value is a 256-bit number.
const numBytes = 256 / 8 const numBytes = 256 / 8
...@@ -120,35 +120,35 @@ func (n *G1) Marshal() []byte { ...@@ -120,35 +120,35 @@ func (n *G1) Marshal() []byte {
// Unmarshal sets e to the result of converting the output of Marshal back into // Unmarshal sets e to the result of converting the output of Marshal back into
// a group element and then returns e. // a group element and then returns e.
func (e *G1) Unmarshal(m []byte) ([]byte, error) { func (g *G1) Unmarshal(m []byte) ([]byte, error) {
// Each value is a 256-bit number. // Each value is a 256-bit number.
const numBytes = 256 / 8 const numBytes = 256 / 8
if len(m) != 2*numBytes { if len(m) != 2*numBytes {
return nil, errors.New("bn256: not enough data") return nil, errors.New("bn256: not enough data")
} }
// Unmarshal the points and check their caps // Unmarshal the points and check their caps
if e.p == nil { if g.p == nil {
e.p = newCurvePoint(nil) g.p = newCurvePoint(nil)
} }
e.p.x.SetBytes(m[0*numBytes : 1*numBytes]) g.p.x.SetBytes(m[0*numBytes : 1*numBytes])
if e.p.x.Cmp(P) >= 0 { if g.p.x.Cmp(P) >= 0 {
return nil, errors.New("bn256: coordinate exceeds modulus") return nil, errors.New("bn256: coordinate exceeds modulus")
} }
e.p.y.SetBytes(m[1*numBytes : 2*numBytes]) g.p.y.SetBytes(m[1*numBytes : 2*numBytes])
if e.p.y.Cmp(P) >= 0 { if g.p.y.Cmp(P) >= 0 {
return nil, errors.New("bn256: coordinate exceeds modulus") return nil, errors.New("bn256: coordinate exceeds modulus")
} }
// Ensure the point is on the curve // Ensure the point is on the curve
if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 { if g.p.x.Sign() == 0 && g.p.y.Sign() == 0 {
// This is the point at infinity. // This is the point at infinity.
e.p.y.SetInt64(1) g.p.y.SetInt64(1)
e.p.z.SetInt64(0) g.p.z.SetInt64(0)
e.p.t.SetInt64(0) g.p.t.SetInt64(0)
} else { } else {
e.p.z.SetInt64(1) g.p.z.SetInt64(1)
e.p.t.SetInt64(1) g.p.t.SetInt64(1)
if !e.p.IsOnCurve() { if !g.p.IsOnCurve() {
return nil, errors.New("bn256: malformed point") return nil, errors.New("bn256: malformed point")
} }
} }
...@@ -161,7 +161,7 @@ type G2 struct { ...@@ -161,7 +161,7 @@ type G2 struct {
p *twistPoint p *twistPoint
} }
// RandomG1 returns x and g₂ˣ where x is a random, non-zero number read from r. // RandomG2 returns x and g₂ˣ where x is a random, non-zero number read from r.
func RandomG2(r io.Reader) (*big.Int, *G2, error) { func RandomG2(r io.Reader) (*big.Int, *G2, error) {
var k *big.Int var k *big.Int
var err error var err error
...@@ -185,47 +185,47 @@ func (g *G2) String() string { ...@@ -185,47 +185,47 @@ func (g *G2) String() string {
// CurvePoints returns the curve points of p which includes the real // CurvePoints returns the curve points of p which includes the real
// and imaginary parts of the curve point. // and imaginary parts of the curve point.
func (e *G2) CurvePoints() (*gfP2, *gfP2, *gfP2, *gfP2) { //func (g *G2) CurvePoints() (*gfP2, *gfP2, *gfP2, *gfP2) {
return e.p.x, e.p.y, e.p.z, e.p.t // return g.p.x, g.p.y, g.p.z, g.p.t
} //}
// ScalarBaseMult sets e to g*k where g is the generator of the group and // ScalarBaseMult sets e to g*k where g is the generator of the group and
// then returns out. // then returns out.
func (e *G2) ScalarBaseMult(k *big.Int) *G2 { func (g *G2) ScalarBaseMult(k *big.Int) *G2 {
if e.p == nil { if g.p == nil {
e.p = newTwistPoint(nil) g.p = newTwistPoint(nil)
} }
e.p.Mul(twistGen, k, new(bnPool)) g.p.Mul(twistGen, k, new(bnPool))
return e return g
} }
// ScalarMult sets e to a*k and then returns e. // ScalarMult sets e to a*k and then returns e.
func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 { func (g *G2) ScalarMult(a *G2, k *big.Int) *G2 {
if e.p == nil { if g.p == nil {
e.p = newTwistPoint(nil) g.p = newTwistPoint(nil)
} }
e.p.Mul(a.p, k, new(bnPool)) g.p.Mul(a.p, k, new(bnPool))
return e return g
} }
// Add sets e to a+b and then returns e. // Add sets e to a+b and then returns e.
// BUG(agl): this function is not complete: a==b fails. // BUG(agl): this function is not complete: a==b fails.
func (e *G2) Add(a, b *G2) *G2 { func (g *G2) Add(a, b *G2) *G2 {
if e.p == nil { if g.p == nil {
e.p = newTwistPoint(nil) g.p = newTwistPoint(nil)
} }
e.p.Add(a.p, b.p, new(bnPool)) g.p.Add(a.p, b.p, new(bnPool))
return e return g
} }
// Marshal converts n into a byte slice. // Marshal converts n into a byte slice.
func (n *G2) Marshal() []byte { func (g *G2) Marshal() []byte {
n.p.MakeAffine(nil) g.p.MakeAffine(nil)
xxBytes := new(big.Int).Mod(n.p.x.x, P).Bytes() xxBytes := new(big.Int).Mod(g.p.x.x, P).Bytes()
xyBytes := new(big.Int).Mod(n.p.x.y, P).Bytes() xyBytes := new(big.Int).Mod(g.p.x.y, P).Bytes()
yxBytes := new(big.Int).Mod(n.p.y.x, P).Bytes() yxBytes := new(big.Int).Mod(g.p.y.x, P).Bytes()
yyBytes := new(big.Int).Mod(n.p.y.y, P).Bytes() yyBytes := new(big.Int).Mod(g.p.y.y, P).Bytes()
// Each value is a 256-bit number. // Each value is a 256-bit number.
const numBytes = 256 / 8 const numBytes = 256 / 8
...@@ -241,46 +241,46 @@ func (n *G2) Marshal() []byte { ...@@ -241,46 +241,46 @@ func (n *G2) Marshal() []byte {
// Unmarshal sets e to the result of converting the output of Marshal back into // Unmarshal sets e to the result of converting the output of Marshal back into
// a group element and then returns e. // a group element and then returns e.
func (e *G2) Unmarshal(m []byte) ([]byte, error) { func (g *G2) Unmarshal(m []byte) ([]byte, error) {
// Each value is a 256-bit number. // Each value is a 256-bit number.
const numBytes = 256 / 8 const numBytes = 256 / 8
if len(m) != 4*numBytes { if len(m) != 4*numBytes {
return nil, errors.New("bn256: not enough data") return nil, errors.New("bn256: not enough data")
} }
// Unmarshal the points and check their caps // Unmarshal the points and check their caps
if e.p == nil { if g.p == nil {
e.p = newTwistPoint(nil) g.p = newTwistPoint(nil)
} }
e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes]) g.p.x.x.SetBytes(m[0*numBytes : 1*numBytes])
if e.p.x.x.Cmp(P) >= 0 { if g.p.x.x.Cmp(P) >= 0 {
return nil, errors.New("bn256: coordinate exceeds modulus") return nil, errors.New("bn256: coordinate exceeds modulus")
} }
e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes]) g.p.x.y.SetBytes(m[1*numBytes : 2*numBytes])
if e.p.x.y.Cmp(P) >= 0 { if g.p.x.y.Cmp(P) >= 0 {
return nil, errors.New("bn256: coordinate exceeds modulus") return nil, errors.New("bn256: coordinate exceeds modulus")
} }
e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes]) g.p.y.x.SetBytes(m[2*numBytes : 3*numBytes])
if e.p.y.x.Cmp(P) >= 0 { if g.p.y.x.Cmp(P) >= 0 {
return nil, errors.New("bn256: coordinate exceeds modulus") return nil, errors.New("bn256: coordinate exceeds modulus")
} }
e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes]) g.p.y.y.SetBytes(m[3*numBytes : 4*numBytes])
if e.p.y.y.Cmp(P) >= 0 { if g.p.y.y.Cmp(P) >= 0 {
return nil, errors.New("bn256: coordinate exceeds modulus") return nil, errors.New("bn256: coordinate exceeds modulus")
} }
// Ensure the point is on the curve // Ensure the point is on the curve
if e.p.x.x.Sign() == 0 && if g.p.x.x.Sign() == 0 &&
e.p.x.y.Sign() == 0 && g.p.x.y.Sign() == 0 &&
e.p.y.x.Sign() == 0 && g.p.y.x.Sign() == 0 &&
e.p.y.y.Sign() == 0 { g.p.y.y.Sign() == 0 {
// This is the point at infinity. // This is the point at infinity.
e.p.y.SetOne() g.p.y.SetOne()
e.p.z.SetZero() g.p.z.SetZero()
e.p.t.SetZero() g.p.t.SetZero()
} else { } else {
e.p.z.SetOne() g.p.z.SetOne()
e.p.t.SetOne() g.p.t.SetOne()
if !e.p.IsOnCurve() { if !g.p.IsOnCurve() {
return nil, errors.New("bn256: malformed point") return nil, errors.New("bn256: malformed point")
} }
} }
...@@ -298,48 +298,48 @@ func (g *GT) String() string { ...@@ -298,48 +298,48 @@ func (g *GT) String() string {
} }
// ScalarMult sets e to a*k and then returns e. // ScalarMult sets e to a*k and then returns e.
func (e *GT) ScalarMult(a *GT, k *big.Int) *GT { func (g *GT) ScalarMult(a *GT, k *big.Int) *GT {
if e.p == nil { if g.p == nil {
e.p = newGFp12(nil) g.p = newGFp12(nil)
} }
e.p.Exp(a.p, k, new(bnPool)) g.p.Exp(a.p, k, new(bnPool))
return e return g
} }
// Add sets e to a+b and then returns e. // Add sets e to a+b and then returns e.
func (e *GT) Add(a, b *GT) *GT { func (g *GT) Add(a, b *GT) *GT {
if e.p == nil { if g.p == nil {
e.p = newGFp12(nil) g.p = newGFp12(nil)
} }
e.p.Mul(a.p, b.p, new(bnPool)) g.p.Mul(a.p, b.p, new(bnPool))
return e return g
} }
// Neg sets e to -a and then returns e. // Neg sets e to -a and then returns e.
func (e *GT) Neg(a *GT) *GT { func (g *GT) Neg(a *GT) *GT {
if e.p == nil { if g.p == nil {
e.p = newGFp12(nil) g.p = newGFp12(nil)
} }
e.p.Invert(a.p, new(bnPool)) g.p.Invert(a.p, new(bnPool))
return e return g
} }
// Marshal converts n into a byte slice. // Marshal converts n into a byte slice.
func (n *GT) Marshal() []byte { func (g *GT) Marshal() []byte {
n.p.Minimal() g.p.Minimal()
xxxBytes := n.p.x.x.x.Bytes() xxxBytes := g.p.x.x.x.Bytes()
xxyBytes := n.p.x.x.y.Bytes() xxyBytes := g.p.x.x.y.Bytes()
xyxBytes := n.p.x.y.x.Bytes() xyxBytes := g.p.x.y.x.Bytes()
xyyBytes := n.p.x.y.y.Bytes() xyyBytes := g.p.x.y.y.Bytes()
xzxBytes := n.p.x.z.x.Bytes() xzxBytes := g.p.x.z.x.Bytes()
xzyBytes := n.p.x.z.y.Bytes() xzyBytes := g.p.x.z.y.Bytes()
yxxBytes := n.p.y.x.x.Bytes() yxxBytes := g.p.y.x.x.Bytes()
yxyBytes := n.p.y.x.y.Bytes() yxyBytes := g.p.y.x.y.Bytes()
yyxBytes := n.p.y.y.x.Bytes() yyxBytes := g.p.y.y.x.Bytes()
yyyBytes := n.p.y.y.y.Bytes() yyyBytes := g.p.y.y.y.Bytes()
yzxBytes := n.p.y.z.x.Bytes() yzxBytes := g.p.y.z.x.Bytes()
yzyBytes := n.p.y.z.y.Bytes() yzyBytes := g.p.y.z.y.Bytes()
// Each value is a 256-bit number. // Each value is a 256-bit number.
const numBytes = 256 / 8 const numBytes = 256 / 8
...@@ -363,7 +363,7 @@ func (n *GT) Marshal() []byte { ...@@ -363,7 +363,7 @@ func (n *GT) Marshal() []byte {
// Unmarshal sets e to the result of converting the output of Marshal back into // Unmarshal sets e to the result of converting the output of Marshal back into
// a group element and then returns e. // a group element and then returns e.
func (e *GT) Unmarshal(m []byte) (*GT, bool) { func (g *GT) Unmarshal(m []byte) (*GT, bool) {
// Each value is a 256-bit number. // Each value is a 256-bit number.
const numBytes = 256 / 8 const numBytes = 256 / 8
...@@ -371,24 +371,24 @@ func (e *GT) Unmarshal(m []byte) (*GT, bool) { ...@@ -371,24 +371,24 @@ func (e *GT) Unmarshal(m []byte) (*GT, bool) {
return nil, false return nil, false
} }
if e.p == nil { if g.p == nil {
e.p = newGFp12(nil) g.p = newGFp12(nil)
} }
e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes]) g.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes])
e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes]) g.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes])
e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes]) g.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes])
e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes]) g.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes])
e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes]) g.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes])
e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes]) g.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes])
e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes]) g.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes])
e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes]) g.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes])
e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes]) g.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes])
e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes]) g.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes])
e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes]) g.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes])
e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes]) g.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes])
return e, true return g, true
} }
// Pair calculates an Optimal Ate pairing. // Pair calculates an Optimal Ate pairing.
......
...@@ -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
// Str 字符串形式
func (h Hash) Str() string { return string(h[:]) } 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[:]) }
// Hex 十六进制形式
func (h Hash) Hex() string { return Bytes2Hex(h[:]) } 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
} }
} }
// From 来源
func (m Message) From() Address { return m.from } func (m Message) From() Address { return m.from }
// To 目的地址
func (m Message) To() *Address { return m.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 }
// Value 转账金额
func (m Message) Value() uint64 { return m.amount } func (m Message) Value() uint64 { return m.amount }
// Nonce nonce值
func (m Message) Nonce() int64 { return m.nonce } func (m Message) Nonce() int64 { return m.nonce }
// Data 附带数据
func (m Message) Data() []byte { return m.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 }
// Alias 合约别名
func (m Message) Alias() string { return m.alias } func (m Message) Alias() string { return m.alias }
...@@ -11,20 +11,26 @@ import ( ...@@ -11,20 +11,26 @@ import (
) )
const ( const (
// GasQuickStep 计费
GasQuickStep uint64 = 2 GasQuickStep uint64 = 2
// GasFastestStep 计费
GasFastestStep uint64 = 3 GasFastestStep uint64 = 3
// GasFastStep 计费
GasFastStep uint64 = 5 GasFastStep uint64 = 5
// GasMidStep 计费
GasMidStep uint64 = 8 GasMidStep uint64 = 8
// GasSlowStep 计费
GasSlowStep uint64 = 10 GasSlowStep uint64 = 10
// GasExtStep 计费
GasExtStep uint64 = 20 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
......
...@@ -14,25 +14,32 @@ import ( ...@@ -14,25 +14,32 @@ import (
// 本文件中定义各种操作中需要花费的Gas逻辑 // 本文件中定义各种操作中需要花费的Gas逻辑
type ( type (
GasFunc func(GasTable, *params.EVMParam, *params.GasParam, *mm.Stack, *mm.Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64 // CalcGasFunc 计算Gas的方法定义
CalcGasFunc func(Table, *params.EVMParam, *params.GasParam, *mm.Stack, *mm.Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
) )
// 此文件中定义各种指令操作花费的Gas计算 // Table 此文件中定义各种指令操作花费的Gas计算
// Gas定价表结构 // Gas定价表结构
type GasTable struct { type Table struct {
// ExtcodeSize 扩展代码大小计价
ExtcodeSize uint64 ExtcodeSize uint64
// ExtcodeCopy 代码复制价格
ExtcodeCopy uint64 ExtcodeCopy uint64
// Balance 账户计价
Balance uint64 Balance uint64
// SLoad 加载数据计价
SLoad uint64 SLoad uint64
// Calls 调用方法计价
Calls uint64 Calls uint64
// Suicide 自杀计价
Suicide uint64 Suicide uint64
// ExpByte 额外数据计价
ExpByte uint64 ExpByte uint64
} }
var ( var (
// 定义各种操作的Gas定价 // TableHomestead 定义各种操作的Gas定价
GasTableHomestead = GasTable{ TableHomestead = Table{
ExtcodeSize: 20, ExtcodeSize: 20,
ExtcodeCopy: 20, ExtcodeCopy: 20,
Balance: 20, Balance: 20,
...@@ -74,15 +81,15 @@ func memoryGasCost(mem *mm.Memory, newMemSize uint64) (uint64, error) { ...@@ -74,15 +81,15 @@ func memoryGasCost(mem *mm.Memory, newMemSize uint64) (uint64, error) {
return 0, nil return 0, nil
} }
// Gas计算逻辑封装,返回固定值的Gas计算都可以使用此方法 // ConstGasFunc Gas计算逻辑封装,返回固定值的Gas计算都可以使用此方法
func ConstGasFunc(gas uint64) GasFunc { func ConstGasFunc(gas uint64) CalcGasFunc {
return func(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { return func(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
return gas, nil return gas, nil
} }
} }
// 计算数据复制需要花费的Gas // CallDataCopy 计算数据复制需要花费的Gas
func GasCallDataCopy(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { func CallDataCopy(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
return 0, err return 0, err
...@@ -108,7 +115,8 @@ func GasCallDataCopy(gt GasTable, evm *params.EVMParam, contractGas *params.GasP ...@@ -108,7 +115,8 @@ func GasCallDataCopy(gt GasTable, evm *params.EVMParam, contractGas *params.GasP
return gas, nil return gas, nil
} }
func GasReturnDataCopy(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // ReturnDataCopy 计算数据复制的价格
func ReturnDataCopy(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
return 0, err return 0, err
...@@ -134,7 +142,8 @@ func GasReturnDataCopy(gt GasTable, evm *params.EVMParam, contractGas *params.Ga ...@@ -134,7 +142,8 @@ func GasReturnDataCopy(gt GasTable, evm *params.EVMParam, contractGas *params.Ga
return gas, nil return gas, nil
} }
func GasSStore(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // SStore 计算数据存储的价格
func SStore(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
var ( var (
y, x = stack.Back(1), stack.Back(0) y, x = stack.Back(1), stack.Back(0)
val = evm.StateDB.GetState(contractGas.Address.String(), common.BigToHash(x)) val = evm.StateDB.GetState(contractGas.Address.String(), common.BigToHash(x))
...@@ -157,8 +166,9 @@ func GasSStore(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, ...@@ -157,8 +166,9 @@ func GasSStore(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam,
} }
} }
func MakeGasLog(n uint64) GasFunc { // MakeGasLog 生成Gas计算方法
return func(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { func MakeGasLog(n uint64) CalcGasFunc {
return func(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
requestedSize, overflow := common.BigUint64(stack.Back(1)) requestedSize, overflow := common.BigUint64(stack.Back(1))
if overflow { if overflow {
return 0, model.ErrGasUintOverflow return 0, model.ErrGasUintOverflow
...@@ -187,7 +197,8 @@ func MakeGasLog(n uint64) GasFunc { ...@@ -187,7 +197,8 @@ func MakeGasLog(n uint64) GasFunc {
} }
} }
func GasSha3(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // Sha3 sha3计费
func Sha3(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
var overflow bool var overflow bool
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
...@@ -211,7 +222,8 @@ func GasSha3(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, st ...@@ -211,7 +222,8 @@ func GasSha3(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, st
return gas, nil return gas, nil
} }
func GasCodeCopy(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // CodeCopy 代码复制计费
func CodeCopy(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
return 0, err return 0, err
...@@ -235,7 +247,8 @@ func GasCodeCopy(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam ...@@ -235,7 +247,8 @@ func GasCodeCopy(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam
return gas, nil return gas, nil
} }
func GasExtCodeCopy(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // ExtCodeCopy 扩展代码复制计费
func ExtCodeCopy(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
return 0, err return 0, err
...@@ -261,7 +274,8 @@ func GasExtCodeCopy(gt GasTable, evm *params.EVMParam, contractGas *params.GasPa ...@@ -261,7 +274,8 @@ func GasExtCodeCopy(gt GasTable, evm *params.EVMParam, contractGas *params.GasPa
return gas, nil return gas, nil
} }
func GasMLoad(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // MLoad 内存加载计费
func MLoad(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
var overflow bool var overflow bool
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
...@@ -273,7 +287,8 @@ func GasMLoad(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, s ...@@ -273,7 +287,8 @@ func GasMLoad(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, s
return gas, nil return gas, nil
} }
func GasMStore8(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // MStore8 内存存储计费
func MStore8(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
var overflow bool var overflow bool
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
...@@ -285,7 +300,8 @@ func GasMStore8(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, ...@@ -285,7 +300,8 @@ func GasMStore8(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam,
return gas, nil return gas, nil
} }
func GasMStore(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // MStore 内存存储计费
func MStore(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
var overflow bool var overflow bool
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
...@@ -297,7 +313,8 @@ func GasMStore(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, ...@@ -297,7 +313,8 @@ func GasMStore(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam,
return gas, nil return gas, nil
} }
func GasCreate(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // Create 开辟内存计费
func Create(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
var overflow bool var overflow bool
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
...@@ -309,19 +326,23 @@ func GasCreate(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, ...@@ -309,19 +326,23 @@ func GasCreate(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam,
return gas, nil return gas, nil
} }
func GasBalance(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // Balance 获取余额计费
func Balance(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
return gt.Balance, nil return gt.Balance, nil
} }
func GasExtCodeSize(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // ExtCodeSize 获取代码大小计费
func ExtCodeSize(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
return gt.ExtcodeSize, nil return gt.ExtcodeSize, nil
} }
func GasSLoad(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // SLoad 加载存储计费
func SLoad(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
return gt.SLoad, nil return gt.SLoad, nil
} }
func GasExp(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // Exp exp运算计费
func Exp(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
expByteLen := uint64((stack.Items[stack.Len()-2].BitLen() + 7) / 8) expByteLen := uint64((stack.Items[stack.Len()-2].BitLen() + 7) / 8)
var ( var (
...@@ -334,7 +355,8 @@ func GasExp(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, sta ...@@ -334,7 +355,8 @@ func GasExp(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, sta
return gas, nil return gas, nil
} }
func GasCall(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // Call 调用合约计费
func Call(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
var ( var (
gas = gt.Calls gas = gt.Calls
transfersValue = stack.Back(2).Sign() != 0 transfersValue = stack.Back(2).Sign() != 0
...@@ -365,7 +387,8 @@ func GasCall(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, st ...@@ -365,7 +387,8 @@ func GasCall(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, st
return gas, nil return gas, nil
} }
func GasCallCode(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // CallCode 调用合约代码计费
func CallCode(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
gas := gt.Calls gas := gt.Calls
if stack.Back(2).Sign() != 0 { if stack.Back(2).Sign() != 0 {
gas += params.CallValueTransferGas gas += params.CallValueTransferGas
...@@ -389,15 +412,18 @@ func GasCallCode(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam ...@@ -389,15 +412,18 @@ func GasCallCode(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam
return gas, nil return gas, nil
} }
func GasReturn(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // Return 返回操作计费
func Return(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
return memoryGasCost(mem, memorySize) return memoryGasCost(mem, memorySize)
} }
func GasRevert(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // Revert revert操作计费
func Revert(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
return memoryGasCost(mem, memorySize) return memoryGasCost(mem, memorySize)
} }
func GasSuicide(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // Suicide 自杀操作计费
func Suicide(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
var gas uint64 var gas uint64
if !evm.StateDB.HasSuicided(contractGas.Address.String()) { if !evm.StateDB.HasSuicided(contractGas.Address.String()) {
evm.StateDB.AddRefund(params.SuicideRefundGas) evm.StateDB.AddRefund(params.SuicideRefundGas)
...@@ -405,7 +431,8 @@ func GasSuicide(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, ...@@ -405,7 +431,8 @@ func GasSuicide(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam,
return gas, nil return gas, nil
} }
func GasDelegateCall(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // DelegateCall 委托调用计费
func DelegateCall(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
return 0, err return 0, err
...@@ -425,7 +452,8 @@ func GasDelegateCall(gt GasTable, evm *params.EVMParam, contractGas *params.GasP ...@@ -425,7 +452,8 @@ func GasDelegateCall(gt GasTable, evm *params.EVMParam, contractGas *params.GasP
return gas, nil return gas, nil
} }
func GasStaticCall(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // StaticCall 静态调用计费
func StaticCall(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
return 0, err return 0, err
...@@ -445,14 +473,17 @@ func GasStaticCall(gt GasTable, evm *params.EVMParam, contractGas *params.GasPar ...@@ -445,14 +473,17 @@ func GasStaticCall(gt GasTable, evm *params.EVMParam, contractGas *params.GasPar
return gas, nil return gas, nil
} }
func GasPush(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // Push 压栈计费
func Push(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
return GasFastestStep, nil return GasFastestStep, nil
} }
func GasSwap(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // Swap 交换计费
func Swap(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
return GasFastestStep, nil return GasFastestStep, nil
} }
func GasDup(gt GasTable, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) { // Dup dup操作计费
func Dup(gt Table, evm *params.EVMParam, contractGas *params.GasParam, stack *mm.Stack, mem *mm.Memory, memorySize uint64) (uint64, error) {
return GasFastestStep, nil return GasFastestStep, nil
} }
...@@ -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 out of gas
ErrOutOfGas = errors.New("out of gas") ErrOutOfGas = errors.New("out of gas")
// ErrCodeStoreOutOfGas contract creation code storage out of gas
ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas") ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas")
// ErrDepth max call depth exceeded
ErrDepth = errors.New("max call depth exceeded") ErrDepth = errors.New("max call depth exceeded")
ErrTraceLimitReached = errors.New("the number of logs reached the specified limit") // ErrInsufficientBalance insufficient balance for transfer
ErrInsufficientBalance = errors.New("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 address not exists
ErrAddrNotExists = errors.New("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 transferring between external accounts not supports
ErrTransferBetweenEOA = errors.New("transferring between external accounts not supports") ErrTransferBetweenEOA = errors.New("transferring between external accounts not supports")
// ErrNoCreator contract has no creator information
ErrNoCreator = errors.New("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") ErrDestruct = errors.New("contract has been destructed")
// ErrWriteProtection evm: write protection
ErrWriteProtection = errors.New("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 evm: execution reverted
ErrExecutionReverted = errors.New("evm: execution reverted") ErrExecutionReverted = errors.New("evm: execution reverted")
// ErrMaxCodeSizeExceeded evm: max code size exceeded
ErrMaxCodeSizeExceeded = errors.New("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 输入参数
Input []byte 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()
......
...@@ -19,13 +19,13 @@ import ( ...@@ -19,13 +19,13 @@ import (
) )
type ( type (
// 检查制定账户是否有足够的金额进行转账 // CanTransferFunc 检查制定账户是否有足够的金额进行转账
CanTransferFunc func(state.StateDB, common.Address, common.Address, uint64) bool CanTransferFunc func(state.EVMStateDB, common.Address, common.Address, uint64) bool
// 执行转账逻辑 // TransferFunc 执行转账逻辑
TransferFunc func(state.StateDB, common.Address, common.Address, uint64) bool TransferFunc func(state.EVMStateDB, common.Address, common.Address, uint64) bool
// 获取制定高度区块的哈希 // GetHashFunc 获取制定高度区块的哈希
// 给 BLOCKHASH 指令使用 // 给 BLOCKHASH 指令使用
GetHashFunc func(uint64) common.Hash GetHashFunc func(uint64) common.Hash
) )
...@@ -48,30 +48,32 @@ func run(evm *EVM, contract *Contract, input []byte) (ret []byte, err error) { ...@@ -48,30 +48,32 @@ func run(evm *EVM, contract *Contract, input []byte) (ret []byte, err error) {
return ret, err return ret, err
} }
// EVM操作辅助上下文 // Context EVM操作辅助上下文
// 外部在构造EVM实例时传入,EVM实例构造完成后不允许修改 // 外部在构造EVM实例时传入,EVM实例构造完成后不允许修改
type Context struct { type Context struct {
// 下面这三个方法的说明,请查看方法类型的定义 // CanTransfer 是否可转账
CanTransfer CanTransferFunc CanTransfer CanTransferFunc
// Transfer 转账
Transfer TransferFunc Transfer TransferFunc
// GetHash 获取区块哈希
GetHash GetHashFunc GetHash GetHashFunc
// ORIGIN 指令返回数据, 合约调用者地址 // Origin 指令返回数据, 合约调用者地址
Origin common.Address Origin common.Address
// GASPRICE 指令返回数据 // GasPrice 指令返回数据
GasPrice uint32 GasPrice uint32
// COINBASE 指令, 区块打包者地址 // Coinbase 指令, 区块打包者地址
Coinbase *common.Address Coinbase *common.Address
// GASLIMIT 指令,当前交易的GasLimit // GasLimit 指令,当前交易的GasLimit
GasLimit uint64 GasLimit uint64
// NUMBER 指令,当前区块高度 // BlockNumber NUMBER 指令,当前区块高度
BlockNumber *big.Int BlockNumber *big.Int
// TIME 指令, 当前区块打包时间 // Time 指令, 当前区块打包时间
Time *big.Int Time *big.Int
// DIFFICULTY 指令,当前区块难度 // Difficulty 指令,当前区块难度
Difficulty *big.Int Difficulty *big.Int
} }
...@@ -80,24 +82,24 @@ type Context struct { ...@@ -80,24 +82,24 @@ type Context struct {
// 在合约代码执行过程中发生的任何错误,都将会导致对状态数据的修改被回滚,并且依然消耗掉剩余的Gas // 在合约代码执行过程中发生的任何错误,都将会导致对状态数据的修改被回滚,并且依然消耗掉剩余的Gas
// 此对象为每个交易创建一个实例,其操作非线程安全 // 此对象为每个交易创建一个实例,其操作非线程安全
type EVM struct { type EVM struct {
// 链相关的一些辅助属性和操作方法 // Context 链相关的一些辅助属性和操作方法
Context Context
// 状态数据操作入口 // EVMStateDB 状态数据操作入口
StateDB state.StateDB StateDB state.EVMStateDB
// 当前调用深度 // 当前调用深度
depth int depth int
// 虚拟机配置属性信息 // VMConfig 虚拟机配置属性信息
VmConfig Config VMConfig Config
// EVM指令解释器,生命周期同EVM // Interpreter EVM指令解释器,生命周期同EVM
Interpreter *Interpreter Interpreter *Interpreter
// EVM执行流程结束标志 // EVM执行流程结束标志
// 不允许手工设置 // 不允许手工设置
abort int32 abort int32
// 此属性用于临时存储计算出来的Gas消耗值 // CallGasTemp 此属性用于临时存储计算出来的Gas消耗值
// 在指令执行时,会调用指令的gasCost方法,计算出此指令需要消耗的Gas,并存放在此临时属性中 // 在指令执行时,会调用指令的gasCost方法,计算出此指令需要消耗的Gas,并存放在此临时属性中
// 然后在执行opCall时,从此属性获取消耗的Gas值 // 然后在执行opCall时,从此属性获取消耗的Gas值
CallGasTemp uint64 CallGasTemp uint64
...@@ -106,14 +108,13 @@ type EVM struct { ...@@ -106,14 +108,13 @@ type EVM struct {
maxCodeSize int maxCodeSize int
} }
// 创建一个新的EVM实例对象 // NewEVM 创建一个新的EVM实例对象
// 在同一个节点中,一个EVM实例对象只服务于一个交易执行的生命周期 // 在同一个节点中,一个EVM实例对象只服务于一个交易执行的生命周期
func NewEVM(ctx Context, statedb state.EVMStateDB, vmConfig Config) *EVM {
func NewEVM(ctx Context, statedb state.StateDB, vmConfig Config) *EVM {
evm := &EVM{ evm := &EVM{
Context: ctx, Context: ctx,
StateDB: statedb, StateDB: statedb,
VmConfig: vmConfig, VMConfig: vmConfig,
maxCodeSize: params.MaxCodeSize, maxCodeSize: params.MaxCodeSize,
} }
...@@ -121,18 +122,18 @@ func NewEVM(ctx Context, statedb state.StateDB, vmConfig Config) *EVM { ...@@ -121,18 +122,18 @@ func NewEVM(ctx Context, statedb state.StateDB, vmConfig Config) *EVM {
return evm return evm
} }
// 返回不同操作消耗的Gas定价表 // GasTable 返回不同操作消耗的Gas定价表
// 接收区块高度作为参数,方便以后在这里作分叉处理 // 接收区块高度作为参数,方便以后在这里作分叉处理
func (c *EVM) GasTable(num *big.Int) gas.GasTable { func (evm *EVM) GasTable(num *big.Int) gas.Table {
return gas.GasTableHomestead return gas.TableHomestead
} }
// 调用此操作会在任意时刻取消此EVM的解释运行逻辑,支持重复调用 // Cancel 调用此操作会在任意时刻取消此EVM的解释运行逻辑,支持重复调用
func (evm *EVM) Cancel() { func (evm *EVM) Cancel() {
atomic.StoreInt32(&evm.abort, 1) atomic.StoreInt32(&evm.abort, 1)
} }
// 设置合约代码的最大支持长度 // SetMaxCodeSize 设置合约代码的最大支持长度
func (evm *EVM) SetMaxCodeSize(maxCodeSize int) { func (evm *EVM) SetMaxCodeSize(maxCodeSize int) {
if maxCodeSize < 1 || maxCodeSize > params.MaxCodeSize { if maxCodeSize < 1 || maxCodeSize > params.MaxCodeSize {
return return
...@@ -144,7 +145,7 @@ func (evm *EVM) SetMaxCodeSize(maxCodeSize int) { ...@@ -144,7 +145,7 @@ func (evm *EVM) SetMaxCodeSize(maxCodeSize int) {
// 封装合约的各种调用逻辑中通用的预检查逻辑 // 封装合约的各种调用逻辑中通用的预检查逻辑
func (evm *EVM) preCheck(caller ContractRef, recipient common.Address, value uint64) (pass bool, err error) { func (evm *EVM) preCheck(caller ContractRef, recipient common.Address, value uint64) (pass bool, err error) {
// 检查调用深度是否合法 // 检查调用深度是否合法
if evm.VmConfig.NoRecursion && evm.depth > 0 { if evm.VMConfig.NoRecursion && evm.depth > 0 {
return false, nil return false, nil
} }
...@@ -164,12 +165,11 @@ func (evm *EVM) preCheck(caller ContractRef, recipient common.Address, value uin ...@@ -164,12 +165,11 @@ func (evm *EVM) preCheck(caller ContractRef, recipient common.Address, value uin
return true, nil return true, nil
} }
// 此方法提供合约外部调用入口 // Call 此方法提供合约外部调用入口
// 根据合约地址调用已经存在的合约,input为合约调用参数 // 根据合约地址调用已经存在的合约,input为合约调用参数
// 合约调用逻辑支持在合约调用的同时进行向合约转账的操作 // 合约调用逻辑支持在合约调用的同时进行向合约转账的操作
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value uint64) (ret []byte, snapshot int, leftOverGas uint64, err error) { func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value uint64) (ret []byte, snapshot int, leftOverGas uint64, err error) {
pass := false pass, err := evm.preCheck(caller, addr, value)
pass, err = evm.preCheck(caller, addr, value)
if !pass { if !pass {
return nil, -1, gas, err return nil, -1, gas, err
} }
...@@ -181,16 +181,16 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas ...@@ -181,16 +181,16 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// 只有一种情况会走到这里来,就是合约账户向外部账户转账的情况 // 只有一种情况会走到这里来,就是合约账户向外部账户转账的情况
if len(input) > 0 || value == 0 { if len(input) > 0 || value == 0 {
// 其它情况要求地址必须存在,所以需要报错 // 其它情况要求地址必须存在,所以需要报错
if evm.VmConfig.Debug && evm.depth == 0 { if evm.VMConfig.Debug && evm.depth == 0 {
evm.VmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) evm.VMConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
evm.VmConfig.Tracer.CaptureEnd(ret, 0, 0, nil) evm.VMConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
} }
return nil, -1, gas, model.ErrAddrNotExists return nil, -1, gas, model.ErrAddrNotExists
} }
} else { } else {
// 否则,为预编译合约,创建一个新的账号 // 否则,为预编译合约,创建一个新的账号
// 此分支先屏蔽,不需要为预编译合约创建账号也可以调用合约逻辑,因为预编译合约只有逻辑没有存储状态,可以不对应具体的账号存储 // 此分支先屏蔽,不需要为预编译合约创建账号也可以调用合约逻辑,因为预编译合约只有逻辑没有存储状态,可以不对应具体的账号存储
// evm.StateDB.CreateAccount(addr, caller.Address()) // evm.EVMStateDB.CreateAccount(addr, caller.Address())
} }
} }
...@@ -213,11 +213,11 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas ...@@ -213,11 +213,11 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
start := types.Now() start := types.Now()
// 调试模式下启用跟踪 // 调试模式下启用跟踪
if evm.VmConfig.Debug && evm.depth == 0 { if evm.VMConfig.Debug && evm.depth == 0 {
evm.VmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) evm.VMConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
defer func() { defer func() {
evm.VmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, types.Since(start), err) evm.VMConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, types.Since(start), err)
}() }()
} }
...@@ -238,12 +238,11 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas ...@@ -238,12 +238,11 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
return ret, snapshot, contract.Gas, err return ret, snapshot, contract.Gas, err
} }
// 合约内部调用合约的入口 // CallCode 合约内部调用合约的入口
// 执行逻辑同Call方法,但是有以下几点不同: // 执行逻辑同Call方法,但是有以下几点不同:
// 在创建合约对象时,合约对象的上下文地址(合约对象的self属性)被设置为caller的地址 // 在创建合约对象时,合约对象的上下文地址(合约对象的self属性)被设置为caller的地址
func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value uint64) (ret []byte, leftOverGas uint64, err error) { func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value uint64) (ret []byte, leftOverGas uint64, err error) {
pass := false pass, err := evm.preCheck(caller, addr, value)
pass, err = evm.preCheck(caller, addr, value)
if !pass { if !pass {
return nil, gas, err return nil, gas, err
} }
...@@ -273,12 +272,11 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, ...@@ -273,12 +272,11 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
return ret, contract.Gas, err return ret, contract.Gas, err
} }
// 合约内部调用合约的入口 // DelegateCall 合约内部调用合约的入口
// 不支持向合约转账 // 不支持向合约转账
// 和CallCode不同的是,它会把合约的外部调用地址设置成caller的caller // 和CallCode不同的是,它会把合约的外部调用地址设置成caller的caller
func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
pass := false pass, err := evm.preCheck(caller, addr, 0)
pass, err = evm.preCheck(caller, addr, 0)
if !pass { if !pass {
return nil, gas, err return nil, gas, err
} }
...@@ -309,12 +307,11 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by ...@@ -309,12 +307,11 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
return ret, contract.Gas, err return ret, contract.Gas, err
} }
// 合约内部调用合约的入口 // StaticCall 合约内部调用合约的入口
// 不支持向合约转账 // 不支持向合约转账
// 在合约逻辑中,可以指定其它的合约地址以及输入参数进行合约调用,但是,这种情况下禁止修改MemoryStateDB中的任何数据,否则执行会出错 // 在合约逻辑中,可以指定其它的合约地址以及输入参数进行合约调用,但是,这种情况下禁止修改MemoryStateDB中的任何数据,否则执行会出错
func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
pass := false pass, err := evm.preCheck(caller, addr, 0)
pass, err = evm.preCheck(caller, addr, 0)
if !pass { if !pass {
return nil, gas, err return nil, gas, err
} }
...@@ -355,13 +352,12 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte ...@@ -355,13 +352,12 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
return ret, contract.Gas, err return ret, contract.Gas, err
} }
// 此方法提供合约外部创建入口; // Create 此方法提供合约外部创建入口;
// 使用传入的部署代码创建新的合约; // 使用传入的部署代码创建新的合约;
// 目前chain33为了保证账户安全,不允许合约中涉及到外部账户的转账操作, // 目前chain33为了保证账户安全,不允许合约中涉及到外部账户的转账操作,
// 所以,本步骤不接收转账金额参数 // 所以,本步骤不接收转账金额参数
func (evm *EVM) Create(caller ContractRef, contractAddr common.Address, code []byte, gas uint64, execName, alias string) (ret []byte, snapshot int, leftOverGas uint64, err error) { func (evm *EVM) Create(caller ContractRef, contractAddr common.Address, code []byte, gas uint64, execName, alias string) (ret []byte, snapshot int, leftOverGas uint64, err error) {
pass := false pass, err := evm.preCheck(caller, contractAddr, 0)
pass, err = evm.preCheck(caller, contractAddr, 0)
if !pass { if !pass {
return nil, -1, gas, err return nil, -1, gas, err
} }
...@@ -374,8 +370,8 @@ func (evm *EVM) Create(caller ContractRef, contractAddr common.Address, code []b ...@@ -374,8 +370,8 @@ func (evm *EVM) Create(caller ContractRef, contractAddr common.Address, code []b
snapshot = evm.StateDB.Snapshot() snapshot = evm.StateDB.Snapshot()
evm.StateDB.CreateAccount(contractAddr.String(), contract.CallerAddress.String(), execName, alias) evm.StateDB.CreateAccount(contractAddr.String(), contract.CallerAddress.String(), execName, alias)
if evm.VmConfig.Debug && evm.depth == 0 { if evm.VMConfig.Debug && evm.depth == 0 {
evm.VmConfig.Tracer.CaptureStart(caller.Address(), contractAddr, true, code, gas, 0) evm.VMConfig.Tracer.CaptureStart(caller.Address(), contractAddr, true, code, gas, 0)
} }
start := types.Now() start := types.Now()
...@@ -412,8 +408,8 @@ func (evm *EVM) Create(caller ContractRef, contractAddr common.Address, code []b ...@@ -412,8 +408,8 @@ func (evm *EVM) Create(caller ContractRef, contractAddr common.Address, code []b
err = model.ErrMaxCodeSizeExceeded err = model.ErrMaxCodeSizeExceeded
} }
if evm.VmConfig.Debug && evm.depth == 0 { if evm.VMConfig.Debug && evm.depth == 0 {
evm.VmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, types.Since(start), err) evm.VMConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, types.Since(start), err)
} }
return ret, snapshot, contract.Gas, err return ret, snapshot, contract.Gas, err
......
...@@ -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,25 +15,26 @@ import ( ...@@ -15,25 +15,26 @@ 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 整数内存池
IntPool *mm.IntPool IntPool *mm.IntPool
// 是否允许修改数据 // 是否允许修改数据
...@@ -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逻辑使用
......
...@@ -11,42 +11,45 @@ import ( ...@@ -11,42 +11,45 @@ import (
) )
type ( type (
// 指令执行函数,每个操作指令对应一个实现,它实现了指令的具体操作逻辑 // ExecutionFunc 指令执行函数,每个操作指令对应一个实现,它实现了指令的具体操作逻辑
ExecutionFunc func(pc *uint64, env *EVM, contract *Contract, memory *mm.Memory, stack *mm.Stack) ([]byte, error) ExecutionFunc func(pc *uint64, env *EVM, contract *Contract, memory *mm.Memory, stack *mm.Stack) ([]byte, error)
) )
// 定义指令操作的结构提 // Operation 定义指令操作的结构提
type Operation struct { type Operation struct {
// 指令的具体操作逻辑 // Execute 指令的具体操作逻辑
Execute ExecutionFunc Execute ExecutionFunc
// 计算当前指令执行所需消耗的Gas // GasCost 计算当前指令执行所需消耗的Gas
GasCost gas.GasFunc GasCost gas.CalcGasFunc
// 检查内存栈中的数据是否满足本操作执行的要求 // ValidateStack 检查内存栈中的数据是否满足本操作执行的要求
ValidateStack mm.StackValidationFunc ValidateStack mm.StackValidationFunc
// 计算本次操作所需要的内存大小 // MemorySize 计算本次操作所需要的内存大小
MemorySize mm.MemorySizeFunc MemorySize mm.MemorySizeFunc
Halts bool // 是否需要暂停(将会结束本合约后面操作的执行) // Halts 是否需要暂停(将会结束本合约后面操作的执行)
Jumps bool // 是否需要执行跳转(此种情况下PC不递增) Halts bool
Writes bool // 是否涉及到修改状态操作(在合约委托调用的情况下,此操作非法,将会抛异常) // Jumps 是否需要执行跳转(此种情况下PC不递增)
Valid bool // 是否为有效操作 Jumps bool
Reverts bool // 是否恢复原始状态(强制暂停,将会结束本合约后面操作的执行) // Writes 是否涉及到修改状态操作(在合约委托调用的情况下,此操作非法,将会抛异常)
Returns bool // 是否返回 Writes bool
// Valid 是否为有效操作
Valid bool
// Reverts 是否恢复原始状态(强制暂停,将会结束本合约后面操作的执行)
Reverts bool
// Returns 是否返回
Returns bool
} }
var ( var (
// 对应EVM不同版本的指令集,从上往下,从旧版本到新版本, // ConstantinopleInstructionSet 对应EVM不同版本的指令集,从上往下,从旧版本到新版本,
// 新版本包含旧版本的指令集(目前直接使用康士坦丁堡指令集) // 新版本包含旧版本的指令集(目前直接使用康士坦丁堡指令集)
FrontierInstructionSet = NewFrontierInstructionSet()
HomesteadInstructionSet = NewHomesteadInstructionSet()
ByzantiumInstructionSet = NewByzantiumInstructionSet()
ConstantinopleInstructionSet = NewConstantinopleInstructionSet() ConstantinopleInstructionSet = NewConstantinopleInstructionSet()
) )
// 康士坦丁堡 版本支持的指令集 // NewConstantinopleInstructionSet 康士坦丁堡 版本支持的指令集
func NewConstantinopleInstructionSet() [256]Operation { func NewConstantinopleInstructionSet() [256]Operation {
instructionSet := NewByzantiumInstructionSet() instructionSet := NewByzantiumInstructionSet()
instructionSet[SHL] = Operation{ instructionSet[SHL] = Operation{
...@@ -70,12 +73,12 @@ func NewConstantinopleInstructionSet() [256]Operation { ...@@ -70,12 +73,12 @@ func NewConstantinopleInstructionSet() [256]Operation {
return instructionSet return instructionSet
} }
// 拜占庭 版本支持的指令集 // NewByzantiumInstructionSet 拜占庭 版本支持的指令集
func NewByzantiumInstructionSet() [256]Operation { func NewByzantiumInstructionSet() [256]Operation {
instructionSet := NewHomesteadInstructionSet() instructionSet := NewHomesteadInstructionSet()
instructionSet[STATICCALL] = Operation{ instructionSet[STATICCALL] = Operation{
Execute: opStaticCall, Execute: opStaticCall,
GasCost: gas.GasStaticCall, GasCost: gas.StaticCall,
ValidateStack: mm.MakeStackFunc(6, 1), ValidateStack: mm.MakeStackFunc(6, 1),
MemorySize: mm.MemoryStaticCall, MemorySize: mm.MemoryStaticCall,
Valid: true, Valid: true,
...@@ -89,14 +92,14 @@ func NewByzantiumInstructionSet() [256]Operation { ...@@ -89,14 +92,14 @@ func NewByzantiumInstructionSet() [256]Operation {
} }
instructionSet[RETURNDATACOPY] = Operation{ instructionSet[RETURNDATACOPY] = Operation{
Execute: opReturnDataCopy, Execute: opReturnDataCopy,
GasCost: gas.GasReturnDataCopy, GasCost: gas.ReturnDataCopy,
ValidateStack: mm.MakeStackFunc(3, 0), ValidateStack: mm.MakeStackFunc(3, 0),
MemorySize: mm.MemoryReturnDataCopy, MemorySize: mm.MemoryReturnDataCopy,
Valid: true, Valid: true,
} }
instructionSet[REVERT] = Operation{ instructionSet[REVERT] = Operation{
Execute: opRevert, Execute: opRevert,
GasCost: gas.GasRevert, GasCost: gas.Revert,
ValidateStack: mm.MakeStackFunc(2, 0), ValidateStack: mm.MakeStackFunc(2, 0),
MemorySize: mm.MemoryRevert, MemorySize: mm.MemoryRevert,
Valid: true, Valid: true,
...@@ -106,12 +109,12 @@ func NewByzantiumInstructionSet() [256]Operation { ...@@ -106,12 +109,12 @@ func NewByzantiumInstructionSet() [256]Operation {
return instructionSet return instructionSet
} }
// 家园 版本支持的指令集 // NewHomesteadInstructionSet 家园 版本支持的指令集
func NewHomesteadInstructionSet() [256]Operation { func NewHomesteadInstructionSet() [256]Operation {
instructionSet := NewFrontierInstructionSet() instructionSet := NewFrontierInstructionSet()
instructionSet[DELEGATECALL] = Operation{ instructionSet[DELEGATECALL] = Operation{
Execute: opDelegateCall, Execute: opDelegateCall,
GasCost: gas.GasDelegateCall, GasCost: gas.DelegateCall,
ValidateStack: mm.MakeStackFunc(6, 1), ValidateStack: mm.MakeStackFunc(6, 1),
MemorySize: mm.MemoryDelegateCall, MemorySize: mm.MemoryDelegateCall,
Valid: true, Valid: true,
...@@ -120,7 +123,7 @@ func NewHomesteadInstructionSet() [256]Operation { ...@@ -120,7 +123,7 @@ func NewHomesteadInstructionSet() [256]Operation {
return instructionSet return instructionSet
} }
// 边境 版本支持的指令集 // NewFrontierInstructionSet 边境 版本支持的指令集
func NewFrontierInstructionSet() [256]Operation { func NewFrontierInstructionSet() [256]Operation {
return [256]Operation{ return [256]Operation{
STOP: { STOP: {
...@@ -186,7 +189,7 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -186,7 +189,7 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
EXP: { EXP: {
Execute: opExp, Execute: opExp,
GasCost: gas.GasExp, GasCost: gas.Exp,
ValidateStack: mm.MakeStackFunc(2, 1), ValidateStack: mm.MakeStackFunc(2, 1),
Valid: true, Valid: true,
}, },
...@@ -264,7 +267,7 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -264,7 +267,7 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
SHA3: { SHA3: {
Execute: opSha3, Execute: opSha3,
GasCost: gas.GasSha3, GasCost: gas.Sha3,
ValidateStack: mm.MakeStackFunc(2, 1), ValidateStack: mm.MakeStackFunc(2, 1),
MemorySize: mm.MemorySha3, MemorySize: mm.MemorySha3,
Valid: true, Valid: true,
...@@ -277,7 +280,7 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -277,7 +280,7 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
BALANCE: { BALANCE: {
Execute: opBalance, Execute: opBalance,
GasCost: gas.GasBalance, GasCost: gas.Balance,
ValidateStack: mm.MakeStackFunc(1, 1), ValidateStack: mm.MakeStackFunc(1, 1),
Valid: true, Valid: true,
}, },
...@@ -313,7 +316,7 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -313,7 +316,7 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
CALLDATACOPY: { CALLDATACOPY: {
Execute: opCallDataCopy, Execute: opCallDataCopy,
GasCost: gas.GasCallDataCopy, GasCost: gas.CallDataCopy,
ValidateStack: mm.MakeStackFunc(3, 0), ValidateStack: mm.MakeStackFunc(3, 0),
MemorySize: mm.MemoryCallDataCopy, MemorySize: mm.MemoryCallDataCopy,
Valid: true, Valid: true,
...@@ -326,7 +329,7 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -326,7 +329,7 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
CODECOPY: { CODECOPY: {
Execute: opCodeCopy, Execute: opCodeCopy,
GasCost: gas.GasCodeCopy, GasCost: gas.CodeCopy,
ValidateStack: mm.MakeStackFunc(3, 0), ValidateStack: mm.MakeStackFunc(3, 0),
MemorySize: mm.MemoryCodeCopy, MemorySize: mm.MemoryCodeCopy,
Valid: true, Valid: true,
...@@ -339,13 +342,13 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -339,13 +342,13 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
EXTCODESIZE: { EXTCODESIZE: {
Execute: opExtCodeSize, Execute: opExtCodeSize,
GasCost: gas.GasExtCodeSize, GasCost: gas.ExtCodeSize,
ValidateStack: mm.MakeStackFunc(1, 1), ValidateStack: mm.MakeStackFunc(1, 1),
Valid: true, Valid: true,
}, },
EXTCODECOPY: { EXTCODECOPY: {
Execute: opExtCodeCopy, Execute: opExtCodeCopy,
GasCost: gas.GasExtCodeCopy, GasCost: gas.ExtCodeCopy,
ValidateStack: mm.MakeStackFunc(4, 0), ValidateStack: mm.MakeStackFunc(4, 0),
MemorySize: mm.MemoryExtCodeCopy, MemorySize: mm.MemoryExtCodeCopy,
Valid: true, Valid: true,
...@@ -394,21 +397,21 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -394,21 +397,21 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
MLOAD: { MLOAD: {
Execute: opMload, Execute: opMload,
GasCost: gas.GasMLoad, GasCost: gas.MLoad,
ValidateStack: mm.MakeStackFunc(1, 1), ValidateStack: mm.MakeStackFunc(1, 1),
MemorySize: mm.MemoryMLoad, MemorySize: mm.MemoryMLoad,
Valid: true, Valid: true,
}, },
MSTORE: { MSTORE: {
Execute: opMstore, Execute: opMstore,
GasCost: gas.GasMStore, GasCost: gas.MStore,
ValidateStack: mm.MakeStackFunc(2, 0), ValidateStack: mm.MakeStackFunc(2, 0),
MemorySize: mm.MemoryMStore, MemorySize: mm.MemoryMStore,
Valid: true, Valid: true,
}, },
MSTORE8: { MSTORE8: {
Execute: opMstore8, Execute: opMstore8,
GasCost: gas.GasMStore8, GasCost: gas.MStore8,
MemorySize: mm.MemoryMStore8, MemorySize: mm.MemoryMStore8,
ValidateStack: mm.MakeStackFunc(2, 0), ValidateStack: mm.MakeStackFunc(2, 0),
...@@ -416,13 +419,13 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -416,13 +419,13 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
SLOAD: { SLOAD: {
Execute: opSload, Execute: opSload,
GasCost: gas.GasSLoad, GasCost: gas.SLoad,
ValidateStack: mm.MakeStackFunc(1, 1), ValidateStack: mm.MakeStackFunc(1, 1),
Valid: true, Valid: true,
}, },
SSTORE: { SSTORE: {
Execute: opSstore, Execute: opSstore,
GasCost: gas.GasSStore, GasCost: gas.SStore,
ValidateStack: mm.MakeStackFunc(2, 0), ValidateStack: mm.MakeStackFunc(2, 0),
Valid: true, Valid: true,
Writes: true, Writes: true,
...@@ -467,385 +470,385 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -467,385 +470,385 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
PUSH1: { PUSH1: {
Execute: makePush(1, 1), Execute: makePush(1, 1),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH2: { PUSH2: {
Execute: makePush(2, 2), Execute: makePush(2, 2),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH3: { PUSH3: {
Execute: makePush(3, 3), Execute: makePush(3, 3),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH4: { PUSH4: {
Execute: makePush(4, 4), Execute: makePush(4, 4),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH5: { PUSH5: {
Execute: makePush(5, 5), Execute: makePush(5, 5),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH6: { PUSH6: {
Execute: makePush(6, 6), Execute: makePush(6, 6),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH7: { PUSH7: {
Execute: makePush(7, 7), Execute: makePush(7, 7),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH8: { PUSH8: {
Execute: makePush(8, 8), Execute: makePush(8, 8),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH9: { PUSH9: {
Execute: makePush(9, 9), Execute: makePush(9, 9),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH10: { PUSH10: {
Execute: makePush(10, 10), Execute: makePush(10, 10),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH11: { PUSH11: {
Execute: makePush(11, 11), Execute: makePush(11, 11),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH12: { PUSH12: {
Execute: makePush(12, 12), Execute: makePush(12, 12),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH13: { PUSH13: {
Execute: makePush(13, 13), Execute: makePush(13, 13),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH14: { PUSH14: {
Execute: makePush(14, 14), Execute: makePush(14, 14),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH15: { PUSH15: {
Execute: makePush(15, 15), Execute: makePush(15, 15),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH16: { PUSH16: {
Execute: makePush(16, 16), Execute: makePush(16, 16),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH17: { PUSH17: {
Execute: makePush(17, 17), Execute: makePush(17, 17),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH18: { PUSH18: {
Execute: makePush(18, 18), Execute: makePush(18, 18),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH19: { PUSH19: {
Execute: makePush(19, 19), Execute: makePush(19, 19),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH20: { PUSH20: {
Execute: makePush(20, 20), Execute: makePush(20, 20),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH21: { PUSH21: {
Execute: makePush(21, 21), Execute: makePush(21, 21),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH22: { PUSH22: {
Execute: makePush(22, 22), Execute: makePush(22, 22),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH23: { PUSH23: {
Execute: makePush(23, 23), Execute: makePush(23, 23),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH24: { PUSH24: {
Execute: makePush(24, 24), Execute: makePush(24, 24),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH25: { PUSH25: {
Execute: makePush(25, 25), Execute: makePush(25, 25),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH26: { PUSH26: {
Execute: makePush(26, 26), Execute: makePush(26, 26),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH27: { PUSH27: {
Execute: makePush(27, 27), Execute: makePush(27, 27),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH28: { PUSH28: {
Execute: makePush(28, 28), Execute: makePush(28, 28),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH29: { PUSH29: {
Execute: makePush(29, 29), Execute: makePush(29, 29),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH30: { PUSH30: {
Execute: makePush(30, 30), Execute: makePush(30, 30),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH31: { PUSH31: {
Execute: makePush(31, 31), Execute: makePush(31, 31),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
PUSH32: { PUSH32: {
Execute: makePush(32, 32), Execute: makePush(32, 32),
GasCost: gas.GasPush, GasCost: gas.Push,
ValidateStack: mm.MakeStackFunc(0, 1), ValidateStack: mm.MakeStackFunc(0, 1),
Valid: true, Valid: true,
}, },
DUP1: { DUP1: {
Execute: makeDup(1), Execute: makeDup(1),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(1), ValidateStack: mm.MakeDupStackFunc(1),
Valid: true, Valid: true,
}, },
DUP2: { DUP2: {
Execute: makeDup(2), Execute: makeDup(2),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(2), ValidateStack: mm.MakeDupStackFunc(2),
Valid: true, Valid: true,
}, },
DUP3: { DUP3: {
Execute: makeDup(3), Execute: makeDup(3),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(3), ValidateStack: mm.MakeDupStackFunc(3),
Valid: true, Valid: true,
}, },
DUP4: { DUP4: {
Execute: makeDup(4), Execute: makeDup(4),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(4), ValidateStack: mm.MakeDupStackFunc(4),
Valid: true, Valid: true,
}, },
DUP5: { DUP5: {
Execute: makeDup(5), Execute: makeDup(5),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(5), ValidateStack: mm.MakeDupStackFunc(5),
Valid: true, Valid: true,
}, },
DUP6: { DUP6: {
Execute: makeDup(6), Execute: makeDup(6),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(6), ValidateStack: mm.MakeDupStackFunc(6),
Valid: true, Valid: true,
}, },
DUP7: { DUP7: {
Execute: makeDup(7), Execute: makeDup(7),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(7), ValidateStack: mm.MakeDupStackFunc(7),
Valid: true, Valid: true,
}, },
DUP8: { DUP8: {
Execute: makeDup(8), Execute: makeDup(8),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(8), ValidateStack: mm.MakeDupStackFunc(8),
Valid: true, Valid: true,
}, },
DUP9: { DUP9: {
Execute: makeDup(9), Execute: makeDup(9),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(9), ValidateStack: mm.MakeDupStackFunc(9),
Valid: true, Valid: true,
}, },
DUP10: { DUP10: {
Execute: makeDup(10), Execute: makeDup(10),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(10), ValidateStack: mm.MakeDupStackFunc(10),
Valid: true, Valid: true,
}, },
DUP11: { DUP11: {
Execute: makeDup(11), Execute: makeDup(11),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(11), ValidateStack: mm.MakeDupStackFunc(11),
Valid: true, Valid: true,
}, },
DUP12: { DUP12: {
Execute: makeDup(12), Execute: makeDup(12),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(12), ValidateStack: mm.MakeDupStackFunc(12),
Valid: true, Valid: true,
}, },
DUP13: { DUP13: {
Execute: makeDup(13), Execute: makeDup(13),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(13), ValidateStack: mm.MakeDupStackFunc(13),
Valid: true, Valid: true,
}, },
DUP14: { DUP14: {
Execute: makeDup(14), Execute: makeDup(14),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(14), ValidateStack: mm.MakeDupStackFunc(14),
Valid: true, Valid: true,
}, },
DUP15: { DUP15: {
Execute: makeDup(15), Execute: makeDup(15),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(15), ValidateStack: mm.MakeDupStackFunc(15),
Valid: true, Valid: true,
}, },
DUP16: { DUP16: {
Execute: makeDup(16), Execute: makeDup(16),
GasCost: gas.GasDup, GasCost: gas.Dup,
ValidateStack: mm.MakeDupStackFunc(16), ValidateStack: mm.MakeDupStackFunc(16),
Valid: true, Valid: true,
}, },
SWAP1: { SWAP1: {
Execute: makeSwap(1), Execute: makeSwap(1),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(2), ValidateStack: mm.MakeSwapStackFunc(2),
Valid: true, Valid: true,
}, },
SWAP2: { SWAP2: {
Execute: makeSwap(2), Execute: makeSwap(2),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(3), ValidateStack: mm.MakeSwapStackFunc(3),
Valid: true, Valid: true,
}, },
SWAP3: { SWAP3: {
Execute: makeSwap(3), Execute: makeSwap(3),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(4), ValidateStack: mm.MakeSwapStackFunc(4),
Valid: true, Valid: true,
}, },
SWAP4: { SWAP4: {
Execute: makeSwap(4), Execute: makeSwap(4),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(5), ValidateStack: mm.MakeSwapStackFunc(5),
Valid: true, Valid: true,
}, },
SWAP5: { SWAP5: {
Execute: makeSwap(5), Execute: makeSwap(5),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(6), ValidateStack: mm.MakeSwapStackFunc(6),
Valid: true, Valid: true,
}, },
SWAP6: { SWAP6: {
Execute: makeSwap(6), Execute: makeSwap(6),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(7), ValidateStack: mm.MakeSwapStackFunc(7),
Valid: true, Valid: true,
}, },
SWAP7: { SWAP7: {
Execute: makeSwap(7), Execute: makeSwap(7),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(8), ValidateStack: mm.MakeSwapStackFunc(8),
Valid: true, Valid: true,
}, },
SWAP8: { SWAP8: {
Execute: makeSwap(8), Execute: makeSwap(8),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(9), ValidateStack: mm.MakeSwapStackFunc(9),
Valid: true, Valid: true,
}, },
SWAP9: { SWAP9: {
Execute: makeSwap(9), Execute: makeSwap(9),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(10), ValidateStack: mm.MakeSwapStackFunc(10),
Valid: true, Valid: true,
}, },
SWAP10: { SWAP10: {
Execute: makeSwap(10), Execute: makeSwap(10),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(11), ValidateStack: mm.MakeSwapStackFunc(11),
Valid: true, Valid: true,
}, },
SWAP11: { SWAP11: {
Execute: makeSwap(11), Execute: makeSwap(11),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(12), ValidateStack: mm.MakeSwapStackFunc(12),
Valid: true, Valid: true,
}, },
SWAP12: { SWAP12: {
Execute: makeSwap(12), Execute: makeSwap(12),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(13), ValidateStack: mm.MakeSwapStackFunc(13),
Valid: true, Valid: true,
}, },
SWAP13: { SWAP13: {
Execute: makeSwap(13), Execute: makeSwap(13),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(14), ValidateStack: mm.MakeSwapStackFunc(14),
Valid: true, Valid: true,
}, },
SWAP14: { SWAP14: {
Execute: makeSwap(14), Execute: makeSwap(14),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(15), ValidateStack: mm.MakeSwapStackFunc(15),
Valid: true, Valid: true,
}, },
SWAP15: { SWAP15: {
Execute: makeSwap(15), Execute: makeSwap(15),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(16), ValidateStack: mm.MakeSwapStackFunc(16),
Valid: true, Valid: true,
}, },
SWAP16: { SWAP16: {
Execute: makeSwap(16), Execute: makeSwap(16),
GasCost: gas.GasSwap, GasCost: gas.Swap,
ValidateStack: mm.MakeSwapStackFunc(17), ValidateStack: mm.MakeSwapStackFunc(17),
Valid: true, Valid: true,
}, },
...@@ -891,7 +894,7 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -891,7 +894,7 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
CREATE: { CREATE: {
Execute: opCreate, Execute: opCreate,
GasCost: gas.GasCreate, GasCost: gas.Create,
ValidateStack: mm.MakeStackFunc(3, 1), ValidateStack: mm.MakeStackFunc(3, 1),
MemorySize: mm.MemoryCreate, MemorySize: mm.MemoryCreate,
Valid: true, Valid: true,
...@@ -900,7 +903,7 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -900,7 +903,7 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
CALL: { CALL: {
Execute: opCall, Execute: opCall,
GasCost: gas.GasCall, GasCost: gas.Call,
ValidateStack: mm.MakeStackFunc(7, 1), ValidateStack: mm.MakeStackFunc(7, 1),
MemorySize: mm.MemoryCall, MemorySize: mm.MemoryCall,
Valid: true, Valid: true,
...@@ -908,7 +911,7 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -908,7 +911,7 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
CALLCODE: { CALLCODE: {
Execute: opCallCode, Execute: opCallCode,
GasCost: gas.GasCallCode, GasCost: gas.CallCode,
ValidateStack: mm.MakeStackFunc(7, 1), ValidateStack: mm.MakeStackFunc(7, 1),
MemorySize: mm.MemoryCall, MemorySize: mm.MemoryCall,
Valid: true, Valid: true,
...@@ -916,7 +919,7 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -916,7 +919,7 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
RETURN: { RETURN: {
Execute: opReturn, Execute: opReturn,
GasCost: gas.GasReturn, GasCost: gas.Return,
ValidateStack: mm.MakeStackFunc(2, 0), ValidateStack: mm.MakeStackFunc(2, 0),
MemorySize: mm.MemoryReturn, MemorySize: mm.MemoryReturn,
Halts: true, Halts: true,
...@@ -924,7 +927,7 @@ func NewFrontierInstructionSet() [256]Operation { ...@@ -924,7 +927,7 @@ func NewFrontierInstructionSet() [256]Operation {
}, },
SELFDESTRUCT: { SELFDESTRUCT: {
Execute: opSuicide, Execute: opSuicide,
GasCost: gas.GasSuicide, GasCost: gas.Suicide,
ValidateStack: mm.MakeStackFunc(1, 0), ValidateStack: mm.MakeStackFunc(1, 0),
Halts: true, Halts: true,
Valid: true, Valid: true,
......
...@@ -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 pc指针
Pc uint64 `json:"pc"` Pc uint64 `json:"pc"`
// Op 操作码
Op string `json:"op"` Op string `json:"op"`
// Gas gas
Gas uint64 `json:"gas"` Gas uint64 `json:"gas"`
// GasCost 花费
GasCost uint64 `json:"gasCost"` GasCost uint64 `json:"gasCost"`
// Memory 内存对象
Memory []string `json:"memory"` Memory []string `json:"memory"`
// MemorySize 内存大小
MemorySize int `json:"memSize"` MemorySize int `json:"memSize"`
// Stack 栈对象
Stack []string `json:"stack"` Stack []string `json:"stack"`
// Storage 存储对象
Storage map[common.Hash]common.Hash `json:"-"` Storage map[common.Hash]common.Hash `json:"-"`
// Depth 调用深度
Depth int `json:"depth"` Depth int `json:"depth"`
// Err 错误信息
Err error `json:"-"` 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 op
REVERT = 0xfd REVERT = 0xfd
// SELFDESTRUCT op
SELFDESTRUCT = 0xff SELFDESTRUCT = 0xff
) )
...@@ -15,24 +15,24 @@ import ( ...@@ -15,24 +15,24 @@ import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
) )
// 合约账户对象 // ContractAccount 合约账户对象
type ContractAccount struct { type ContractAccount struct {
mdb *MemoryStateDB mdb *MemoryStateDB
// 合约代码地址 // Addr 合约代码地址
Addr string Addr string
// 合约固定数据 // Data 合约固定数据
Data evmtypes.EVMContractData Data evmtypes.EVMContractData
// 合约状态数据 // State 合约状态数据
State evmtypes.EVMContractState State evmtypes.EVMContractState
// 当前的状态数据缓存 // 当前的状态数据缓存
stateCache map[string]common.Hash stateCache map[string]common.Hash
} }
// 创建一个新的合约对象 // NewContractAccount 创建一个新的合约对象
// 注意,此时合约对象有可能已经存在也有可能不存在 // 注意,此时合约对象有可能已经存在也有可能不存在
// 需要通过LoadContract进行判断 // 需要通过LoadContract进行判断
func NewContractAccount(addr string, db *MemoryStateDB) *ContractAccount { func NewContractAccount(addr string, db *MemoryStateDB) *ContractAccount {
...@@ -46,74 +46,73 @@ func NewContractAccount(addr string, db *MemoryStateDB) *ContractAccount { ...@@ -46,74 +46,73 @@ func NewContractAccount(addr string, db *MemoryStateDB) *ContractAccount {
return ca return ca
} }
// 获取状态数据; // GetState 获取状态数据;
// 获取数据分为两层,一层是从当前的缓存中获取,如果获取不到,再从localdb中获取 // 获取数据分为两层,一层是从当前的缓存中获取,如果获取不到,再从localdb中获取
func (self *ContractAccount) GetState(key common.Hash) common.Hash { func (ca *ContractAccount) GetState(key common.Hash) common.Hash {
// 从ForkV19开始,状态数据使用单独的KEY存储 // 从ForkV19开始,状态数据使用单独的KEY存储
if types.IsDappFork(self.mdb.blockHeight, "evm", "ForkEVMState") { if types.IsDappFork(ca.mdb.blockHeight, "evm", "ForkEVMState") {
if val, ok := self.stateCache[key.Hex()]; ok { if val, ok := ca.stateCache[key.Hex()]; ok {
return val return val
} }
keyStr := getStateItemKey(self.Addr, key.Hex()) keyStr := getStateItemKey(ca.Addr, key.Hex())
// 如果缓存中取不到数据,则只能到本地数据库中查询 // 如果缓存中取不到数据,则只能到本地数据库中查询
val, err := self.mdb.LocalDB.Get([]byte(keyStr)) val, err := ca.mdb.LocalDB.Get([]byte(keyStr))
if err != nil { if err != nil {
log15.Debug("GetState error!", "key", key, "error", err) log15.Debug("GetState error!", "key", key, "error", err)
return common.Hash{} return common.Hash{}
} }
valHash := common.BytesToHash(val) valHash := common.BytesToHash(val)
self.stateCache[key.Hex()] = valHash ca.stateCache[key.Hex()] = valHash
return valHash return valHash
} else {
return common.BytesToHash(self.State.GetStorage()[key.Hex()])
} }
return common.BytesToHash(ca.State.GetStorage()[key.Hex()])
} }
// 设置状态数据 // SetState 设置状态数据
func (self *ContractAccount) SetState(key, value common.Hash) { func (ca *ContractAccount) SetState(key, value common.Hash) {
self.mdb.addChange(storageChange{ ca.mdb.addChange(storageChange{
baseChange: baseChange{}, baseChange: baseChange{},
account: self.Addr, account: ca.Addr,
key: key, key: key,
prevalue: self.GetState(key), prevalue: ca.GetState(key),
}) })
if types.IsDappFork(self.mdb.blockHeight, "evm", "ForkEVMState") { if types.IsDappFork(ca.mdb.blockHeight, "evm", "ForkEVMState") {
self.stateCache[key.Hex()] = value ca.stateCache[key.Hex()] = value
//需要设置到localdb中,以免同一个区块中同一个合约多次调用时,状态数据丢失 //需要设置到localdb中,以免同一个区块中同一个合约多次调用时,状态数据丢失
keyStr := getStateItemKey(self.Addr, key.Hex()) keyStr := getStateItemKey(ca.Addr, key.Hex())
self.mdb.LocalDB.Set([]byte(keyStr), value.Bytes()) ca.mdb.LocalDB.Set([]byte(keyStr), value.Bytes())
} else { } else {
self.State.GetStorage()[key.Hex()] = value.Bytes() ca.State.GetStorage()[key.Hex()] = value.Bytes()
self.updateStorageHash() ca.updateStorageHash()
} }
} }
// 从原有的存储在一个对象,将状态数据分散存储到多个KEY,保证合约可以支撑大量状态数据 // TransferState 从原有的存储在一个对象,将状态数据分散存储到多个KEY,保证合约可以支撑大量状态数据
func (self *ContractAccount) TransferState() { func (ca *ContractAccount) TransferState() {
if len(self.State.Storage) > 0 { if len(ca.State.Storage) > 0 {
storage := self.State.Storage storage := ca.State.Storage
// 为了保证不会造成新、旧数据并存的情况,需要将旧的状态数据清空 // 为了保证不会造成新、旧数据并存的情况,需要将旧的状态数据清空
self.State.Storage = make(map[string][]byte) ca.State.Storage = make(map[string][]byte)
self.State.StorageHash = common.ToHash([]byte{}).Bytes() ca.State.StorageHash = common.ToHash([]byte{}).Bytes()
// 从旧的区块迁移状态数据到新的区块,模拟状态数据变更的操作 // 从旧的区块迁移状态数据到新的区块,模拟状态数据变更的操作
for key, value := range storage { for key, value := range storage {
self.SetState(common.BytesToHash(common.FromHex(key)), common.BytesToHash(value)) ca.SetState(common.BytesToHash(common.FromHex(key)), common.BytesToHash(value))
} }
// 更新本合约的状态数据(删除旧的map存储信息) // 更新本合约的状态数据(删除旧的map存储信息)
self.mdb.UpdateState(self.Addr) ca.mdb.UpdateState(ca.Addr)
return return
} }
} }
func (self *ContractAccount) updateStorageHash() { func (ca *ContractAccount) updateStorageHash() {
// 从ForkV20开始,状态数据使用单独KEY存储 // 从ForkV20开始,状态数据使用单独KEY存储
if types.IsDappFork(self.mdb.blockHeight, "evm", "ForkEVMState") { if types.IsDappFork(ca.mdb.blockHeight, "evm", "ForkEVMState") {
return return
} }
var state = &evmtypes.EVMContractState{Suicided: self.State.Suicided, Nonce: self.State.Nonce} var state = &evmtypes.EVMContractState{Suicided: ca.State.Suicided, Nonce: ca.State.Nonce}
state.Storage = make(map[string][]byte) state.Storage = make(map[string][]byte)
for k, v := range self.State.GetStorage() { for k, v := range ca.State.GetStorage() {
state.Storage[k] = v state.Storage[k] = v
} }
ret, err := proto.Marshal(state) ret, err := proto.Marshal(state)
...@@ -122,152 +121,160 @@ func (self *ContractAccount) updateStorageHash() { ...@@ -122,152 +121,160 @@ func (self *ContractAccount) updateStorageHash() {
return return
} }
self.State.StorageHash = common.ToHash(ret).Bytes() ca.State.StorageHash = common.ToHash(ret).Bytes()
} }
// 从外部恢复合约数据 // 从外部恢复合约数据
func (self *ContractAccount) resotreData(data []byte) { func (ca *ContractAccount) resotreData(data []byte) {
var content evmtypes.EVMContractData var content evmtypes.EVMContractData
err := proto.Unmarshal(data, &content) err := proto.Unmarshal(data, &content)
if err != nil { if err != nil {
log15.Error("read contract data error", self.Addr) log15.Error("read contract data error", ca.Addr)
return return
} }
self.Data = content ca.Data = content
} }
// 从外部恢复合约状态 // 从外部恢复合约状态
func (self *ContractAccount) resotreState(data []byte) { func (ca *ContractAccount) resotreState(data []byte) {
var content evmtypes.EVMContractState var content evmtypes.EVMContractState
err := proto.Unmarshal(data, &content) err := proto.Unmarshal(data, &content)
if err != nil { if err != nil {
log15.Error("read contract state error", self.Addr) log15.Error("read contract state error", ca.Addr)
return return
} }
self.State = content ca.State = content
if self.State.Storage == nil { if ca.State.Storage == nil {
self.State.Storage = make(map[string][]byte) ca.State.Storage = make(map[string][]byte)
} }
} }
// 从数据库中加载合约信息(在只有合约地址的情况下) // LoadContract 从数据库中加载合约信息(在只有合约地址的情况下)
func (self *ContractAccount) LoadContract(db db.KV) { func (ca *ContractAccount) LoadContract(db db.KV) {
// 加载代码数据 // 加载代码数据
data, err := db.Get(self.GetDataKey()) data, err := db.Get(ca.GetDataKey())
if err != nil { if err != nil {
return return
} }
self.resotreData(data) ca.resotreData(data)
// 加载状态数据 // 加载状态数据
data, err = db.Get(self.GetStateKey()) data, err = db.Get(ca.GetStateKey())
if err != nil { if err != nil {
return return
} }
self.resotreState(data) ca.resotreState(data)
} }
// 设置合约二进制代码 // SetCode 设置合约二进制代码
// 会同步生成代码哈希 // 会同步生成代码哈希
func (self *ContractAccount) SetCode(code []byte) { func (ca *ContractAccount) SetCode(code []byte) {
prevcode := self.Data.GetCode() prevcode := ca.Data.GetCode()
self.mdb.addChange(codeChange{ ca.mdb.addChange(codeChange{
baseChange: baseChange{}, baseChange: baseChange{},
account: self.Addr, account: ca.Addr,
prevhash: self.Data.GetCodeHash(), prevhash: ca.Data.GetCodeHash(),
prevcode: prevcode, prevcode: prevcode,
}) })
self.Data.Code = code ca.Data.Code = code
self.Data.CodeHash = common.ToHash(code).Bytes() ca.Data.CodeHash = common.ToHash(code).Bytes()
} }
func (self *ContractAccount) SetCreator(creator string) { // SetCreator 设置创建者
func (ca *ContractAccount) SetCreator(creator string) {
if len(creator) == 0 { if len(creator) == 0 {
log15.Error("SetCreator error", "creator", creator) log15.Error("SetCreator error", "creator", creator)
return return
} }
self.Data.Creator = creator ca.Data.Creator = creator
} }
func (self *ContractAccount) SetExecName(execName string) { // SetExecName 设置合约名称
func (ca *ContractAccount) SetExecName(execName string) {
if len(execName) == 0 { if len(execName) == 0 {
log15.Error("SetExecName error", "execName", execName) log15.Error("SetExecName error", "execName", execName)
return return
} }
self.Data.Name = execName ca.Data.Name = execName
} }
func (self *ContractAccount) SetAliasName(alias string) { // SetAliasName 设置合约别名
func (ca *ContractAccount) SetAliasName(alias string) {
if len(alias) == 0 { if len(alias) == 0 {
log15.Error("SetAliasName error", "aliasName", alias) log15.Error("SetAliasName error", "aliasName", alias)
return return
} }
self.Data.Alias = alias ca.Data.Alias = alias
} }
func (self *ContractAccount) GetAliasName() string { // GetAliasName 获取合约别名
return self.Data.Alias func (ca *ContractAccount) GetAliasName() string {
return ca.Data.Alias
} }
func (self *ContractAccount) GetCreator() string { // GetCreator 获取创建者
return self.Data.Creator func (ca *ContractAccount) GetCreator() string {
return ca.Data.Creator
} }
func (self *ContractAccount) GetExecName() string { // GetExecName 获取合约明名称
return self.Data.Name func (ca *ContractAccount) GetExecName() string {
return ca.Data.Name
} }
// 合约固定数据,包含合约代码,以及代码哈希 // GetDataKV 合约固定数据,包含合约代码,以及代码哈希
func (self *ContractAccount) GetDataKV() (kvSet []*types.KeyValue) { func (ca *ContractAccount) GetDataKV() (kvSet []*types.KeyValue) {
self.Data.Addr = self.Addr ca.Data.Addr = ca.Addr
datas, err := proto.Marshal(&self.Data) datas, err := proto.Marshal(&ca.Data)
if err != nil { if err != nil {
log15.Error("marshal contract data error!", "addr", self.Addr, "error", err) log15.Error("marshal contract data error!", "addr", ca.Addr, "error", err)
return return
} }
kvSet = append(kvSet, &types.KeyValue{Key: self.GetDataKey(), Value: datas}) kvSet = append(kvSet, &types.KeyValue{Key: ca.GetDataKey(), Value: datas})
return return
} }
// 获取合约状态数据,包含nonce、是否自杀、存储哈希、存储数据 // GetStateKV 获取合约状态数据,包含nonce、是否自杀、存储哈希、存储数据
func (self *ContractAccount) GetStateKV() (kvSet []*types.KeyValue) { func (ca *ContractAccount) GetStateKV() (kvSet []*types.KeyValue) {
datas, err := proto.Marshal(&self.State) datas, err := proto.Marshal(&ca.State)
if err != nil { if err != nil {
log15.Error("marshal contract state error!", "addr", self.Addr, "error", err) log15.Error("marshal contract state error!", "addr", ca.Addr, "error", err)
return return
} }
kvSet = append(kvSet, &types.KeyValue{Key: self.GetStateKey(), Value: datas}) kvSet = append(kvSet, &types.KeyValue{Key: ca.GetStateKey(), Value: datas})
return return
} }
// 构建变更日志 // BuildDataLog 构建变更日志
func (self *ContractAccount) BuildDataLog() (log *types.ReceiptLog) { func (ca *ContractAccount) BuildDataLog() (log *types.ReceiptLog) {
datas, err := proto.Marshal(&self.Data) datas, err := proto.Marshal(&ca.Data)
if err != nil { if err != nil {
log15.Error("marshal contract data error!", "addr", self.Addr, "error", err) log15.Error("marshal contract data error!", "addr", ca.Addr, "error", err)
return return
} }
return &types.ReceiptLog{evmtypes.TyLogContractData, datas} return &types.ReceiptLog{Ty: evmtypes.TyLogContractData, Log: datas}
} }
// 构建变更日志 // BuildStateLog 构建变更日志
func (self *ContractAccount) BuildStateLog() (log *types.ReceiptLog) { func (ca *ContractAccount) BuildStateLog() (log *types.ReceiptLog) {
datas, err := proto.Marshal(&self.State) datas, err := proto.Marshal(&ca.State)
if err != nil { if err != nil {
log15.Error("marshal contract state log error!", "addr", self.Addr, "error", err) log15.Error("marshal contract state log error!", "addr", ca.Addr, "error", err)
return return
} }
return &types.ReceiptLog{evmtypes.TyLogContractState, datas} return &types.ReceiptLog{Ty: evmtypes.TyLogContractState, Log: datas}
} }
func (self *ContractAccount) GetDataKey() []byte { // GetDataKey 获取数据KEY
return []byte("mavl-" + evmtypes.ExecutorName + "-data: " + self.Addr) func (ca *ContractAccount) GetDataKey() []byte {
return []byte("mavl-" + evmtypes.ExecutorName + "-data: " + ca.Addr)
} }
func (self *ContractAccount) GetStateKey() []byte { // GetStateKey 获取状态key
return []byte("mavl-" + evmtypes.ExecutorName + "-state: " + self.Addr) func (ca *ContractAccount) GetStateKey() []byte {
return []byte("mavl-" + evmtypes.ExecutorName + "-state: " + ca.Addr)
} }
// 这份数据是存在LocalDB中的 // 这份数据是存在LocalDB中的
...@@ -275,28 +282,33 @@ func getStateItemKey(addr, key string) string { ...@@ -275,28 +282,33 @@ func getStateItemKey(addr, key string) string {
return fmt.Sprintf("LODB-"+evmtypes.ExecutorName+"-state:%v:%v", addr, key) return fmt.Sprintf("LODB-"+evmtypes.ExecutorName+"-state:%v:%v", addr, key)
} }
func (self *ContractAccount) Suicide() bool { // Suicide 自杀
self.State.Suicided = true func (ca *ContractAccount) Suicide() bool {
ca.State.Suicided = true
return true return true
} }
func (self *ContractAccount) HasSuicided() bool { // HasSuicided 是否已经自杀
return self.State.GetSuicided() func (ca *ContractAccount) HasSuicided() bool {
return ca.State.GetSuicided()
} }
func (self *ContractAccount) Empty() bool { // Empty 是否为空对象
return self.Data.GetCodeHash() == nil || len(self.Data.GetCodeHash()) == 0 func (ca *ContractAccount) Empty() bool {
return ca.Data.GetCodeHash() == nil || len(ca.Data.GetCodeHash()) == 0
} }
func (self *ContractAccount) SetNonce(nonce uint64) { // SetNonce 设置nonce值
self.mdb.addChange(nonceChange{ func (ca *ContractAccount) SetNonce(nonce uint64) {
ca.mdb.addChange(nonceChange{
baseChange: baseChange{}, baseChange: baseChange{},
account: self.Addr, account: ca.Addr,
prev: self.State.GetNonce(), prev: ca.State.GetNonce(),
}) })
self.State.Nonce = nonce ca.State.Nonce = nonce
} }
func (self *ContractAccount) GetNonce() uint64 { // GetNonce 获取nonce值
return self.State.GetNonce() func (ca *ContractAccount) GetNonce() uint64 {
return ca.State.GetNonce()
} }
...@@ -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
} }
......
...@@ -16,20 +16,20 @@ import ( ...@@ -16,20 +16,20 @@ import (
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/model" "github.com/33cn/plugin/plugin/dapp/evm/executor/vm/model"
) )
// 内存状态数据库,保存在区块操作时内部的数据变更操作 // MemoryStateDB 内存状态数据库,保存在区块操作时内部的数据变更操作
// 本数据库不会直接写文件,只会暂存变更记录 // 本数据库不会直接写文件,只会暂存变更记录
// 在区块打包完成后,这里的缓存变更数据会被清空(通过区块打包分别写入blockchain和statedb数据库) // 在区块打包完成后,这里的缓存变更数据会被清空(通过区块打包分别写入blockchain和statedb数据库)
// 在交易执行过程中,本数据库会暂存并变更,在交易执行结束后,会返回变更的数据集,返回给blockchain // 在交易执行过程中,本数据库会暂存并变更,在交易执行结束后,会返回变更的数据集,返回给blockchain
// 执行器的Exec阶段会返回:交易收据、合约账户(包含合约地址、合约代码、合约存储信息) // 执行器的Exec阶段会返回:交易收据、合约账户(包含合约地址、合约代码、合约存储信息)
// 执行器的ExecLocal阶段会返回:合约创建人和合约的关联信息 // 执行器的ExecLocal阶段会返回:合约创建人和合约的关联信息
type MemoryStateDB struct { type MemoryStateDB struct {
// 状态DB,从执行器框架传入 // StateDB 状态DB,从执行器框架传入
StateDB db.KV StateDB db.KV
// 本地DB,从执行器框架传入 // LocalDB 本地DB,从执行器框架传入
LocalDB db.KVDB LocalDB db.KVDB
// Coins账户操作对象,从执行器框架传入 // CoinsAccount Coins账户操作对象,从执行器框架传入
CoinsAccount *account.DB CoinsAccount *account.DB
// 缓存账户对象 // 缓存账户对象
...@@ -45,7 +45,7 @@ type MemoryStateDB struct { ...@@ -45,7 +45,7 @@ type MemoryStateDB struct {
// 版本号,用于标识数据变更版本 // 版本号,用于标识数据变更版本
snapshots []*Snapshot snapshots []*Snapshot
currentVer *Snapshot currentVer *Snapshot
versionId int versionID int
// 存储sha3指令对应的数据,仅用于debug日志 // 存储sha3指令对应的数据,仅用于debug日志
preimages map[common.Hash][]byte preimages map[common.Hash][]byte
...@@ -62,7 +62,7 @@ type MemoryStateDB struct { ...@@ -62,7 +62,7 @@ type MemoryStateDB struct {
dataDirty map[string]interface{} dataDirty map[string]interface{}
} }
// 基于执行器框架的三个DB构建内存状态机对象 // NewMemoryStateDB 基于执行器框架的三个DB构建内存状态机对象
// 此对象的生命周期对应一个区块,在同一个区块内的多个交易执行时共享同一个DB对象 // 此对象的生命周期对应一个区块,在同一个区块内的多个交易执行时共享同一个DB对象
// 开始执行下一个区块时(执行器框架调用setEnv设置的区块高度发生变更时),会重新创建此DB对象 // 开始执行下一个区块时(执行器框架调用setEnv设置的区块高度发生变更时),会重新创建此DB对象
func NewMemoryStateDB(StateDB db.KV, LocalDB db.KVDB, CoinsAccount *account.DB, blockHeight int64) *MemoryStateDB { func NewMemoryStateDB(StateDB db.KV, LocalDB db.KVDB, CoinsAccount *account.DB, blockHeight int64) *MemoryStateDB {
...@@ -82,55 +82,55 @@ func NewMemoryStateDB(StateDB db.KV, LocalDB db.KVDB, CoinsAccount *account.DB, ...@@ -82,55 +82,55 @@ func NewMemoryStateDB(StateDB db.KV, LocalDB db.KVDB, CoinsAccount *account.DB,
return mdb return mdb
} }
// 每一个交易执行之前调用此方法,设置此交易的上下文信息 // Prepare 每一个交易执行之前调用此方法,设置此交易的上下文信息
// 目前的上下文中包含交易哈希以及交易在区块中的序号 // 目前的上下文中包含交易哈希以及交易在区块中的序号
func (self *MemoryStateDB) Prepare(txHash common.Hash, txIndex int) { func (mdb *MemoryStateDB) Prepare(txHash common.Hash, txIndex int) {
self.txHash = txHash mdb.txHash = txHash
self.txIndex = txIndex mdb.txIndex = txIndex
} }
// 创建一个新的合约账户对象 // CreateAccount 创建一个新的合约账户对象
func (self *MemoryStateDB) CreateAccount(addr, creator string, execName, alias string) { func (mdb *MemoryStateDB) CreateAccount(addr, creator string, execName, alias string) {
acc := self.GetAccount(addr) acc := mdb.GetAccount(addr)
if acc == nil { if acc == nil {
// 这种情况下为新增合约账户 // 这种情况下为新增合约账户
acc := NewContractAccount(addr, self) acc := NewContractAccount(addr, mdb)
acc.SetCreator(creator) acc.SetCreator(creator)
acc.SetExecName(execName) acc.SetExecName(execName)
acc.SetAliasName(alias) acc.SetAliasName(alias)
self.accounts[addr] = acc mdb.accounts[addr] = acc
self.addChange(createAccountChange{baseChange: baseChange{}, account: addr}) mdb.addChange(createAccountChange{baseChange: baseChange{}, account: addr})
} }
} }
func (self *MemoryStateDB) addChange(entry DataChange) { func (mdb *MemoryStateDB) addChange(entry DataChange) {
if self.currentVer != nil { if mdb.currentVer != nil {
self.currentVer.append(entry) mdb.currentVer.append(entry)
} }
} }
// 从外部账户地址扣钱(钱其实是打到合约账户中的) // SubBalance 从外部账户地址扣钱(钱其实是打到合约账户中的)
func (self *MemoryStateDB) SubBalance(addr, caddr string, value uint64) { func (mdb *MemoryStateDB) SubBalance(addr, caddr string, value uint64) {
res := self.Transfer(addr, caddr, value) res := mdb.Transfer(addr, caddr, value)
log15.Debug("transfer result", "from", addr, "to", caddr, "amount", value, "result", res) log15.Debug("transfer result", "from", addr, "to", caddr, "amount", value, "result", res)
} }
// 向外部账户地址打钱(钱其实是外部账户之前打到合约账户中的) // AddBalance 向外部账户地址打钱(钱其实是外部账户之前打到合约账户中的)
func (self *MemoryStateDB) AddBalance(addr, caddr string, value uint64) { func (mdb *MemoryStateDB) AddBalance(addr, caddr string, value uint64) {
res := self.Transfer(caddr, addr, value) res := mdb.Transfer(caddr, addr, value)
log15.Debug("transfer result", "from", addr, "to", caddr, "amount", value, "result", res) log15.Debug("transfer result", "from", addr, "to", caddr, "amount", value, "result", res)
} }
// 这里需要区分对待,如果是合约账户,则查看合约账户所有者地址在此合约下的余额; // GetBalance 这里需要区分对待,如果是合约账户,则查看合约账户所有者地址在此合约下的余额;
// 如果是外部账户,则直接返回外部账户的余额 // 如果是外部账户,则直接返回外部账户的余额
func (self *MemoryStateDB) GetBalance(addr string) uint64 { func (mdb *MemoryStateDB) GetBalance(addr string) uint64 {
if self.CoinsAccount == nil { if mdb.CoinsAccount == nil {
return 0 return 0
} }
isExec := self.Exist(addr) isExec := mdb.Exist(addr)
var ac *types.Account var ac *types.Account
if isExec { if isExec {
contract := self.GetAccount(addr) contract := mdb.GetAccount(addr)
if contract == nil { if contract == nil {
return 0 return 0
} }
...@@ -138,9 +138,9 @@ func (self *MemoryStateDB) GetBalance(addr string) uint64 { ...@@ -138,9 +138,9 @@ func (self *MemoryStateDB) GetBalance(addr string) uint64 {
if len(creator) == 0 { if len(creator) == 0 {
return 0 return 0
} }
ac = self.CoinsAccount.LoadExecAccount(creator, addr) ac = mdb.CoinsAccount.LoadExecAccount(creator, addr)
} else { } else {
ac = self.CoinsAccount.LoadAccount(addr) ac = mdb.CoinsAccount.LoadAccount(addr)
} }
if ac != nil { if ac != nil {
return uint64(ac.Balance) return uint64(ac.Balance)
...@@ -148,152 +148,156 @@ func (self *MemoryStateDB) GetBalance(addr string) uint64 { ...@@ -148,152 +148,156 @@ func (self *MemoryStateDB) GetBalance(addr string) uint64 {
return 0 return 0
} }
// 目前chain33中没有保留账户的nonce信息,这里临时添加到合约账户中; // GetNonce 目前chain33中没有保留账户的nonce信息,这里临时添加到合约账户中;
// 所以,目前只有合约对象有nonce值 // 所以,目前只有合约对象有nonce值
func (self *MemoryStateDB) GetNonce(addr string) uint64 { func (mdb *MemoryStateDB) GetNonce(addr string) uint64 {
acc := self.GetAccount(addr) acc := mdb.GetAccount(addr)
if acc != nil { if acc != nil {
return acc.GetNonce() return acc.GetNonce()
} }
return 0 return 0
} }
func (self *MemoryStateDB) SetNonce(addr string, nonce uint64) { // SetNonce 设置nonce值
acc := self.GetAccount(addr) func (mdb *MemoryStateDB) SetNonce(addr string, nonce uint64) {
acc := mdb.GetAccount(addr)
if acc != nil { if acc != nil {
acc.SetNonce(nonce) acc.SetNonce(nonce)
} }
} }
func (self *MemoryStateDB) GetCodeHash(addr string) common.Hash { // GetCodeHash 获取代码哈希
acc := self.GetAccount(addr) func (mdb *MemoryStateDB) GetCodeHash(addr string) common.Hash {
acc := mdb.GetAccount(addr)
if acc != nil { if acc != nil {
return common.BytesToHash(acc.Data.GetCodeHash()) return common.BytesToHash(acc.Data.GetCodeHash())
} }
return common.Hash{} return common.Hash{}
} }
func (self *MemoryStateDB) GetCode(addr string) []byte { // GetCode 获取代码内容
acc := self.GetAccount(addr) func (mdb *MemoryStateDB) GetCode(addr string) []byte {
acc := mdb.GetAccount(addr)
if acc != nil { if acc != nil {
return acc.Data.GetCode() return acc.Data.GetCode()
} }
return nil return nil
} }
func (self *MemoryStateDB) SetCode(addr string, code []byte) { // SetCode 设置代码内容
acc := self.GetAccount(addr) func (mdb *MemoryStateDB) SetCode(addr string, code []byte) {
acc := mdb.GetAccount(addr)
if acc != nil { if acc != nil {
self.dataDirty[addr] = true mdb.dataDirty[addr] = true
acc.SetCode(code) acc.SetCode(code)
} }
} }
// 获取合约代码自身的大小 // GetCodeSize 获取合约代码自身的大小
// 对应 EXTCODESIZE 操作码 // 对应 EXTCODESIZE 操作码
func (self *MemoryStateDB) GetCodeSize(addr string) int { func (mdb *MemoryStateDB) GetCodeSize(addr string) int {
code := self.GetCode(addr) code := mdb.GetCode(addr)
if code != nil { if code != nil {
return len(code) return len(code)
} }
return 0 return 0
} }
// 合约自杀或SSTORE指令时,返还Gas // AddRefund 合约自杀或SSTORE指令时,返还Gas
func (self *MemoryStateDB) AddRefund(gas uint64) { func (mdb *MemoryStateDB) AddRefund(gas uint64) {
self.addChange(refundChange{baseChange: baseChange{}, prev: self.refund}) mdb.addChange(refundChange{baseChange: baseChange{}, prev: mdb.refund})
self.refund += gas mdb.refund += gas
} }
func (self *MemoryStateDB) GetRefund() uint64 { // GetRefund 获取奖励
return self.refund func (mdb *MemoryStateDB) GetRefund() uint64 {
return mdb.refund
} }
// 从缓存中获取或加载合约账户 // GetAccount 从缓存中获取或加载合约账户
func (self *MemoryStateDB) GetAccount(addr string) *ContractAccount { func (mdb *MemoryStateDB) GetAccount(addr string) *ContractAccount {
if acc, ok := self.accounts[addr]; ok { if acc, ok := mdb.accounts[addr]; ok {
return acc return acc
} else { }
// 需要加载合约对象,根据是否存在合约代码来判断是否有合约对象 // 需要加载合约对象,根据是否存在合约代码来判断是否有合约对象
contract := NewContractAccount(addr, self) contract := NewContractAccount(addr, mdb)
contract.LoadContract(self.StateDB) contract.LoadContract(mdb.StateDB)
if contract.Empty() { if contract.Empty() {
return nil return nil
} }
self.accounts[addr] = contract mdb.accounts[addr] = contract
return contract return contract
}
} }
// SLOAD 指令加载合约状态数据 // GetState SLOAD 指令加载合约状态数据
func (self *MemoryStateDB) GetState(addr string, key common.Hash) common.Hash { func (mdb *MemoryStateDB) GetState(addr string, key common.Hash) common.Hash {
// 先从合约缓存中获取 // 先从合约缓存中获取
acc := self.GetAccount(addr) acc := mdb.GetAccount(addr)
if acc != nil { if acc != nil {
return acc.GetState(key) return acc.GetState(key)
} }
return common.Hash{} return common.Hash{}
} }
// SSTORE 指令修改合约状态数据 // SetState SSTORE 指令修改合约状态数据
func (self *MemoryStateDB) SetState(addr string, key common.Hash, value common.Hash) { func (mdb *MemoryStateDB) SetState(addr string, key common.Hash, value common.Hash) {
acc := self.GetAccount(addr) acc := mdb.GetAccount(addr)
if acc != nil { if acc != nil {
acc.SetState(key, value) acc.SetState(key, value)
// 新的分叉中状态数据变更不需要单独进行标识 // 新的分叉中状态数据变更不需要单独进行标识
if !types.IsDappFork(self.blockHeight, "evm", "ForkEVMState") { if !types.IsDappFork(mdb.blockHeight, "evm", "ForkEVMState") {
self.stateDirty[addr] = true mdb.stateDirty[addr] = true
} }
} }
} }
// 转换合约状态数据存储 // TransferStateData 转换合约状态数据存储
func (self *MemoryStateDB) TransferStateData(addr string) { func (mdb *MemoryStateDB) TransferStateData(addr string) {
acc := self.GetAccount(addr) acc := mdb.GetAccount(addr)
if acc != nil { if acc != nil {
acc.TransferState() acc.TransferState()
} }
} }
// 表示合约地址的状态数据发生了变更,需要进行更新 // UpdateState 表示合约地址的状态数据发生了变更,需要进行更新
func (self *MemoryStateDB) UpdateState(addr string) { func (mdb *MemoryStateDB) UpdateState(addr string) {
self.stateDirty[addr] = true mdb.stateDirty[addr] = true
} }
// SELFDESTRUCT 合约对象自杀 // Suicide SELFDESTRUCT 合约对象自杀
// 合约自杀后,合约对象依然存在,只是无法被调用,也无法恢复 // 合约自杀后,合约对象依然存在,只是无法被调用,也无法恢复
func (self *MemoryStateDB) Suicide(addr string) bool { func (mdb *MemoryStateDB) Suicide(addr string) bool {
acc := self.GetAccount(addr) acc := mdb.GetAccount(addr)
if acc != nil { if acc != nil {
self.addChange(suicideChange{ mdb.addChange(suicideChange{
baseChange: baseChange{}, baseChange: baseChange{},
account: addr, account: addr,
prev: acc.State.GetSuicided(), prev: acc.State.GetSuicided(),
}) })
self.stateDirty[addr] = true mdb.stateDirty[addr] = true
return acc.Suicide() return acc.Suicide()
} }
return false return false
} }
// 判断此合约对象是否已经自杀 // HasSuicided 判断此合约对象是否已经自杀
// 自杀的合约对象是不允许调用的 // 自杀的合约对象是不允许调用的
func (self *MemoryStateDB) HasSuicided(addr string) bool { func (mdb *MemoryStateDB) HasSuicided(addr string) bool {
acc := self.GetAccount(addr) acc := mdb.GetAccount(addr)
if acc != nil { if acc != nil {
return acc.HasSuicided() return acc.HasSuicided()
} }
return false return false
} }
// 判断合约对象是否存在 // Exist 判断合约对象是否存在
func (self *MemoryStateDB) Exist(addr string) bool { func (mdb *MemoryStateDB) Exist(addr string) bool {
return self.GetAccount(addr) != nil return mdb.GetAccount(addr) != nil
} }
// 判断合约对象是否为空 // Empty 判断合约对象是否为空
func (self *MemoryStateDB) Empty(addr string) bool { func (mdb *MemoryStateDB) Empty(addr string) bool {
acc := self.GetAccount(addr) acc := mdb.GetAccount(addr)
// 如果包含合约代码,则不为空 // 如果包含合约代码,则不为空
if acc != nil && !acc.Empty() { if acc != nil && !acc.Empty() {
...@@ -301,19 +305,19 @@ func (self *MemoryStateDB) Empty(addr string) bool { ...@@ -301,19 +305,19 @@ func (self *MemoryStateDB) Empty(addr string) bool {
} }
// 账户有余额,也不为空 // 账户有余额,也不为空
if self.GetBalance(addr) != 0 { if mdb.GetBalance(addr) != 0 {
return false return false
} }
return true return true
} }
// 将数据状态回滚到指定快照版本(中间的版本数据将会被删除) // RevertToSnapshot 将数据状态回滚到指定快照版本(中间的版本数据将会被删除)
func (self *MemoryStateDB) RevertToSnapshot(version int) { func (mdb *MemoryStateDB) RevertToSnapshot(version int) {
if version >= len(self.snapshots) { if version >= len(mdb.snapshots) {
return return
} }
ver := self.snapshots[version] ver := mdb.snapshots[version]
// 如果版本号不对,回滚失败 // 如果版本号不对,回滚失败
if ver == nil || ver.id != version { if ver == nil || ver.id != version {
...@@ -322,50 +326,50 @@ func (self *MemoryStateDB) RevertToSnapshot(version int) { ...@@ -322,50 +326,50 @@ func (self *MemoryStateDB) RevertToSnapshot(version int) {
} }
// 从最近版本开始回滚 // 从最近版本开始回滚
for index := len(self.snapshots) - 1; index >= version; index-- { for index := len(mdb.snapshots) - 1; index >= version; index-- {
self.snapshots[index].revert() mdb.snapshots[index].revert()
} }
// 只保留回滚版本之前的版本数据 // 只保留回滚版本之前的版本数据
self.snapshots = self.snapshots[:version] mdb.snapshots = mdb.snapshots[:version]
self.versionId = version mdb.versionID = version
if version == 0 { if version == 0 {
self.currentVer = nil mdb.currentVer = nil
} else { } else {
self.currentVer = self.snapshots[version-1] mdb.currentVer = mdb.snapshots[version-1]
} }
} }
// 对当前的数据状态打快照,并生成快照版本号,方便后面回滚数据 // Snapshot 对当前的数据状态打快照,并生成快照版本号,方便后面回滚数据
func (self *MemoryStateDB) Snapshot() int { func (mdb *MemoryStateDB) Snapshot() int {
id := self.versionId id := mdb.versionID
self.versionId++ mdb.versionID++
self.currentVer = &Snapshot{id: id, statedb: self} mdb.currentVer = &Snapshot{id: id, statedb: mdb}
self.snapshots = append(self.snapshots, self.currentVer) mdb.snapshots = append(mdb.snapshots, mdb.currentVer)
return id return id
} }
// 获取最后一次成功的快照版本号 // GetLastSnapshot 获取最后一次成功的快照版本号
func (self *MemoryStateDB) GetLastSnapshot() *Snapshot { func (mdb *MemoryStateDB) GetLastSnapshot() *Snapshot {
if self.versionId == 0 { if mdb.versionID == 0 {
return nil return nil
} }
return self.snapshots[self.versionId-1] return mdb.snapshots[mdb.versionID-1]
} }
// 获取合约对象的变更日志 // GetReceiptLogs 获取合约对象的变更日志
func (self *MemoryStateDB) GetReceiptLogs(addr string) (logs []*types.ReceiptLog) { func (mdb *MemoryStateDB) GetReceiptLogs(addr string) (logs []*types.ReceiptLog) {
acc := self.GetAccount(addr) acc := mdb.GetAccount(addr)
if acc != nil { if acc != nil {
if self.stateDirty[addr] != nil { if mdb.stateDirty[addr] != nil {
stateLog := acc.BuildStateLog() stateLog := acc.BuildStateLog()
if stateLog != nil { if stateLog != nil {
logs = append(logs, stateLog) logs = append(logs, stateLog)
} }
} }
if self.dataDirty[addr] != nil { if mdb.dataDirty[addr] != nil {
logs = append(logs, acc.BuildDataLog()) logs = append(logs, acc.BuildDataLog())
} }
return return
...@@ -373,16 +377,16 @@ func (self *MemoryStateDB) GetReceiptLogs(addr string) (logs []*types.ReceiptLog ...@@ -373,16 +377,16 @@ func (self *MemoryStateDB) GetReceiptLogs(addr string) (logs []*types.ReceiptLog
return return
} }
// 获取本次操作所引起的状态数据变更 // GetChangedData 获取本次操作所引起的状态数据变更
// 因为目前执行器每次执行都是一个新的MemoryStateDB,所以,所有的快照都是从0开始的, // 因为目前执行器每次执行都是一个新的MemoryStateDB,所以,所有的快照都是从0开始的,
// 这里获取的应该是从0到目前快照的所有变更; // 这里获取的应该是从0到目前快照的所有变更;
// 另外,因为合约内部会调用其它合约,也会产生数据变更,所以这里返回的数据,不止是一个合约的数据。 // 另外,因为合约内部会调用其它合约,也会产生数据变更,所以这里返回的数据,不止是一个合约的数据。
func (self *MemoryStateDB) GetChangedData(version int) (kvSet []*types.KeyValue, logs []*types.ReceiptLog) { func (mdb *MemoryStateDB) GetChangedData(version int) (kvSet []*types.KeyValue, logs []*types.ReceiptLog) {
if version < 0 { if version < 0 {
return return
} }
for _, snapshot := range self.snapshots { for _, snapshot := range mdb.snapshots {
kv, log := snapshot.getData() kv, log := snapshot.getData()
if kv != nil { if kv != nil {
kvSet = append(kvSet, kv...) kvSet = append(kvSet, kv...)
...@@ -395,12 +399,12 @@ func (self *MemoryStateDB) GetChangedData(version int) (kvSet []*types.KeyValue, ...@@ -395,12 +399,12 @@ func (self *MemoryStateDB) GetChangedData(version int) (kvSet []*types.KeyValue,
return return
} }
// 借助coins执行器进行转账相关操作 // CanTransfer 借助coins执行器进行转账相关操作
func (self *MemoryStateDB) CanTransfer(sender, recipient string, amount uint64) bool { func (mdb *MemoryStateDB) CanTransfer(sender, recipient string, amount uint64) bool {
log15.Debug("check CanTransfer", "sender", sender, "recipient", recipient, "amount", amount) log15.Debug("check CanTransfer", "sender", sender, "recipient", recipient, "amount", amount)
tType, errInfo := self.checkTransfer(sender, recipient, amount) tType, errInfo := mdb.checkTransfer(sender, recipient, amount)
if errInfo != nil { if errInfo != nil {
log15.Error("check transfer error", "sender", sender, "recipient", recipient, "amount", amount, "err info", errInfo) log15.Error("check transfer error", "sender", sender, "recipient", recipient, "amount", amount, "err info", errInfo)
...@@ -416,7 +420,7 @@ func (self *MemoryStateDB) CanTransfer(sender, recipient string, amount uint64) ...@@ -416,7 +420,7 @@ func (self *MemoryStateDB) CanTransfer(sender, recipient string, amount uint64)
case NoNeed: case NoNeed:
return true return true
case ToExec: case ToExec:
accFrom := self.CoinsAccount.LoadExecAccount(sender, recipient) accFrom := mdb.CoinsAccount.LoadExecAccount(sender, recipient)
b := accFrom.GetBalance() - value b := accFrom.GetBalance() - value
if b < 0 { if b < 0 {
log15.Error("check transfer error", "error info", types.ErrNoBalance) log15.Error("check transfer error", "error info", types.ErrNoBalance)
...@@ -424,13 +428,13 @@ func (self *MemoryStateDB) CanTransfer(sender, recipient string, amount uint64) ...@@ -424,13 +428,13 @@ func (self *MemoryStateDB) CanTransfer(sender, recipient string, amount uint64)
} }
return true return true
case FromExec: case FromExec:
return self.checkExecAccount(sender, value) return mdb.checkExecAccount(sender, value)
default: default:
return false return false
} }
} }
func (self *MemoryStateDB) checkExecAccount(addr string, value int64) bool { func (mdb *MemoryStateDB) checkExecAccount(addr string, value int64) bool {
var err error var err error
defer func() { defer func() {
if err != nil { if err != nil {
...@@ -442,7 +446,7 @@ func (self *MemoryStateDB) checkExecAccount(addr string, value int64) bool { ...@@ -442,7 +446,7 @@ func (self *MemoryStateDB) checkExecAccount(addr string, value int64) bool {
err = types.ErrAmount err = types.ErrAmount
return false return false
} }
contract := self.GetAccount(addr) contract := mdb.GetAccount(addr)
if contract == nil { if contract == nil {
err = model.ErrAddrNotExists err = model.ErrAddrNotExists
return false return false
...@@ -453,7 +457,7 @@ func (self *MemoryStateDB) checkExecAccount(addr string, value int64) bool { ...@@ -453,7 +457,7 @@ func (self *MemoryStateDB) checkExecAccount(addr string, value int64) bool {
return false return false
} }
accFrom := self.CoinsAccount.LoadExecAccount(contract.GetCreator(), addr) accFrom := mdb.CoinsAccount.LoadExecAccount(contract.GetCreator(), addr)
b := accFrom.GetBalance() - value b := accFrom.GetBalance() - value
if b < 0 { if b < 0 {
err = types.ErrNoBalance err = types.ErrNoBalance
...@@ -462,28 +466,33 @@ func (self *MemoryStateDB) checkExecAccount(addr string, value int64) bool { ...@@ -462,28 +466,33 @@ func (self *MemoryStateDB) checkExecAccount(addr string, value int64) bool {
return true return true
} }
// TransferType 定义转账类型
type TransferType int type TransferType int
const ( const (
_ TransferType = iota _ TransferType = iota
// NoNeed 无需转账
NoNeed NoNeed
// ToExec 向合约转账
ToExec ToExec
// FromExec 从合约转入
FromExec FromExec
// Error 处理出错
Error Error
) )
func (self *MemoryStateDB) checkTransfer(sender, recipient string, amount uint64) (tType TransferType, err error) { func (mdb *MemoryStateDB) checkTransfer(sender, recipient string, amount uint64) (tType TransferType, err error) {
if amount == 0 { if amount == 0 {
return NoNeed, nil return NoNeed, nil
} }
if self.CoinsAccount == nil { if mdb.CoinsAccount == nil {
log15.Error("no coinsaccount exists", "sender", sender, "recipient", recipient, "amount", amount) log15.Error("no coinsaccount exists", "sender", sender, "recipient", recipient, "amount", amount)
return Error, model.NoCoinsAccount return Error, model.ErrNoCoinsAccount
} }
// 首先需要检查转账双方的信息,是属于合约账户还是外部账户 // 首先需要检查转账双方的信息,是属于合约账户还是外部账户
execSender := self.Exist(sender) execSender := mdb.Exist(sender)
execRecipient := self.Exist(recipient) execRecipient := mdb.Exist(recipient)
if execRecipient && execSender { if execRecipient && execSender {
// 双方均为合约账户,不支持 // 双方均为合约账户,不支持
...@@ -506,12 +515,12 @@ func (self *MemoryStateDB) checkTransfer(sender, recipient string, amount uint64 ...@@ -506,12 +515,12 @@ func (self *MemoryStateDB) checkTransfer(sender, recipient string, amount uint64
return tType, err return tType, err
} }
// 借助coins执行器进行转账相关操作 // Transfer 借助coins执行器进行转账相关操作
// 只支持 合约账户到合约账户,其它情况不支持 // 只支持 合约账户到合约账户,其它情况不支持
func (self *MemoryStateDB) Transfer(sender, recipient string, amount uint64) bool { func (mdb *MemoryStateDB) Transfer(sender, recipient string, amount uint64) bool {
log15.Debug("transfer from contract to external(contract)", "sender", sender, "recipient", recipient, "amount", amount) log15.Debug("transfer from contract to external(contract)", "sender", sender, "recipient", recipient, "amount", amount)
tType, errInfo := self.checkTransfer(sender, recipient, amount) tType, errInfo := mdb.checkTransfer(sender, recipient, amount)
if errInfo != nil { if errInfo != nil {
log15.Error("transfer error", "sender", sender, "recipient", recipient, "amount", amount, "err info", errInfo) log15.Error("transfer error", "sender", sender, "recipient", recipient, "amount", amount, "err info", errInfo)
...@@ -532,9 +541,9 @@ func (self *MemoryStateDB) Transfer(sender, recipient string, amount uint64) boo ...@@ -532,9 +541,9 @@ func (self *MemoryStateDB) Transfer(sender, recipient string, amount uint64) boo
case NoNeed: case NoNeed:
return true return true
case ToExec: case ToExec:
ret, err = self.transfer2Contract(sender, recipient, value) ret, err = mdb.transfer2Contract(sender, recipient, value)
case FromExec: case FromExec:
ret, err = self.transfer2External(sender, recipient, value) ret, err = mdb.transfer2External(sender, recipient, value)
default: default:
return false return false
} }
...@@ -543,9 +552,9 @@ func (self *MemoryStateDB) Transfer(sender, recipient string, amount uint64) boo ...@@ -543,9 +552,9 @@ func (self *MemoryStateDB) Transfer(sender, recipient string, amount uint64) boo
if err != nil { if err != nil {
log15.Error("transfer error", "sender", sender, "recipient", recipient, "amount", amount, "err info", err) log15.Error("transfer error", "sender", sender, "recipient", recipient, "amount", amount, "err info", err)
return false return false
} else { }
if ret != nil { if ret != nil {
self.addChange(transferChange{ mdb.addChange(transferChange{
baseChange: baseChange{}, baseChange: baseChange{},
amount: value, amount: value,
data: ret.KV, data: ret.KV,
...@@ -553,7 +562,6 @@ func (self *MemoryStateDB) Transfer(sender, recipient string, amount uint64) boo ...@@ -553,7 +562,6 @@ func (self *MemoryStateDB) Transfer(sender, recipient string, amount uint64) boo
}) })
} }
return true return true
}
} }
// 因为chain33的限制,在执行器中转账只能在以下几个方向进行: // 因为chain33的限制,在执行器中转账只能在以下几个方向进行:
...@@ -561,9 +569,9 @@ func (self *MemoryStateDB) Transfer(sender, recipient string, amount uint64) boo ...@@ -561,9 +569,9 @@ func (self *MemoryStateDB) Transfer(sender, recipient string, amount uint64) boo
// 其它情况不支持,所以要想实现EVM合约与账户之间的转账需要经过中转处理,比如A要向B创建的X合约转账,则执行以下流程: // 其它情况不支持,所以要想实现EVM合约与账户之间的转账需要经过中转处理,比如A要向B创建的X合约转账,则执行以下流程:
// A -> A:X -> B:X; (其中第一步需要外部手工执行) // A -> A:X -> B:X; (其中第一步需要外部手工执行)
// 本方法封装第二步转账逻辑; // 本方法封装第二步转账逻辑;
func (self *MemoryStateDB) transfer2Contract(sender, recipient string, amount int64) (ret *types.Receipt, err error) { func (mdb *MemoryStateDB) transfer2Contract(sender, recipient string, amount int64) (ret *types.Receipt, err error) {
// 首先获取合约的创建者信息 // 首先获取合约的创建者信息
contract := self.GetAccount(recipient) contract := mdb.GetAccount(recipient)
if contract == nil { if contract == nil {
return nil, model.ErrAddrNotExists return nil, model.ErrAddrNotExists
} }
...@@ -577,7 +585,7 @@ func (self *MemoryStateDB) transfer2Contract(sender, recipient string, amount in ...@@ -577,7 +585,7 @@ func (self *MemoryStateDB) transfer2Contract(sender, recipient string, amount in
// 有可能是外部账户调用自己创建的合约,这种情况下这一步可以省略 // 有可能是外部账户调用自己创建的合约,这种情况下这一步可以省略
ret = &types.Receipt{} ret = &types.Receipt{}
if strings.Compare(sender, creator) != 0 { if strings.Compare(sender, creator) != 0 {
rs, err := self.CoinsAccount.ExecTransfer(sender, creator, execAddr, amount) rs, err := mdb.CoinsAccount.ExecTransfer(sender, creator, execAddr, amount)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -591,9 +599,9 @@ func (self *MemoryStateDB) transfer2Contract(sender, recipient string, amount in ...@@ -591,9 +599,9 @@ func (self *MemoryStateDB) transfer2Contract(sender, recipient string, amount in
// chain33转账限制请参考方法 Transfer2Contract ; // chain33转账限制请参考方法 Transfer2Contract ;
// 本方法封装从合约账户到外部账户的转账逻辑; // 本方法封装从合约账户到外部账户的转账逻辑;
func (self *MemoryStateDB) transfer2External(sender, recipient string, amount int64) (ret *types.Receipt, err error) { func (mdb *MemoryStateDB) transfer2External(sender, recipient string, amount int64) (ret *types.Receipt, err error) {
// 首先获取合约的创建者信息 // 首先获取合约的创建者信息
contract := self.GetAccount(sender) contract := mdb.GetAccount(sender)
if contract == nil { if contract == nil {
return nil, model.ErrAddrNotExists return nil, model.ErrAddrNotExists
} }
...@@ -607,7 +615,7 @@ func (self *MemoryStateDB) transfer2External(sender, recipient string, amount in ...@@ -607,7 +615,7 @@ func (self *MemoryStateDB) transfer2External(sender, recipient string, amount in
// 第一步先从创建者的合约账户到接受者的合约账户 // 第一步先从创建者的合约账户到接受者的合约账户
// 如果是自己调用自己创建的合约,这一步也可以省略 // 如果是自己调用自己创建的合约,这一步也可以省略
if strings.Compare(creator, recipient) != 0 { if strings.Compare(creator, recipient) != 0 {
ret, err = self.CoinsAccount.ExecTransfer(creator, recipient, execAddr, amount) ret, err = mdb.CoinsAccount.ExecTransfer(creator, recipient, execAddr, amount)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -615,17 +623,17 @@ func (self *MemoryStateDB) transfer2External(sender, recipient string, amount in ...@@ -615,17 +623,17 @@ func (self *MemoryStateDB) transfer2External(sender, recipient string, amount in
// 第二步再从接收者的合约账户取款到接受者账户 // 第二步再从接收者的合约账户取款到接受者账户
// 本操作不允许,需要外部操作coins账户 // 本操作不允许,需要外部操作coins账户
//rs, err := self.CoinsAccount.TransferWithdraw(recipient.String(), sender.String(), amount) //rs, err := mdb.CoinsAccount.TransferWithdraw(recipient.String(), sender.String(), amount)
//if err != nil { //if err != nil {
// return nil, err // return nil, err
//} //}
// //
//ret = self.mergeResult(ret, rs) //ret = mdb.mergeResult(ret, rs)
return ret, nil return ret, nil
} }
func (self *MemoryStateDB) mergeResult(one, two *types.Receipt) (ret *types.Receipt) { func (mdb *MemoryStateDB) mergeResult(one, two *types.Receipt) (ret *types.Receipt) {
ret = one ret = one
if ret == nil { if ret == nil {
ret = two ret = two
...@@ -636,45 +644,45 @@ func (self *MemoryStateDB) mergeResult(one, two *types.Receipt) (ret *types.Rece ...@@ -636,45 +644,45 @@ func (self *MemoryStateDB) mergeResult(one, two *types.Receipt) (ret *types.Rece
return return
} }
// LOG0-4 指令对应的具体操作 // AddLog LOG0-4 指令对应的具体操作
// 生成对应的日志信息,目前这些生成的日志信息会在合约执行后打印到日志文件中 // 生成对应的日志信息,目前这些生成的日志信息会在合约执行后打印到日志文件中
func (self *MemoryStateDB) AddLog(log *model.ContractLog) { func (mdb *MemoryStateDB) AddLog(log *model.ContractLog) {
self.addChange(addLogChange{txhash: self.txHash}) mdb.addChange(addLogChange{txhash: mdb.txHash})
log.TxHash = self.txHash log.TxHash = mdb.txHash
log.Index = int(self.logSize) log.Index = int(mdb.logSize)
self.logs[self.txHash] = append(self.logs[self.txHash], log) mdb.logs[mdb.txHash] = append(mdb.logs[mdb.txHash], log)
self.logSize++ mdb.logSize++
} }
// 存储sha3指令对应的数据 // AddPreimage 存储sha3指令对应的数据
func (self *MemoryStateDB) AddPreimage(hash common.Hash, data []byte) { func (mdb *MemoryStateDB) AddPreimage(hash common.Hash, data []byte) {
// 目前只用于打印日志 // 目前只用于打印日志
if _, ok := self.preimages[hash]; !ok { if _, ok := mdb.preimages[hash]; !ok {
self.addChange(addPreimageChange{hash: hash}) mdb.addChange(addPreimageChange{hash: hash})
pi := make([]byte, len(data)) pi := make([]byte, len(data))
copy(pi, data) copy(pi, data)
self.preimages[hash] = pi mdb.preimages[hash] = pi
} }
} }
// 本合约执行完毕之后打印合约生成的日志(如果有) // PrintLogs 本合约执行完毕之后打印合约生成的日志(如果有)
// 这里不保证当前区块可以打包成功,只是在执行区块中的交易时,如果交易执行成功,就会打印合约日志 // 这里不保证当前区块可以打包成功,只是在执行区块中的交易时,如果交易执行成功,就会打印合约日志
func (self *MemoryStateDB) PrintLogs() { func (mdb *MemoryStateDB) PrintLogs() {
items := self.logs[self.txHash] items := mdb.logs[mdb.txHash]
for _, item := range items { for _, item := range items {
item.PrintLog() item.PrintLog()
} }
} }
// 打印本区块内生成的preimages日志 // WritePreimages 打印本区块内生成的preimages日志
func (self *MemoryStateDB) WritePreimages(number int64) { func (mdb *MemoryStateDB) WritePreimages(number int64) {
for k, v := range self.preimages { for k, v := range mdb.preimages {
log15.Debug("Contract preimages ", "key:", k.Str(), "value:", common.Bytes2Hex(v), "block height:", number) log15.Debug("Contract preimages ", "key:", k.Str(), "value:", common.Bytes2Hex(v), "block height:", number)
} }
} }
// 测试用,清空版本数据 // ResetDatas 测试用,清空版本数据
func (self *MemoryStateDB) ResetDatas() { func (mdb *MemoryStateDB) ResetDatas() {
self.currentVer = nil mdb.currentVer = nil
self.snapshots = self.snapshots[:0] mdb.snapshots = mdb.snapshots[:0]
} }
...@@ -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 金额
Amount uint64 `json:"amount"` Amount uint64 `json:"amount"`
// Code 合约代码
Code string `json:"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 备注
Note string `json:"note"` Note string `json:"note"`
// Alias 合约别名
Alias string `json:"alias"` Alias string `json:"alias"`
// Fee 交易手续费
Fee int64 `json:"fee"` Fee int64 `json:"fee"`
// Name 交易名称
Name string `json:"name"` Name string `json:"name"`
// IsCreate 是否创建合约
IsCreate bool `json:"isCreate"` IsCreate bool `json:"isCreate"`
} }
...@@ -11,40 +11,39 @@ import ( ...@@ -11,40 +11,39 @@ import (
) )
const ( const (
// EvmCreateAction 创建合约
EvmCreateAction = 1 EvmCreateAction = 1
// EvmCallAction 调用合约
EvmCallAction = 2 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 EVM执行器名称
ExecerEvm = []byte(ExecutorName) 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,
......
...@@ -20,64 +20,65 @@ import ( ...@@ -20,64 +20,65 @@ import (
) )
const ( const (
//剪刀
// Scissor 剪刀
Scissor = int32(1) Scissor = int32(1)
//石头
// Rock 石头
Rock = int32(2) Rock = int32(2)
//布 // Paper
Paper = int32(3) Paper = int32(3)
//未知结果
// Unknown 未知结果
Unknown = int32(4) Unknown = int32(4)
//游戏结果 // IsDraw 平局
//平局
IsDraw = int32(1) IsDraw = int32(1)
// IsCreatorWin creator win
IsCreatorWin = int32(2) IsCreatorWin = int32(2)
// IsMatcherWin matcher win
IsMatcherWin = int32(3) IsMatcherWin = int32(3)
//开奖超时
// IsTimeOut 开奖超时
IsTimeOut = int32(4) IsTimeOut = int32(4)
// ListDESC desc query
ListDESC = int32(0) ListDESC = int32(0)
// ListASC asc query
ListASC = int32(1) ListASC = int32(1)
GameCount = "GameCount" //根据状态,地址统计整个合约目前总共成功执行了多少场游戏。 // GameCount 根据状态,地址统计整个合约目前总共成功执行了多少场游戏
GameCount = "GameCount"
// MaxGameAmount max game amount.单位为types.Coin 1e8
MaxGameAmount = int64(100)
MaxGameAmount = int64(100) //单位为types.Coin 1e8 // MinGameAmount min game amount
MinGameAmount = int64(2) MinGameAmount = int64(2)
DefaultCount = int64(20) //默认一次取多少条记录
MaxCount = int64(100) //最多取100条 // DefaultCount 默认一次取多少条记录
//从有matcher参与游戏开始计算本局游戏开奖的有效时间,单位为天 DefaultCount = int64(20)
// MaxCount 最多取100条
MaxCount = int64(100)
//ActiveTime 从有matcher参与游戏开始计算本局游戏开奖的有效时间,单位为天
ActiveTime = int64(24) ActiveTime = int64(24)
) )
// name configured in manager
var ( var (
ConfName_ActiveTime = gt.GameX + ":" + "activeTime" ConfNameActiveTime = gt.GameX + ":" + "activeTime"
ConfName_DefaultCount = gt.GameX + ":" + "defaultCount" ConfNameDefaultCount = gt.GameX + ":" + "defaultCount"
ConfName_MaxCount = gt.GameX + ":" + "maxCount" ConfNameMaxCount = gt.GameX + ":" + "maxCount"
ConfName_MaxGameAmount = gt.GameX + ":" + "maxGameAmount" ConfNameMaxGameAmount = gt.GameX + ":" + "maxGameAmount"
ConfName_MinGameAmount = gt.GameX + ":" + "minGameAmount" ConfNameMinGameAmount = gt.GameX + ":" + "minGameAmount"
) )
//game 的状态变化: // GetReceiptLog get receipt log
// staus == 1 (创建,开始猜拳游戏)
// status == 2 (匹配,参与)
// status == 3 (取消)
// status == 4 (Close的情况)
/*
在石头剪刀布游戏中,一局游戏的生命周期只有四种状态,其中创建者参与了整个的生命周期,因此当一局游戏 发生状态变更时,
都需要及时建立相应的索引与之关联,同时还要删除老状态时的索引,以免形成脏数据。
分页查询接口的实现:
1.索引建立规则;
根据状态索引建立: key= status:HeightIndex
状态地址索引建立:key= status:addr:HeightIndex
value=gameId
HeightIndex=fmt.Sprintf("%018d", d.GetHeight()*types.MaxTxsPerBlock+int64(d.GetIndex()))
2.利用状态数据库中Game中存有相应的Action时的txhash,从而去查询相应action时的 height和index,
继而可以得到准确的key,从而删除localDB中的臃余索引。
*/
func (action *Action) GetReceiptLog(game *gt.Game) *types.ReceiptLog { func (action *Action) GetReceiptLog(game *gt.Game) *types.ReceiptLog {
log := &types.ReceiptLog{} log := &types.ReceiptLog{}
r := &gt.ReceiptGame{} r := &gt.ReceiptGame{}
...@@ -108,47 +109,53 @@ func (action *Action) GetReceiptLog(game *gt.Game) *types.ReceiptLog { ...@@ -108,47 +109,53 @@ func (action *Action) GetReceiptLog(game *gt.Game) *types.ReceiptLog {
return log return log
} }
//fmt.Sprintf("%018d", action.height*types.MaxTxsPerBlock+int64(action.index)) //GetIndex get index
func (action *Action) GetIndex(game *gt.Game) int64 { func (action *Action) GetIndex(game *gt.Game) int64 {
return action.height*types.MaxTxsPerBlock + int64(action.index) return action.height*types.MaxTxsPerBlock + int64(action.index)
} }
//GetKVSet get kv set
func (action *Action) GetKVSet(game *gt.Game) (kvset []*types.KeyValue) { func (action *Action) GetKVSet(game *gt.Game) (kvset []*types.KeyValue) {
value := types.Encode(game) value := types.Encode(game)
kvset = append(kvset, &types.KeyValue{Key(game.GameId), value}) kvset = append(kvset, &types.KeyValue{Key(game.GameId), value})
return kvset return kvset
} }
func (action *Action) updateCount(status int32, addr string) (kvset []*types.KeyValue) { func (action *Action) updateCount(status int32, addr string) (kvset []*types.KeyValue) {
count, err := queryCountByStatusAndAddr(action.db, status, addr) count, err := queryCountByStatusAndAddr(action.db, status, addr)
if err != nil { if err != nil {
glog.Error("Query count have err:", err.Error()) glog.Error("updateCount", "Query count have err:", err.Error())
} }
kvset = append(kvset, &types.KeyValue{CalcCountKey(status, addr), []byte(strconv.FormatInt(count+1, 10))}) kvset = append(kvset, &types.KeyValue{calcCountKey(status, addr), []byte(strconv.FormatInt(count+1, 10))})
return kvset return kvset
} }
func (action *Action) updateStateDBCache(status int32, addr string) { func (action *Action) updateStateDBCache(status int32, addr string) {
count, err := queryCountByStatusAndAddr(action.db, status, addr) count, err := queryCountByStatusAndAddr(action.db, status, addr)
if err != nil { if err != nil {
glog.Error("Query count have err:", err.Error()) glog.Error("updateStateDBCache", "Query count have err:", err.Error())
} }
action.db.Set(CalcCountKey(status, addr), []byte(strconv.FormatInt(count+1, 10))) action.db.Set(calcCountKey(status, addr), []byte(strconv.FormatInt(count+1, 10)))
} }
func (action *Action) saveStateDB(game *gt.Game) { func (action *Action) saveStateDB(game *gt.Game) {
action.db.Set(Key(game.GetGameId()), types.Encode(game)) action.db.Set(Key(game.GetGameId()), types.Encode(game))
} }
func CalcCountKey(status int32, addr string) (key []byte) {
func calcCountKey(status int32, addr string) (key []byte) {
key = append(key, []byte("mavl-"+gt.GameX+"-")...) key = append(key, []byte("mavl-"+gt.GameX+"-")...)
key = append(key, []byte(fmt.Sprintf("%s:%d:%s", GameCount, status, addr))...) key = append(key, []byte(fmt.Sprintf("%s:%d:%s", GameCount, status, addr))...)
return key return key
} }
//gameId to save key // Key gameId to save key
func Key(id string) (key []byte) { func Key(id string) (key []byte) {
key = append(key, []byte("mavl-"+gt.GameX+"-")...) key = append(key, []byte("mavl-"+gt.GameX+"-")...)
key = append(key, []byte(id)...) key = append(key, []byte(id)...)
return key return key
} }
// Action action struct
type Action struct { type Action struct {
coinsAccount *account.DB coinsAccount *account.DB
db dbm.KV db dbm.KV
...@@ -161,35 +168,39 @@ type Action struct { ...@@ -161,35 +168,39 @@ type Action struct {
index int index int
} }
// NewAction new action
func NewAction(g *Game, tx *types.Transaction, index int) *Action { func NewAction(g *Game, tx *types.Transaction, index int) *Action {
hash := tx.Hash() hash := tx.Hash()
fromaddr := tx.From() fromaddr := tx.From()
return &Action{g.GetCoinsAccount(), g.GetStateDB(), hash, fromaddr, return &Action{g.GetCoinsAccount(), g.GetStateDB(), hash, fromaddr,
g.GetBlockTime(), g.GetHeight(), dapp.ExecAddress(string(tx.Execer)), g.GetLocalDB(), index} g.GetBlockTime(), g.GetHeight(), dapp.ExecAddress(string(tx.Execer)), g.GetLocalDB(), index}
} }
func (action *Action) CheckExecAccountBalance(fromAddr string, ToFrozen, ToActive int64) bool {
func (action *Action) checkExecAccountBalance(fromAddr string, ToFrozen, ToActive int64) bool {
acc := action.coinsAccount.LoadExecAccount(fromAddr, action.execaddr) acc := action.coinsAccount.LoadExecAccount(fromAddr, action.execaddr)
if acc.GetBalance() >= ToFrozen && acc.GetFrozen() >= ToActive { if acc.GetBalance() >= ToFrozen && acc.GetFrozen() >= ToActive {
return true return true
} }
return false return false
} }
// GameCreate create game
func (action *Action) GameCreate(create *gt.GameCreate) (*types.Receipt, error) { func (action *Action) GameCreate(create *gt.GameCreate) (*types.Receipt, error) {
gameId := common.ToHex(action.txhash) gameID := common.ToHex(action.txhash)
var logs []*types.ReceiptLog var logs []*types.ReceiptLog
var kv []*types.KeyValue var kv []*types.KeyValue
maxGameAmount := GetConfValue(action.db, ConfName_MaxGameAmount, MaxGameAmount) maxGameAmount := getConfValue(action.db, ConfNameMaxGameAmount, MaxGameAmount)
if create.GetValue() > maxGameAmount*types.Coin { if create.GetValue() > maxGameAmount*types.Coin {
glog.Error("Create the game, the deposit is too big ", "value", create.GetValue()) glog.Error("Create the game, the deposit is too big ", "value", create.GetValue(), "err", gt.ErrGameCreateAmount.Error())
return nil, gt.ErrGameCreateAmount return nil, gt.ErrGameCreateAmount
} }
minGameAmount := GetConfValue(action.db, ConfName_MinGameAmount, MinGameAmount) minGameAmount := getConfValue(action.db, ConfNameMinGameAmount, MinGameAmount)
if create.GetValue() < minGameAmount*types.Coin || math.Remainder(float64(create.GetValue()), 2) != 0 { if create.GetValue() < minGameAmount*types.Coin || math.Remainder(float64(create.GetValue()), 2) != 0 {
return nil, fmt.Errorf("The amount you participate in cannot be less than 2 and must be an even number.") return nil, fmt.Errorf("%s", "The amount you participate in cannot be less than 2 and must be an even number!")
} }
if !action.CheckExecAccountBalance(action.fromaddr, create.GetValue(), 0) { if !action.checkExecAccountBalance(action.fromaddr, create.GetValue(), 0) {
glog.Error("GameCreate", "addr", action.fromaddr, "execaddr", action.execaddr, "id", glog.Error("GameCreate", "addr", action.fromaddr, "execaddr", action.execaddr, "id",
gameId, "err", types.ErrNoBalance) gameID, "err", types.ErrNoBalance.Error())
return nil, types.ErrNoBalance return nil, types.ErrNoBalance
} }
//冻结子账户资金 //冻结子账户资金
...@@ -199,14 +210,14 @@ func (action *Action) GameCreate(create *gt.GameCreate) (*types.Receipt, error) ...@@ -199,14 +210,14 @@ func (action *Action) GameCreate(create *gt.GameCreate) (*types.Receipt, error)
return nil, err return nil, err
} }
game := &gt.Game{ game := &gt.Game{
GameId: gameId, GameId: gameID,
Value: create.GetValue(), Value: create.GetValue(),
HashType: create.GetHashType(), HashType: create.GetHashType(),
HashValue: create.GetHashValue(), HashValue: create.GetHashValue(),
CreateTime: action.blocktime, CreateTime: action.blocktime,
CreateAddress: action.fromaddr, CreateAddress: action.fromaddr,
Status: gt.GameActionCreate, Status: gt.GameActionCreate,
CreateTxHash: gameId, CreateTxHash: gameID,
} }
//更新stateDB缓存,用于计数 //更新stateDB缓存,用于计数
action.updateStateDBCache(game.GetStatus(), "") action.updateStateDBCache(game.GetStatus(), "")
...@@ -224,27 +235,27 @@ func (action *Action) GameCreate(create *gt.GameCreate) (*types.Receipt, error) ...@@ -224,27 +235,27 @@ func (action *Action) GameCreate(create *gt.GameCreate) (*types.Receipt, error)
return receipt, nil return receipt, nil
} }
//match game // GameMatch match game
func (action *Action) GameMatch(match *gt.GameMatch) (*types.Receipt, error) { func (action *Action) GameMatch(match *gt.GameMatch) (*types.Receipt, error) {
game, err := action.readGame(match.GetGameId()) game, err := action.readGame(match.GetGameId())
if err != nil { if err != nil {
glog.Error("GameMatch", "addr", action.fromaddr, "execaddr", action.execaddr, "get game failed", glog.Error("GameMatch", "addr", action.fromaddr, "execaddr", action.execaddr, "get game failed",
match.GetGameId(), "err", err) match.GetGameId(), "err", err.Error())
return nil, err return nil, err
} }
if game.GetStatus() != gt.GameActionCreate { if game.GetStatus() != gt.GameActionCreate {
glog.Error("GameMatch", "addr", action.fromaddr, "execaddr", action.execaddr, "id", glog.Error("GameMatch", "addr", action.fromaddr, "execaddr", action.execaddr, "id",
match.GetGameId(), "err", gt.ErrGameMatchStatus) match.GetGameId(), "err", gt.ErrGameMatchStatus.Error())
return nil, gt.ErrGameMatchStatus return nil, gt.ErrGameMatchStatus
} }
if game.GetCreateAddress() == action.fromaddr { if game.GetCreateAddress() == action.fromaddr {
glog.Error("GameMatch", "addr", action.fromaddr, "execaddr", action.execaddr, "id", glog.Error("GameMatch", "addr", action.fromaddr, "execaddr", action.execaddr, "id",
match.GetGameId(), "err", gt.ErrGameMatch) match.GetGameId(), "err", gt.ErrGameMatch.Error())
return nil, gt.ErrGameMatch return nil, gt.ErrGameMatch
} }
if !action.CheckExecAccountBalance(action.fromaddr, game.GetValue()/2, 0) { if !action.checkExecAccountBalance(action.fromaddr, game.GetValue()/2, 0) {
glog.Error("GameMatch", "addr", action.fromaddr, "execaddr", action.execaddr, "id", glog.Error("GameMatch", "addr", action.fromaddr, "execaddr", action.execaddr, "id",
match.GetGameId(), "err", types.ErrNoBalance) match.GetGameId(), "err", types.ErrNoBalance.Error())
return nil, types.ErrNoBalance return nil, types.ErrNoBalance
} }
//冻结 game value 中资金的一半 //冻结 game value 中资金的一半
...@@ -278,32 +289,34 @@ func (action *Action) GameMatch(match *gt.GameMatch) (*types.Receipt, error) { ...@@ -278,32 +289,34 @@ func (action *Action) GameMatch(match *gt.GameMatch) (*types.Receipt, error) {
receipts := &types.Receipt{types.ExecOk, kvs, logs} receipts := &types.Receipt{types.ExecOk, kvs, logs}
return receipts, nil return receipts, nil
} }
// GameCancel cancel game
func (action *Action) GameCancel(cancel *gt.GameCancel) (*types.Receipt, error) { func (action *Action) GameCancel(cancel *gt.GameCancel) (*types.Receipt, error) {
game, err := action.readGame(cancel.GetGameId()) game, err := action.readGame(cancel.GetGameId())
if err != nil { if err != nil {
glog.Error("GameCancel ", "addr", action.fromaddr, "execaddr", action.execaddr, "get game failed", glog.Error("GameCancel ", "addr", action.fromaddr, "execaddr", action.execaddr, "get game failed",
cancel.GetGameId(), "err", err) cancel.GetGameId(), "err", err.Error())
return nil, err return nil, err
} }
if game.GetCreateAddress() != action.fromaddr { if game.GetCreateAddress() != action.fromaddr {
glog.Error("GameCancel ", "addr", action.fromaddr, "execaddr", action.execaddr, "id", glog.Error("GameCancel ", "addr", action.fromaddr, "execaddr", action.execaddr, "id",
cancel.GetGameId(), "err", gt.ErrGameCancleAddr) cancel.GetGameId(), "err", gt.ErrGameCancleAddr.Error())
return nil, gt.ErrGameCancleAddr return nil, gt.ErrGameCancleAddr
} }
if game.GetStatus() != gt.GameActionCreate { if game.GetStatus() != gt.GameActionCreate {
glog.Error("GameCancel ", "addr", action.fromaddr, "execaddr", action.execaddr, "id", glog.Error("GameCancel ", "addr", action.fromaddr, "execaddr", action.execaddr, "id",
cancel.GetGameId(), "err", gt.ErrGameCancleStatus) cancel.GetGameId(), "err", gt.ErrGameCancleStatus.Error())
return nil, gt.ErrGameCancleStatus return nil, gt.ErrGameCancleStatus
} }
if !action.CheckExecAccountBalance(action.fromaddr, 0, game.GetValue()) { if !action.checkExecAccountBalance(action.fromaddr, 0, game.GetValue()) {
glog.Error("GameCancel", "addr", action.fromaddr, "execaddr", action.execaddr, "id", glog.Error("GameCancel", "addr", action.fromaddr, "execaddr", action.execaddr, "id",
game.GetGameId(), "err", types.ErrNoBalance) game.GetGameId(), "err", types.ErrNoBalance.Error())
return nil, types.ErrNoBalance return nil, types.ErrNoBalance
} }
receipt, err := action.coinsAccount.ExecActive(game.GetCreateAddress(), action.execaddr, game.GetValue()) receipt, err := action.coinsAccount.ExecActive(game.GetCreateAddress(), action.execaddr, game.GetValue())
if err != nil { if err != nil {
glog.Error("GameCancel ", "addr", action.fromaddr, "execaddr", action.execaddr, "id", glog.Error("GameCancel ", "addr", action.fromaddr, "execaddr", action.execaddr, "id",
cancel.GetGameId(), "amount", game.GetValue(), "err", err) cancel.GetGameId(), "amount", game.GetValue(), "err", err.Error())
return nil, err return nil, err
} }
game.Closetime = action.blocktime game.Closetime = action.blocktime
...@@ -328,13 +341,14 @@ func (action *Action) GameCancel(cancel *gt.GameCancel) (*types.Receipt, error) ...@@ -328,13 +341,14 @@ func (action *Action) GameCancel(cancel *gt.GameCancel) (*types.Receipt, error)
return &types.Receipt{types.ExecOk, kv, logs}, nil return &types.Receipt{types.ExecOk, kv, logs}, nil
} }
// GameClose close game
func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
var logs []*types.ReceiptLog var logs []*types.ReceiptLog
var kv []*types.KeyValue var kv []*types.KeyValue
game, err := action.readGame(close.GetGameId()) game, err := action.readGame(close.GetGameId())
if err != nil { if err != nil {
glog.Error("GameClose ", "addr", action.fromaddr, "execaddr", action.execaddr, "get game failed", glog.Error("GameClose ", "addr", action.fromaddr, "execaddr", action.execaddr, "get game failed",
close.GetGameId(), "err", err) close.GetGameId(), "err", err.Error())
return nil, err return nil, err
} }
//开奖时间控制 //开奖时间控制
...@@ -348,14 +362,14 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { ...@@ -348,14 +362,14 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
return nil, gt.ErrGameCloseStatus return nil, gt.ErrGameCloseStatus
} }
//各自冻结余额检查 //各自冻结余额检查
if !action.CheckExecAccountBalance(game.GetCreateAddress(), 0, 2*game.GetValue()/3) { if !action.checkExecAccountBalance(game.GetCreateAddress(), 0, 2*game.GetValue()/3) {
glog.Error("GameClose", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "id", glog.Error("GameClose", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "id",
game.GetGameId(), "err", types.ErrNoBalance) game.GetGameId(), "err", types.ErrNoBalance.Error())
return nil, types.ErrNoBalance return nil, types.ErrNoBalance
} }
if !action.CheckExecAccountBalance(game.GetMatchAddress(), 0, game.GetValue()/3) { if !action.checkExecAccountBalance(game.GetMatchAddress(), 0, game.GetValue()/3) {
glog.Error("GameClose", "addr", game.GetMatchAddress(), "execaddr", action.execaddr, "id", glog.Error("GameClose", "addr", game.GetMatchAddress(), "execaddr", action.execaddr, "id",
game.GetGameId(), "err", types.ErrNoBalance) game.GetGameId(), "err", types.ErrNoBalance.Error())
return nil, types.ErrNoBalance return nil, types.ErrNoBalance
} }
result, creatorGuess := action.checkGameResult(game, close) result, creatorGuess := action.checkGameResult(game, close)
...@@ -364,7 +378,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { ...@@ -364,7 +378,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
receipt, err := action.coinsAccount.ExecActive(game.GetCreateAddress(), action.execaddr, 2*game.GetValue()/3) receipt, err := action.coinsAccount.ExecActive(game.GetCreateAddress(), action.execaddr, 2*game.GetValue()/3)
if err != nil { if err != nil {
glog.Error("GameClose.execActive", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", 2*game.GetValue()/3, glog.Error("GameClose.execActive", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", 2*game.GetValue()/3,
"err", err) "err", err.Error())
return nil, err return nil, err
} }
logs = append(logs, receipt.Logs...) logs = append(logs, receipt.Logs...)
...@@ -373,7 +387,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { ...@@ -373,7 +387,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
if err != nil { if err != nil {
action.coinsAccount.ExecFrozen(game.GetCreateAddress(), action.execaddr, 2*game.GetValue()/3) // rollback action.coinsAccount.ExecFrozen(game.GetCreateAddress(), action.execaddr, 2*game.GetValue()/3) // rollback
glog.Error("GameClose.ExecTransferFrozen", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", 2*game.GetValue()/3, glog.Error("GameClose.ExecTransferFrozen", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", 2*game.GetValue()/3,
"err", err) "err", err.Error())
return nil, err return nil, err
} }
logs = append(logs, receipt.Logs...) logs = append(logs, receipt.Logs...)
...@@ -383,7 +397,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { ...@@ -383,7 +397,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
receipt, err := action.coinsAccount.ExecActive(game.GetCreateAddress(), action.execaddr, game.GetValue()/3) receipt, err := action.coinsAccount.ExecActive(game.GetCreateAddress(), action.execaddr, game.GetValue()/3)
if err != nil { if err != nil {
glog.Error("GameClose.ExecActive", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", game.GetValue()/3, glog.Error("GameClose.ExecActive", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", game.GetValue()/3,
"err", err) "err", err.Error())
return nil, err return nil, err
} }
logs = append(logs, receipt.Logs...) logs = append(logs, receipt.Logs...)
...@@ -392,7 +406,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { ...@@ -392,7 +406,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
if err != nil { if err != nil {
action.coinsAccount.ExecFrozen(game.GetCreateAddress(), action.execaddr, game.GetValue()/3) // rollback action.coinsAccount.ExecFrozen(game.GetCreateAddress(), action.execaddr, game.GetValue()/3) // rollback
glog.Error("GameClose.ExecActive", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", game.GetValue()/3, glog.Error("GameClose.ExecActive", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", game.GetValue()/3,
"err", err) "err", err.Error())
return nil, err return nil, err
} }
logs = append(logs, receipt.Logs...) logs = append(logs, receipt.Logs...)
...@@ -402,7 +416,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { ...@@ -402,7 +416,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
action.coinsAccount.ExecFrozen(game.GetCreateAddress(), action.execaddr, game.GetValue()/3) // rollback action.coinsAccount.ExecFrozen(game.GetCreateAddress(), action.execaddr, game.GetValue()/3) // rollback
action.coinsAccount.ExecFrozen(game.GetMatchAddress(), action.execaddr, game.GetValue()/3) // rollback action.coinsAccount.ExecFrozen(game.GetMatchAddress(), action.execaddr, game.GetValue()/3) // rollback
glog.Error("GameClose.ExecTransferFrozen", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", game.GetValue()/3, glog.Error("GameClose.ExecTransferFrozen", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", game.GetValue()/3,
"err", err) "err", err.Error())
return nil, err return nil, err
} }
logs = append(logs, receipt.Logs...) logs = append(logs, receipt.Logs...)
...@@ -413,7 +427,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { ...@@ -413,7 +427,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
receipt, err := action.coinsAccount.ExecActive(game.GetCreateAddress(), action.execaddr, 2*game.GetValue()/3) receipt, err := action.coinsAccount.ExecActive(game.GetCreateAddress(), action.execaddr, 2*game.GetValue()/3)
if err != nil { if err != nil {
glog.Error("GameClose.ExecActive", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", 2*game.GetValue()/3, glog.Error("GameClose.ExecActive", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", 2*game.GetValue()/3,
"err", err) "err", err.Error())
return nil, err return nil, err
} }
logs = append(logs, receipt.Logs...) logs = append(logs, receipt.Logs...)
...@@ -422,7 +436,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { ...@@ -422,7 +436,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
if err != nil { if err != nil {
action.coinsAccount.ExecFrozen(game.GetCreateAddress(), action.execaddr, 2*game.GetValue()/3) // rollback action.coinsAccount.ExecFrozen(game.GetCreateAddress(), action.execaddr, 2*game.GetValue()/3) // rollback
glog.Error("GameClose.ExecActive", "addr", game.GetMatchAddress(), "execaddr", action.execaddr, "amount", game.GetValue()/3, glog.Error("GameClose.ExecActive", "addr", game.GetMatchAddress(), "execaddr", action.execaddr, "amount", game.GetValue()/3,
"err", err) "err", err.Error())
return nil, err return nil, err
} }
logs = append(logs, receipt.Logs...) logs = append(logs, receipt.Logs...)
...@@ -432,7 +446,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { ...@@ -432,7 +446,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
receipt, err := action.coinsAccount.ExecActive(game.GetMatchAddress(), action.execaddr, game.GetValue()/3) receipt, err := action.coinsAccount.ExecActive(game.GetMatchAddress(), action.execaddr, game.GetValue()/3)
if err != nil { if err != nil {
glog.Error("GameClose.ExecActive", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", 2*game.GetValue()/3, glog.Error("GameClose.ExecActive", "addr", game.GetCreateAddress(), "execaddr", action.execaddr, "amount", 2*game.GetValue()/3,
"err", err) "err", err.Error())
return nil, err return nil, err
} }
logs = append(logs, receipt.Logs...) logs = append(logs, receipt.Logs...)
...@@ -441,7 +455,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { ...@@ -441,7 +455,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
if err != nil { if err != nil {
action.coinsAccount.ExecFrozen(game.GetMatchAddress(), action.execaddr, game.GetValue()/3) // rollback action.coinsAccount.ExecFrozen(game.GetMatchAddress(), action.execaddr, game.GetValue()/3) // rollback
glog.Error("GameClose.ExecTransferFrozen", "addr", game.GetMatchAddress(), "execaddr", action.execaddr, "amount", game.GetValue()/3, glog.Error("GameClose.ExecTransferFrozen", "addr", game.GetMatchAddress(), "execaddr", action.execaddr, "amount", game.GetValue()/3,
"err", err) "err", err.Error())
return nil, err return nil, err
} }
logs = append(logs, receipt.Logs...) logs = append(logs, receipt.Logs...)
...@@ -472,7 +486,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) { ...@@ -472,7 +486,7 @@ func (action *Action) GameClose(close *gt.GameClose) (*types.Receipt, error) {
// 检查开奖是否超时,若超过一天,则不让庄家开奖,但其他人可以开奖, // 检查开奖是否超时,若超过一天,则不让庄家开奖,但其他人可以开奖,
// 若没有一天,则其他人没有开奖权限,只有庄家有开奖权限 // 若没有一天,则其他人没有开奖权限,只有庄家有开奖权限
func (action *Action) checkGameIsTimeOut(game *gt.Game) bool { func (action *Action) checkGameIsTimeOut(game *gt.Game) bool {
activeTime := GetConfValue(action.db, ConfName_ActiveTime, ActiveTime) activeTime := getConfValue(action.db, ConfNameActiveTime, ActiveTime)
DurTime := 60 * 60 * activeTime DurTime := 60 * 60 * activeTime
return action.blocktime > (game.GetMatchTime() + DurTime) return action.blocktime > (game.GetMatchTime() + DurTime)
} }
...@@ -491,10 +505,10 @@ func (action *Action) checkGameResult(game *gt.Game, close *gt.GameClose) (int32 ...@@ -491,10 +505,10 @@ func (action *Action) checkGameResult(game *gt.Game, close *gt.GameClose) (int32
return IsCreatorWin, Rock return IsCreatorWin, Rock
} else if game.GetMatcherGuess() == Paper { } else if game.GetMatcherGuess() == Paper {
return IsMatcherWin, Rock return IsMatcherWin, Rock
} else { }
//其他情况说明matcher 使坏,填了其他值,当做作弊处理 //其他情况说明matcher 使坏,填了其他值,当做作弊处理
return IsCreatorWin, Rock return IsCreatorWin, Rock
}
} else if bytes.Equal(common.Sha256([]byte(close.GetSecret()+string(Scissor))), game.GetHashValue()) { } else if bytes.Equal(common.Sha256([]byte(close.GetSecret()+string(Scissor))), game.GetHashValue()) {
//此刻庄家出的剪刀 //此刻庄家出的剪刀
if game.GetMatcherGuess() == Rock { if game.GetMatcherGuess() == Rock {
...@@ -503,9 +517,9 @@ func (action *Action) checkGameResult(game *gt.Game, close *gt.GameClose) (int32 ...@@ -503,9 +517,9 @@ func (action *Action) checkGameResult(game *gt.Game, close *gt.GameClose) (int32
return IsDraw, Scissor return IsDraw, Scissor
} else if game.GetMatcherGuess() == Paper { } else if game.GetMatcherGuess() == Paper {
return IsCreatorWin, Scissor return IsCreatorWin, Scissor
} else {
return IsCreatorWin, Scissor
} }
return IsCreatorWin, Scissor
} else if bytes.Equal(common.Sha256([]byte(close.GetSecret()+string(Paper))), game.GetHashValue()) { } else if bytes.Equal(common.Sha256([]byte(close.GetSecret()+string(Paper))), game.GetHashValue()) {
//此刻庄家出的是布 //此刻庄家出的是布
if game.GetMatcherGuess() == Rock { if game.GetMatcherGuess() == Rock {
...@@ -514,9 +528,9 @@ func (action *Action) checkGameResult(game *gt.Game, close *gt.GameClose) (int32 ...@@ -514,9 +528,9 @@ func (action *Action) checkGameResult(game *gt.Game, close *gt.GameClose) (int32
return IsMatcherWin, Paper return IsMatcherWin, Paper
} else if game.GetMatcherGuess() == Paper { } else if game.GetMatcherGuess() == Paper {
return IsDraw, Paper return IsDraw, Paper
} else {
return IsCreatorWin, Paper
} }
return IsCreatorWin, Paper
} }
//其他情况默认是matcher win //其他情况默认是matcher win
return IsMatcherWin, Unknown return IsMatcherWin, Unknown
...@@ -536,17 +550,18 @@ func (action *Action) readGame(id string) (*gt.Game, error) { ...@@ -536,17 +550,18 @@ func (action *Action) readGame(id string) (*gt.Game, error) {
return &game, nil return &game, nil
} }
// List query game list
func List(db dbm.Lister, stateDB dbm.KV, param *gt.QueryGameListByStatusAndAddr) (types.Message, error) { func List(db dbm.Lister, stateDB dbm.KV, param *gt.QueryGameListByStatusAndAddr) (types.Message, error) {
return QueryGameListByPage(db, stateDB, param) return QueryGameListByPage(db, stateDB, param)
} }
//分页查询 // QueryGameListByPage 分页查询
func QueryGameListByPage(db dbm.Lister, stateDB dbm.KV, param *gt.QueryGameListByStatusAndAddr) (types.Message, error) { func QueryGameListByPage(db dbm.Lister, stateDB dbm.KV, param *gt.QueryGameListByStatusAndAddr) (types.Message, error) {
switch param.GetStatus() { switch param.GetStatus() {
case gt.GameActionCreate, gt.GameActionMatch, gt.GameActionClose, gt.GameActionCancel: case gt.GameActionCreate, gt.GameActionMatch, gt.GameActionClose, gt.GameActionCancel:
return queryGameListByStatusAndAddr(db, stateDB, param) return queryGameListByStatusAndAddr(db, stateDB, param)
} }
return nil, fmt.Errorf("the status only fill in 1,2,3,4!") return nil, fmt.Errorf("%s", "the status only fill in 1,2,3,4!")
} }
func queryGameListByStatusAndAddr(db dbm.Lister, stateDB dbm.KV, param *gt.QueryGameListByStatusAndAddr) (types.Message, error) { func queryGameListByStatusAndAddr(db dbm.Lister, stateDB dbm.KV, param *gt.QueryGameListByStatusAndAddr) (types.Message, error) {
...@@ -554,8 +569,8 @@ func queryGameListByStatusAndAddr(db dbm.Lister, stateDB dbm.KV, param *gt.Query ...@@ -554,8 +569,8 @@ func queryGameListByStatusAndAddr(db dbm.Lister, stateDB dbm.KV, param *gt.Query
if param.GetDirection() == ListASC { if param.GetDirection() == ListASC {
direction = ListASC direction = ListASC
} }
count := int32(GetConfValue(stateDB, ConfName_DefaultCount, DefaultCount)) count := int32(getConfValue(stateDB, ConfNameDefaultCount, DefaultCount))
maxCount := int32(GetConfValue(stateDB, ConfName_MaxCount, MaxCount)) maxCount := int32(getConfValue(stateDB, ConfNameMaxCount, MaxCount))
if 0 < param.GetCount() && param.GetCount() <= maxCount { if 0 < param.GetCount() && param.GetCount() <= maxCount {
count = param.GetCount() count = param.GetCount()
} }
...@@ -590,13 +605,15 @@ func queryGameListByStatusAndAddr(db dbm.Lister, stateDB dbm.KV, param *gt.Query ...@@ -590,13 +605,15 @@ func queryGameListByStatusAndAddr(db dbm.Lister, stateDB dbm.KV, param *gt.Query
return &gt.ReplyGameList{GetGameList(stateDB, gameIds)}, nil return &gt.ReplyGameList{GetGameList(stateDB, gameIds)}, nil
} }
//count数查询 // QueryGameListCount count数查询
func QueryGameListCount(stateDB dbm.KV, param *gt.QueryGameListCount) (types.Message, error) { func QueryGameListCount(stateDB dbm.KV, param *gt.QueryGameListCount) (types.Message, error) {
if param.Status < 1 || param.Status > 4 { if param.Status < 1 || param.Status > 4 {
return nil, fmt.Errorf("the status only fill in 1,2,3,4!") return nil, fmt.Errorf("%s", "the status only fill in 1,2,3,4!")
} }
return &gt.ReplyGameListCount{QueryCountByStatusAndAddr(stateDB, param.GetStatus(), param.GetAddress())}, nil return &gt.ReplyGameListCount{QueryCountByStatusAndAddr(stateDB, param.GetStatus(), param.GetAddress())}, nil
} }
// QueryCountByStatusAndAddr query game count by status and addr
func QueryCountByStatusAndAddr(stateDB dbm.KV, status int32, addr string) int64 { func QueryCountByStatusAndAddr(stateDB dbm.KV, status int32, addr string) int64 {
switch status { switch status {
case gt.GameActionCreate, gt.GameActionMatch, gt.GameActionCancel, gt.GameActionClose: case gt.GameActionCreate, gt.GameActionMatch, gt.GameActionCancel, gt.GameActionClose:
...@@ -607,14 +624,14 @@ func QueryCountByStatusAndAddr(stateDB dbm.KV, status int32, addr string) int64 ...@@ -607,14 +624,14 @@ func QueryCountByStatusAndAddr(stateDB dbm.KV, status int32, addr string) int64
return 0 return 0
} }
func queryCountByStatusAndAddr(stateDB dbm.KV, status int32, addr string) (int64, error) { func queryCountByStatusAndAddr(stateDB dbm.KV, status int32, addr string) (int64, error) {
data, err := stateDB.Get(CalcCountKey(status, addr)) data, err := stateDB.Get(calcCountKey(status, addr))
if err != nil { if err != nil {
glog.Error("query count have err:", err.Error()) glog.Error("queryCountByStatusAndAddr", "query count have err:", err.Error())
return 0, err return 0, err
} }
count, err := strconv.ParseInt(string(data), 10, 64) count, err := strconv.ParseInt(string(data), 10, 64)
if err != nil { if err != nil {
glog.Error("Type conversion error:", err.Error()) glog.Error("queryCountByStatusAndAddr", "Type conversion error:", err.Error())
return 0, err return 0, err
} }
return count, nil return count, nil
...@@ -623,20 +640,21 @@ func queryCountByStatusAndAddr(stateDB dbm.KV, status int32, addr string) (int64 ...@@ -623,20 +640,21 @@ func queryCountByStatusAndAddr(stateDB dbm.KV, status int32, addr string) (int64
func readGame(db dbm.KV, id string) (*gt.Game, error) { func readGame(db dbm.KV, id string) (*gt.Game, error) {
data, err := db.Get(Key(id)) data, err := db.Get(Key(id))
if err != nil { if err != nil {
glog.Error("query data have err:", err.Error()) glog.Error("readGame", "query data have err:", err.Error())
return nil, err return nil, err
} }
var game gt.Game var game gt.Game
//decode //decode
err = types.Decode(data, &game) err = types.Decode(data, &game)
if err != nil { if err != nil {
glog.Error("decode game have err:", err.Error()) glog.Error("readGame", "decode game have err:", err.Error())
return nil, err return nil, err
} }
return &game, nil return &game, nil
} }
func Infos(db dbm.KV, infos *gt.QueryGameInfos) (types.Message, error) { // QueryGameListByIds query game list by gameIds
func QueryGameListByIds(db dbm.KV, infos *gt.QueryGameInfos) (types.Message, error) {
var games []*gt.Game var games []*gt.Game
for i := 0; i < len(infos.GameIds); i++ { for i := 0; i < len(infos.GameIds); i++ {
id := infos.GameIds[i] id := infos.GameIds[i]
...@@ -649,7 +667,7 @@ func Infos(db dbm.KV, infos *gt.QueryGameInfos) (types.Message, error) { ...@@ -649,7 +667,7 @@ func Infos(db dbm.KV, infos *gt.QueryGameInfos) (types.Message, error) {
return &gt.ReplyGameList{Games: games}, nil return &gt.ReplyGameList{Games: games}, nil
} }
//安全批量查询方式,防止因为脏数据导致查询接口奔溃 // GetGameList 安全批量查询方式,防止因为脏数据导致查询接口奔溃
func GetGameList(db dbm.KV, values []string) []*gt.Game { func GetGameList(db dbm.KV, values []string) []*gt.Game {
var games []*gt.Game var games []*gt.Game
for _, value := range values { for _, value := range values {
...@@ -661,29 +679,29 @@ func GetGameList(db dbm.KV, values []string) []*gt.Game { ...@@ -661,29 +679,29 @@ func GetGameList(db dbm.KV, values []string) []*gt.Game {
} }
return games return games
} }
func GetConfValue(db dbm.KV, key string, default_value int64) int64 { func getConfValue(db dbm.KV, key string, defaultValue int64) int64 {
var item types.ConfigItem var item types.ConfigItem
value, err := getManageKey(key, db) value, err := getManageKey(key, db)
if err != nil { if err != nil {
return default_value return defaultValue
} }
if value != nil { if value != nil {
err = types.Decode(value, &item) err = types.Decode(value, &item)
if err != nil { if err != nil {
glog.Error("gamedb GetConfValue", "decode db key:", key, err.Error()) glog.Error("gamedb getConfValue", "decode db key:", key, "err", err.Error())
return default_value return defaultValue
} }
} }
values := item.GetArr().GetValue() values := item.GetArr().GetValue()
if len(values) == 0 { if len(values) == 0 {
glog.Error("gamedb GetConfValue", "can't get value from values arr. key:", key) glog.Error("gamedb getConfValue", "can't get value from values arr. key:", key)
return default_value return defaultValue
} }
//取数组最后一位,作为最新配置项的值 //取数组最后一位,作为最新配置项的值
v, err := strconv.ParseInt(values[len(values)-1], 10, 64) v, err := strconv.ParseInt(values[len(values)-1], 10, 64)
if err != nil { if err != nil {
glog.Error("gamedb GetConfValue", "Type conversion error:", err.Error()) glog.Error("gamedb getConfValue", "Type conversion error:", err.Error())
return default_value return defaultValue
} }
return v return v
} }
...@@ -692,10 +710,10 @@ func getManageKey(key string, db dbm.KV) ([]byte, error) { ...@@ -692,10 +710,10 @@ func getManageKey(key string, db dbm.KV) ([]byte, error) {
value, err := db.Get([]byte(manageKey)) value, err := db.Get([]byte(manageKey))
if err != nil { if err != nil {
if types.IsPara() { //平行链只有一种存储方式 if types.IsPara() { //平行链只有一种存储方式
glog.Error("gamedb getManage", "can't get value from db,key:", key, err.Error()) glog.Error("gamedb getManage", "can't get value from db,key:", key, "err", err.Error())
return nil, err return nil, err
} }
glog.Debug("gamedb", "get db key", "not found") glog.Debug("gamedb getManageKey", "get db key", "not found")
return getConfigKey(key, db) return getConfigKey(key, db)
} }
return value, nil return value, nil
...@@ -705,7 +723,7 @@ func getConfigKey(key string, db dbm.KV) ([]byte, error) { ...@@ -705,7 +723,7 @@ func getConfigKey(key string, db dbm.KV) ([]byte, error) {
configKey := types.ConfigKey(key) configKey := types.ConfigKey(key)
value, err := db.Get([]byte(configKey)) value, err := db.Get([]byte(configKey))
if err != nil { if err != nil {
glog.Error("gamedb getConfigKey", "can't get value from db,key:", key, err.Error()) glog.Error("gamedb getConfigKey", "can't get value from db,key:", key, "err", err.Error())
return nil, err return nil, err
} }
return value, nil return value, nil
......
...@@ -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