EOS基础全家桶(十)交易Action操作

简介

区块链上的所有操作都是通过交易(Transaction)上链的,无论你是转账交易还是发起的智能合约的调用,而EOS和传统区块链不同的是EOS在一个交易里可以发起多个行为(Action),这使得EOS的操作可以支持更原子化的事务控制,也同时为上链增加了便捷性和可操作性。而今天我们就要学习下EOS中的交易的结构和交易的操作。

交易结构

我们先用之前账号管理篇章中使用的创建系统账号的方法来看一下一个交易的结构。

cleos create account eosio astaldo \
EOS6nbWS7ZReiPMdMABoEmVBYanyTMb3GYRQGsTRMCYx9vijWoaS3 \
EOS6nbWS7ZReiPMdMABoEmVBYanyTMb3GYRQGsTRMCYx9vijWoaS3 \
-j -d

  

和之前不同的是我们在最后加上了两个参数,-j表示输出json格式数据,-d表示不进行交易广播。因为没有广播,所以交易并不会上链。

{
  "expiration": "2020-04-29T08:27:24",
  "ref_block_num": 79,
  "ref_block_prefix": 199531063,
  "max_net_usage_words": 0,
  "max_cpu_usage_ms": 0,
  "delay_sec": 0,
  "context_free_actions": [],
  "actions": [{
      "account": "eosio",
      "name": "newaccount",
      "authorization": [{
          "actor": "eosio",
          "permission": "active"
        }
      ],
      "data": "0000000000ea305500000080a668323601000000010002fa026835dadff4e20d401c1d912a819dfcb3b08372a0feda23ad257e9c65b7580100000001000000010002fa026835dadff4e20d401c1d912a819dfcb3b08372a0feda23ad257e9c65b75801000000"
    }
  ],
  "transaction_extensions": [],
  "signatures": [
    "SIG_K1_K72sFmvGoPCYB9es4cfceuyzSj6fJqtVpnikG7v9vXssQHnRJHGnNSRcu1S4oV5prmASEfYyWRP9rst9HKjV7nNttysL3o"
  ],
  "context_free_data": []
}

  

我们来看下一个交易的基本结构。首先可以看到actions字段是一个数组集合,这就是为了支持同一交易中进行多个action操作,这个我下面会单独再说。我们来说说主要的字段:

expiration 该交易上链的有效期,过期未能上链便会返回交易过期的异常。
ref_block_num 引用区块号
ref_block_prefix 引用区块的前缀
delay_sec 延时执行时间(s)
actions 交易包含的行为集合
signatures 交易的签名集合

我们再来看action的基本结构:

account 账号名,即合约账号名
name 行为名称,也可以理解为智能合约的方法名
authorization 授权集合,调用这个action所要用到的账号权限
data 行为参数数据的打包数据

接下来我给大家看一个相对复杂的交易。

cleos -u "http://jungle2.cryptolions.io" \
system newaccount --stake-net '1 EOS' --stake-cpu '10 EOS' \
--buy-ram-kbytes 1000 eosastaldo11 eosastaldo33 \
EOS8h8YD7956jYf99BV6kBit5d9461xaxyTf9HPxmARcnTEnFivY8 \
EOS7DhW1StAhprCBwpAfgMpmHuN2H3V8t4B45tzQtEYckHRr5CASN \
-p eosastaldo11@active -p eosastaldo22@active \
-j -d

  

这里使用创建普通账号的方法,这里调用的是jungle测试网,并使用了两个账号来签名(这里只是为了构建一个复杂的交易,但是使用多账号签名其实也是有实际意义的,可以借用资源,这个我们稍后补充说明)

  "expiration": "2020-04-29T09:38:15",
  "ref_block_num": 50179,
  "ref_block_prefix": 686944513,
  "max_net_usage_words": 0,
  "max_cpu_usage_ms": 0,
  "delay_sec": 0,
  "context_free_actions": [],
  "actions": [{
      "account": "eosio",
      "name": "newaccount",
      "authorization": [{
          "actor": "eosastaldo11",
          "permission": "active"
        },{
          "actor": "eosastaldo22",
          "permission": "active"
        }
      ],
      "data": "10024dd1646c305530064dd1646c305501000000010003f4fe1f6168380331582f3c4dca57b5f9ce4098b999b44e0a9945ff216c2d55690100000001000000010003330272e86792b3b335277c64d9ea1e1988a192f734774df22012ac562b19b7d001000000"
    },{
      "account": "eosio",
      "name": "buyrambytes",
      "authorization": [{
          "actor": "eosastaldo11",
          "permission": "active"
        },{
          "actor": "eosastaldo22",
          "permission": "active"
        }
      ],
      "data": "10024dd1646c305530064dd1646c305500a00f00"
    },{
      "account": "eosio",
      "name": "delegatebw",
      "authorization": [{
          "actor": "eosastaldo11",
          "permission": "active"
        },{
          "actor": "eosastaldo22",
          "permission": "active"
        }
      ],
      "data": "10024dd1646c305530064dd1646c3055102700000000000004454f5300000000a08601000000000004454f530000000000"
    }
  ],
  "transaction_extensions": [],
  "signatures": [
    "SIG_K1_Kk9kasEiNqQyEvkwSUFidAgzZVcPJGifSULX48F7qiCmmnz3ucrg6fb9V5YCEkK73oGP44j26MeT96UxLPBo1auCLbqFEM",
    "SIG_K1_KhKTiKFK96hTnHRAzW69TTjFnrAh4FTCgHbfASoAFzauYwfNJ1jYmW4sa6AX57ihG94FbA1TKJZEYSUgNbzsJUq35dXJSf"
  ],
  "context_free_data": []
}

  

我们注意到有三个主要的不同,一个是actions里面有3个action,分别是newaccount、buyram和delegatebw,对应的是创建账号、购买内存和抵押资源。而每个action中的authorization也都有两个,正是我们指定签名的eosastaldo11@active和eosastaldo22@active。最后一个是signatures里面也有两个签名,对应了我们使用的两个账号权限的签名。

补充:上面提到了使用两个账号签名,这个功能其实可以有两个实际作用:

1 - EOS中在1.8以后支持了借用资源的功能,说白了就是当有多个action或者action中有多个authorization时,只扣减第一个账号的CPU和NET资源。而这个功能在CPU价格疯涨的现在,被普遍应用于为某些资源低的账号提供CPU和NET使用。
2 - 合约中可以进行多个账号的权限验证,只有用户同时拥有多个账号私钥时才可进行的操作。和多签功能不同的是,这个签名方式将可以在一个交易中完成对多个权限的验证,而多签主要应用在多个不同所属账号间的授权,且只能进行单账号权限的验证。

发起交易的流程

我们通过命令行获得的交易数据,其实是经过了很多步骤才获得的,我这里只简单说明下,细节和实现我们会在后面的深度剖析版块慢慢说明。

action打包数据

首先需要把所有action进行打包,怎么打包呢?获取这个action的合约账号的abi信息,然后将这个action的参数进行类型序列化,最后生成wasm格式的数据。也就是我们上面将交易结构中看到的类似于10024dd1646c305530064dd1646c305501000000010003f4fe1f6168380331582f3c4dca57b5f9ce4098b999b44e0a9945ff216c2d55690100000001000000010003330272e86792b3b335277c64d9ea1e1988a192f734774df22012ac562b19b7d001000000这样的数据。

获取区块信息

我们既然要上链,就要和区块关联起来,所以我们需要获取现在最新的区块号,并获得该区块号的前缀信息。这些都可以通过RPC接口获得,然后我们的交易上链需要设置一个过期时间(广播出去后要等到上链是有一定的时间差的,我们通过过期时间来控制交易的有效性)。

如果你这个交易还是一个延时交易(大部分交易都是即时发生并上链的,有时我们需要延时调用,比如在某个特定的时间执行的操作),那你还需要设置延时时间。

签名

交易要进行签名前,我们需要把交易打包生成wasm数据,并按照特定格式组装后再用私钥签名。

需要用哪些私钥进行签名呢,我们会将action中的authorization都取出来,通过RPC接口查询可以用于签名的公钥有哪些,然后我们和自己拥有的密钥对进行比对,就可以获得签名要使用的私钥了。

为了将交易数据和链关联,预签名数据里会用到chainid。将签名放入signatures字段。至此,我们的交易就准备好了。

广播

交易组装完后就要发到节点上,节点进行校验和执行后,会广播出去,由超级节点打包到区块中,再将区块广播出去,经过共识机制验证后最终达到不可逆,完成上链。

发起转账交易

我们现在来通过cleos tranfer命令进行一个转账。命令有几个核心参数。

-c,—contract TEXT Token合约的账号名,默认eosio.token
sender 发起转账的账号,同action中的from
recipient 接收转账的账号,同action中的to
amount 账号金额,”0.0000 EOS”格式,同action中的quantity
memo 备注,同action中memo

我们使用EOS testnet的环境,从我的账号xxsizdfracfg转10个TNT给ywndohtegtui。

cleos -u https://api.testnet.eos.io transfer xxsizdfracfg ywndohtegtui "10.0000 TNT" "for test, fishopark.com"

  

transfer

如果你要转的并不是系统代币(EOS主网的代币就是EOS),那你还需要指定-c参数,说明代币的合约账号。比如,我在EOS测试网上发行了一个TADO的代币,现在我要从ywndohtegtui转给xxsizdfracfg。

cleos -u https://api.testnet.eos.io transfer -c ywndohtegtui ywndohtegtui xxsizdfracfg "1.0000 TADO" "for test, fishopark.com"

  

transfer2

调用合约Action

我们知道转账其实也是一个action操作,cleos封装了这个常用操作,而创建新账号也是,cleos将这个有3个action的操作封装了。那么我们自己进行合约调用操作该怎么进行呢?

简单合约Action调用调用直接通过cleos push action命令调用,而复杂交易或者多Action调用的交易则需要通过cleos push action -d -j先获取各Action数据,然后手动拼装transaction后,通过cleos push transaction发起。

这里我们只介绍单Action的调用,多Action的调用会在后续介绍多签等内容是消息介绍。cleos push action命令有几个核心参数。

account 合约账号名
action action名称
data 参数,支持字符串数组和json格式。

我们调用一个Action需要先了解这个Action所在的合约名,Action的名字,已经参数的名称和类型,而这些大多都可以通过合约的Abi信息中获得。

假设我现在还是要调用EOS测试网上我发行的token合约的ywndohtegtui账号上的issue,那么:

account: ywndohtegtui
action: issue
data:

to: ywndohtegtui
quantity: 99.0000 TADO
memo: push action test, fishopark.com

因为官方标准Token合约中限制了发行只能发行给发行人,所以这里我们发行给ywndohtegtui。

#使用字符串数组格式
cleos -u https://api.testnet.eos.io push action ywndohtegtui issue '["ywndohtegtui","99.0000 TADO","push action test, fishopark.com"]' -p ywndohtegtui@active

#或者使用json数据格式
cleos -u https://api.testnet.eos.io push action ywndohtegtui issue '{"to":"ywndohtegtui","quantity":"99.0000 TADO","memo":"push action test, fishopark.com"}' -p ywndohtegtui@active

  

push_action

 
posted @ 2020-05-07 14:53  AstaldoChen  阅读(820)  评论(0编辑  收藏  举报