AIOU Chain Docs

AIOU Chain Docs

  • Docs
  • Languages icon中文
    • English

›Reference

Getting started

  • Overview
  • Quickstart

AIOU Design and Concepts

  • Account
  • Economic model

Smart Contract

  • Smart Contract Quick Start
  • AIOU Blockchain API
  • Update Contract
  • Generate Receipt in Smart Contract
  • Create IRC20 Token

Running AIOU node

  • Join AIOU Network
  • Become Servi Node

Reference

  • API
  • System Contract
  • Economic Contract
  • Token Contract
  • Gas Charge Table

AIOU Javascript SDK

  • AIOU
  • Blockchain
  • KeyPair
  • Transaction

AIOU Tech Internals

  • VM
  • Database
  • Network layer

API

/getNodeInfo


GET

概要: 获得节点的信息

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getNodeInfo

响应格式

一个成功响应的例子

200 OK

{
    "build_time": "20190329_164908+0800",
    "git_hash": "5d0d3917bae2afab2758c7fe0519b95981252901",
    "mode": "ModeNormal",
    "network": 
    {
        "id": "12D3KooWQ1Uh2tu9GLybc6PwwZHfKkCSFQ3hS9wFUD7mF3xW5KwC",
        "peer_count": 30
    },
    "code_version": "3.0.7",
    "server_time": "1554292230570963220"
}

字段类型描述
build_timestring构建可执行程序的时间
git_hashstring版本的git hash
modestring节点运行模式, ModeNormal - 正常模式,ModeSync - 同步块模式,ModeInit - 初始化模式
networkNetworkInfo network网络连接信息
code_versionstring代码版本号
server_timestring服务器当前时间戳,单位纳秒

NetworkInfo

字段类型描述
idstring本节点的ID
peer_countint32邻居节点的数量

/getChainInfo


GET

概要: 获得区块链的信息

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getChainInfo

响应格式

一个成功响应的例子

200 OK

{
    "net_name": "debugnet",
    "protocol_version": "1.0",
    "chain_id": 1024,
    "head_block": "16041",
    "head_block_hash": "DLJVtko6nQnAdvQ7y6dXHo3WMdG324yRLz8tPKk9tGHu",
    "lib_block": "16028",
    "lib_block_hash": "8apn7vCvQ6s9PFBzGfaXrvyL5eAaLNc4mEAgnTMoW8tC",
    "witness_list": ["AIOU2K9GKzVazBRLPTkZSCMcyMayKv7dWgdHD8uuWPzjfPdzj93x6J", "AIOU2YKPmRDGy5xLR7Gv65CN5nQ3vMmVhRjAsEM7Gj9xcB1LWgZUAd", "AIOU7E4T5rG9wjPZXDeM1zjhhWU3ZswtPQ1heeRUFUxntr65sYRBi"],
    "lib_witness_list": ["AIOU2K9GKzVazBRLPTkZSCMcyMayKv7dWgdHD8uuWPzjfPdzj93x6J", "AIOU2YKPmRDGy5xLR7Gv65CN5nQ3vMmVhRjAsEM7Gj9xcB1LWgZUAd", "AIOU7E4T5rG9wjPZXDeM1zjhhWU3ZswtPQ1heeRUFUxntr65sYRBi"],
    "pending_witness_list": ["AIOU2K9GKzVazBRLPTkZSCMcyMayKv7dWgdHD8uuWPzjfPdzj93x6J", "AIOU2YKPmRDGy5xLR7Gv65CN5nQ3vMmVhRjAsEM7Gj9xcB1LWgZUAd", "AIOU7E4T5rG9wjPZXDeM1zjhhWU3ZswtPQ1heeRUFUxntr65sYRBi"],
    "head_block_time": "1552917911507043000",
    "lib_block_time": "1552917911507043000"
}
字段类型描述
net_namestring网络名字,例如mainnet或testnet
protocol_versionstringaiou协议版本
chain_iduint32网络 ID
head_blockint64最新块的块号
head_block_hashstring最新块的hash
lib_blockint64不可逆块的高度
lib_block_hashstring不可逆块的hash
witness_listrepeated string当前造块节点的pubkey列表
lib_witness_listrepeated string不可逆块时刻的造块节点的pubkey列表
pending_witness_listrepeated string下一轮造块节点的pubkey列表
head_block_timeint64最新块的区块时间
lib_block_timeint64不可逆块的区块时间

/getGasRatio


GET

概要: 获取当前上链交易的 gas 倍率信息,方便用户合理设置自己交易的 gas 倍率。
建议使用比 lowest_gas_ratio 稍高的 gas ratio 值,来保证交易尽快上链。

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getGasRatio

响应格式

一个成功响应的例子

200 OK

{
    "lowest_gas_ratio": 1.5,
    "median_gas_ratio": 1.76
}
字段类型描述
lowest_gas_ratiodouble最新的 block 中的打包成功的所有合约的最低 gas ratio
median_gas_ratiodouble最新的 block 中的打包成功的所有合约的中位数 gas ratio

/getRAMInfo


GET

概要: 获取当前区块链的RAM信息,包括用量和价格。

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getRAMInfo

响应格式

一个成功响应的例子

200 OK

{
    "available_ram": "96207067431",
    "buy_price": 0.04227129323234719,
    "sell_price": 0.00014551844642842057,
    "total_ram": "137438953472",
    "used_ram": "41231886041"
}
字段类型描述
available_ramint64可用 RAM 数量,以 byte 为单位
used_ramint64已经出售的 RAM 数量,以 byte 为单位
total_ramint64系统总计 RAM 数量,以 byte 为单位
buy_pricedouble此刻购买 RAM 的价格,以 AIOU/byte 为单位,已经包含手续费
sell_pricedouble此刻购买 RAM 的价格,以 AIOU/byte 为单位

/getTxByHash/{hash}


GET

概要: 通过交易hash获取交易数据

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getTxByHash/6eGkZoXPQtYXdh7dBSXe2L1ckUCDj4egRn4fXtS2ACnR
字段类型描述
hashstring交易的hash

响应格式

一个成功响应的例子

200 OK

{
    "status": "IRREVERSIBLE",
    "transaction": {
        "hash": "6eGkZoXPQtYXdh7dBSXe2L1ckUCDj4egRn4fXtS2ACnR",
        "time": "1544269519362042000",
        "expiration": "1544279519362041000",
        "gas_ratio": 1,
        "gas_limit": 50000,
        "delay": "0",
        "chain_id": 1024,
        "actions": [{
            "contract": "ContractTBv8ZDKUhTyeS4MomdcHRrXnJMELa5usSMHP6QJntFQ",
            "action_name": "transfer",
            "data": "[\"admin\",\"i1544269477\",1]"
        }],
        "signers": [],
        "publisher": "admin",
        "referred_tx": "",
        "amount_limit": [],
        "tx_receipt": null
    },
    "block_number": "4047298"
}
字段类型描述
statusenumPENDING-交易在缓存中, PACKED - 交易在非不可逆块中,IRREVERSIBLE - 交易在不可逆的块中
transactionTransaction transaction交易数据
block_numberstring交易所在的区块号

Transaction

字段类型描述
hashstring交易的hash
timeint64交易的时间戳
expirationint64交易的过期时间
gas_ratiodoubleGas费率,建议设置成1(1.00 ~ 100.00),可以通过提高费率来让交易更容易被打包
gas_limitdoubleGas上限,执行交易所消耗的Gas不会超过这个上限
delayint64延迟时间,交易会在延迟时间之后被执行,单位纳秒
chain_iduint32网络 ID
actionsrepeated Action交易的最小执行单元
signersrepeated string交易的签名列表
publisherstring交易提交者,承担交易的执行费用
referred_txstring交易生成依赖,用于延迟交易
amount_limitrepeated AmountLimit用户可以设置的花费token的限制, 如 {"aiou": 100} 即本次交易对于每个签名者花费aiou不超过100
tx_receiptTxReceipt tx_receipt交易Action的receipt

Action

字段类型描述
contractstring调用的合约名字
action_namestring调用的合约函数名
datastring调用的具体参数。把所有的参数生成 array 后再用 json 序列化,一般形如 '["a_string",13]'

AmountLimit

字段类型描述
tokenstringtoken 名字
valuedouble这种 token 对应的限额

TxReceipt

字段类型描述
tx_hashstring交易的hash
gas_usagedouble交易执行的Gas消耗
ram_usagemap<string, int64>交易的RAM消耗,map-key - 账户名,map-value - 使用RAM量
status_codeenum交易执行状态,SUCCESS - 成功,GAS_RUN_OUT - Gas不足,BALANCE_NOT_ENOUGH - 余额不足,WRONG_PARAMETER - 错误参数, RUNTIME_ERROR - 运行时错误, TIMEOUT - 超时, WRONG_TX_FORMAT - 交易格式错误, DUPLICATE_SET_CODE - 重复设置set code, UNKNOWN_ERROR - 未知错误
messagestringstatus_code的详细描述信息
returnsrepeated string每个Action的返回值
receiptsrepeated Receiptevent功能使用

Receipt

字段类型描述
func_namestringabi函数的名字
contentstring内容

/getTxReceiptByTxHash/{hash}


GET

概要: 通过交易hash获取交易receipt数据

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getTxReceiptByTxHash/6eGkZoXPQtYXdh7dBSXe2L1ckUCDj4egRn4fXtS2ACnR
字段类型描述
hashstringreceipt的hash

响应格式

一个成功响应的例子

200 OK

{
    "tx_hash": "6eGkZoXPQtYXdh7dBSXe2L1ckUCDj4egRn4fXtS2ACnR",
    "gas_usage": 6633,
    "ram_usage": {
        "admin": "0",
        "issue.aiou": "0"
    },
    "status_code": "SUCCESS",
    "message": "",
    "returns": ["[\"\"]"],
    "receipts": [{
        "func_name": "token.aiou/transfer",
        "content": "[\"aiou\",\"admin\",\"i1544269477\",\"1\",\"\"]"
    }]
}
字段类型描述
TxReceipt交易的receipt

/getBlockByHash/{hash}/{complete}


GET

概要: 通过block hash获取block的数据

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getBlockByHash/4c9GHyGLi6hUqB4d6zGFcywycYKucsmWsbgvhPe31GaY/false
字段类型描述
hashstringblock hash
completebooltrue - 显示block中的交易, false - 不显示block中交易详情

响应格式

一个成功响应的例子

200 OK

{
    "status": "IRREVERSIBLE",
    "block": {
        "hash": "4c9GHyGLi6hUqB4d6zGFcywycYKucsmWsbgvhPe31GaY",
        "version": "0",
        "parent_hash": "G4njPLnYskU4DcuTz5CwpLPETcfH6yN78V8emge8t21f",
        "tx_merkle_hash": "HHKAG2D7Kon2on5SqV66ZsfdNk9Wus8yhWqdTb86wgPJ",
        "tx_receipt_merkle_hash": "FXr8Mf7hr568MP23BFWJiBUej2xSj3M7416WAKJpswzx",
        "number": "2",
        "witness": "AIOU2YKPmRDGy5xLR7Gv65CN5nQ3vMmVhRjAsEM7Gj9xcB1LWgZUAd",
        "time": "1544262978309033000",
        "gas_usage": 0,
        "tx_count": "1",
        "info": null,
        "transactions": []
    }
}
字段类型描述
statusenumPENDIND - block在缓存中,IRREVERSIBLE - block不可逆
blockBlock blockblock结构体

Block

字段类型描述
hashstringblock hash
versionint64bock版本号
parent_hashstringblock父块的hash
tx_merkle_hashstring所有交易的merkle tree hash
tx_receipt_merkle_hashstring所有receipt的merkle tree hash
numberint64block号
witnessstringblock生产者的pubkey
timeint64block生产时间
gas_usagedoubleblock中交易消耗的总Gas
tx_countint64block中交易总数
infoInfo info保留字段
transactionsrepeated Transaction交易字段

Info

字段类型描述
modeint32并发的模式,0 - 不并发, 1 - 并发
threadint32交易并发执行的线程数量
batch_indexrepeated int32交易的索引

/getBlockByNumber/{number}/{complete}


GET

概要: 通过block号获取block的数据

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getBlockByNumber/3/false
字段类型描述
numberint64block号
completebooltrue - 显示block中的交易, false - 不显示block中交易详情

响应格式

一个成功响应的例子

200 OK

{
    "status": "IRREVERSIBLE",
    "block": {
        "hash": "HPZyoPQ44vsyLDRspjgrySyHnpuiGwckPx8uNtHZugJW",
        "version": "0",
        "parent_hash": "4c9GHyGLi6hUqB4d6zGFcywycYKucsmWsbgvhPe31GaY",
        "tx_merkle_hash": "HHKAG2D7Kon2on5SqV66ZsfdNk9Wus8yhWqdTb86wgPJ",
        "tx_receipt_merkle_hash": "62pESNUGDVsH4B1BCymJvmjGxPu5bb4R3u4x45K9Ybdq",
        "number": "3",
        "witness": "AIOU2YKPmRDGy5xLR7Gv65CN5nQ3vMmVhRjAsEM7Gj9xcB1LWgZUAd",
        "time": "1544262978609003000",
        "gas_usage": 0,
        "tx_count": "1",
        "info": null,
        "transactions": []
    }
}
字段类型描述
statusenumPENDIND - block在缓存中,IRREVERSIBLE - block不可逆
blockBlock blockblock结构体

/getAccount/{name}/{by_longest_chain}


GET

概要: 获取账号信息

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getAccount/admin/true
字段类型描述
namestring账户名
by_longest_chainbooltrue - 从最长链得到数据,false - 从不可逆块得到数据

响应格式

一个成功响应的例子

200 OK

{
    "name": "admin",
    "balance": 982678652,
    "gas_info": {
        "current_total": 53102598634,
        "transferable_gas": 60000,
        "pledge_gas": 53102538634,
        "increase_speed": 330011,
        "limit": 90003000000,
        "pledged_info": [{
            "pledger": "admin",
            "amount": 3000100
        }]
    },
    "ram_info": {
        "available": "99000"
    },
    "permissions": {
        "active": {
            "name": "active",
            "group_names": [],
            "items": [{
                "id": "AIOU2mCzj85xkSvMf1eoGtrexQcwE6gK8z5xr6Kc48DwxXPCqQJva4",
                "is_key_pair": true,
                "weight": "1",
                "permission": ""
            }],
            "threshold": "1"
        },
        "owner": {
            "name": "owner",
            "group_names": [],
            "items": [{
                "id": "AIOU2mCzj85xkSvMf1eoGtrexQcwE6gK8z5xr6Kc48DwxXPCqQJva4",
                "is_key_pair": true,
                "weight": "1",
                "permission": ""
            }],
            "threshold": "1"
        }
    },
    "groups": {},
    "frozen_balances": [],
    "vote_infos": []
}
字段类型描述
namestring账户名字
balancedouble余额
gas_infoGasInfo gas_infoGas信息
ram_infoRAMInfoRam信息
permissionsmap<string, Permission>权限
groupsmap<string, Group>权限组
frozen_balancesrepeated FrozenBalance冻结余额信息
vote_infosrepeated VoteInfo投票信息

GasInfo

字段类型描述
current_totaldouble当前Gas总量
transferable_gasdouble可以流通的Gas量
pledge_gasdouble质押获得的Gas
increase_speeddouble每秒增加的Gas
limitdouble质押Token获得的Gas上限
pledged_inforepeated PledgeInfo本账号帮其他账号质押的信息

PledgeInfo

字段类型描述
pledgerstring接受本账号质押的账号
amountdouble本账号给 pledger 质押的金额

RAMInfo

字段类型描述
availableint64可用的RAM bytes
usedint64已使用的RAM bytes
totalint64总共RAM bytes

Permission

字段类型描述
namestring权限名字
group_namesrepeated string权限组名字
itemsrepeated Item权限信息
thresholdint64权限阈值

Item

字段类型描述
idstring权限名字或者key pair id
is_key_pairbooltrue - id是key pair, false - id为权限名字
weightint64权限权重
permissionstring权限

Group

字段类型描述
namestring组名字
itemsrepeated Item权限组信息

FrozenBalance

字段类型描述
amountdouble金额
timeint64解冻时间

VoteInfo

字段类型描述
optionstring候选人
votesstring投票数
cleared_votesstring被清零投票数

/getTokenBalance/{account}/{token}/{by_longest_chain}


GET

概要: 获取账号指定代币的余额

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getTokenBalance/admin/aiou/true
字段类型描述
accountstring账号名
tokenstring代币名字
by_longest_chainbooltrue - 从最长链得到数据,false - 从不可逆块得到数据

响应格式

一个成功响应的例子

200 OK

{
    "balance": 982678652,
    "frozen_balances": []
}
字段类型描述
balancedouble余额
frozen_balancesrepeated FrozenBalance冻结信息

/getContract/{id}/{by_longest_chain}


GET

概要: 通过合约ID获取合约数据

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getContract/base.aiou/true
字段类型描述
idstring合约的ID
by_longest_chainbooltrue - 从最长链得到数据,false - 从不可逆块得到数据

响应格式

一个成功响应的例子

200 OK

{
    "id": "base.aiou",
    "code": "const producerPermission = 'active';\nconst voteStatInterval = 200;\nclass Base {\n    constructor() {\n    }\n    init() {\n        _AIOUInstruction_counter.incr(12);this._put('execBlockNumber', 0);\n    }\n    InitAdmin(adminID) {\n        _AIOUInstruction_counter.incr(4);const bn = block.number;\n        if (_AIOUInstruction_counter.incr(8),_AIOUBinaryOp(bn, 0, '!==')) {\n            _AIOUInstruction_counter.incr(14);throw new Error('init out of genesis block');\n        }\n        _AIOUInstruction_counter.incr(12);this._put('adminID', adminID);\n    }\n    can_update(data) {\n        _AIOUInstruction_counter.incr(12);const admin = this._get('adminID');\n        _AIOUInstruction_counter.incr(12);this._requireAuth(admin, producerPermission);\n        return true;\n    }\n    _requireAuth(account, permission) {\n        _AIOUInstruction_counter.incr(12);const ret = BlockChain.requireAuth(account, permission);\n        if (_AIOUInstruction_counter.incr(8),_AIOUBinaryOp(ret, true, '!==')) {\n            _AIOUInstruction_counter.incr(22);throw new Error(_AIOUBinaryOp('require auth failed. ret = ', ret, '+'));\n        }\n    }\n    _get(k) {\n        _AIOUInstruction_counter.incr(12);const val = storage.get(k);\n        if (_AIOUInstruction_counter.incr(8),_AIOUBinaryOp(val, '', '===')) {\n            return null;\n        }\n        _AIOUInstruction_counter.incr(12);return JSON.parse(val);\n    }\n    _put(k, v) {\n        _AIOUInstruction_counter.incr(24);storage.put(k, JSON.stringify(v));\n    }\n    _vote() {\n        _AIOUInstruction_counter.incr(12);BlockChain.callWithAuth('vote_producer.aiou', 'Stat', `[]`);\n    }\n    _bonus(data) {\n        _AIOUInstruction_counter.incr(24);BlockChain.callWithAuth('bonus.aiou', 'IssueContribute', JSON.stringify([data]));\n    }\n    _saveBlockInfo() {\n        _AIOUInstruction_counter.incr(12);let json = storage.get('current_block_info');\n        _AIOUInstruction_counter.incr(36);storage.put(_AIOUBinaryOp('chain_info_', block.parentHash, '+'), JSON.stringify(json));\n        _AIOUInstruction_counter.incr(24);storage.put('current_block_info', JSON.stringify(block));\n    }\n    Exec(data) {\n        _AIOUInstruction_counter.incr(12);this._saveBlockInfo();\n        _AIOUInstruction_counter.incr(4);const bn = block.number;\n        _AIOUInstruction_counter.incr(12);const execBlockNumber = this._get('execBlockNumber');\n        if (_AIOUInstruction_counter.incr(8),_AIOUBinaryOp(bn, execBlockNumber, '===')) {\n            return true;\n        }\n        _AIOUInstruction_counter.incr(12);this._put('execBlockNumber', bn);\n        if (_AIOUInstruction_counter.incr(16),_AIOUBinaryOp(_AIOUBinaryOp(bn, voteStatInterval, '%'), 0, '===')) {\n            _AIOUInstruction_counter.incr(12);this._vote();\n        }\n        _AIOUInstruction_counter.incr(12);this._bonus(data);\n    }\n}\n_AIOUInstruction_counter.incr(7);module.exports = Base;",
    "language": "javascript",
    "version": "1.0.0",
    "abis": [{
        "name": "Exec",
        "args": ["json"],
        "amount_limit": []
    }, {
        "name": "can_update",
        "args": ["string"],
        "amount_limit": []
    }, {
        "name": "InitAdmin",
        "args": ["string"],
        "amount_limit": []
    }, {
        "name": "init",
        "args": [],
        "amount_limit": []
    }]
}
字段类型描述
idstring合约的id
codestring合约的代码
languagestring合约语言
versionstring合约版本
abisrepeated ABI合约的abis

ABI

字段类型描述
namestring接口的名字
argsrepeated string接口的参数
amount_limitrepeated AmountLimit金额限制

/getContractStorage


POST

概要: 获取合约的存储数据

请求格式

一个请求格式的例子

curl -X POST http://127.0.0.1:30001/getContractStorage -d '{"id":"token.aiou","key":"TIaiou","field":"decimal","by_longest_chain":true}'
字段类型描述
idstring智能合约的ID
keystringStateDB的key
fieldstring从StateDB中得到值,如果StateDB[key]是一个map,那么需要设置field(可以得到StateDB[key][field]的值)
by_longest_chainbooltrue - 从最长链得到数据,false - 从不可逆块得到数据

响应格式

一个成功响应的例子

200 OK
{"data":"8","block_hash":"GFfWHwe9cdw5aHaTDExFm2DBzaV9wdgybTQpHsQsbaKS","block_number":"38194"}
字段类型描述
datastring存储的数据
block_hashstring这个数据来自的区块的 hash
block_numberstring这个数据来自的区块的编号

/getContractStorageFields


POST

概要: 获取合约存储中 map 的 key 列表,最多返回 256 条。注意:开发者不应该依赖此接口获取合约中一个 map 的所有 key,若有这样的需求,需要自己维护所有的 key。

请求格式

一个请求格式的例子

curl -X POST http://127.0.0.1:30001/getContractStorageFields -d '{"id":"token.aiou","key":"TIaiou","by_longest_chain":true}'
字段类型描述
idstring智能合约的ID
keystructStateDB的key
by_longest_chainbooltrue - 从最长链得到数据,false - 从不可逆块得到数据

响应格式

一个成功响应的例子

200 OK
{
    "fields": ["issuer","totalSupply","supply","canTransfer","onlyIssuerCanTransfer","defaultRate","decimal","fullName"]
}

/getBatchContractStorage


POST

概要: 批量获取合约的存储数据

请求格式

一个请求格式的例子

curl -X POST http://127.0.0.1:30001/getBatchContractStorage -d '{"id":"token.aiou","key_fields":[{"field":"supply","key":"TIaiou"}, {"field":"decimal","key":"TIaiou"}, {"field":"xxxx","key":"xxxx"}],"by_longest_chain":true}'
字段类型描述
idstring智能合约的ID
key_fieldsrepeated KeyField要批量查询的 key-field,返回值的顺序与传入顺序一致
by_longest_chainbooltrue - 从最长链得到数据,false - 从不可逆块得到数据

KeyField

字段类型描述
keystringStateDB的key
fieldstring从StateDB中得到值,如果StateDB[key]是一个map,那么需要设置field(可以得到StateDB[key][field]的值)

响应格式

一个成功响应的例子

200 OK
{"datas":["2100000000000000000","8","null"],"block_hash":"3Tv3QUPRhhAj7L3j6DCEtkKycXtkeFgAMU3zZU3HA6Qr","block_number":"39123"}
字段类型描述
datasrepeated string存储的数据,返回顺序与传入顺序一致
block_hashstring这个数据来自的区块的 hash
block_numberstring这个数据来自的区块的编号

/sendTx


POST

概要:
把交易发到节点上。
节点收到这个交易后,首先会做基本检查,如果不通过则返回错误,如果通过,则将本交易加入交易池中,并且返回交易的 Hash。
用户在一段时间之后,可以使用这个收到的 Hash 通过 getTxByHash 或 getTxReceiptByTxHash 接口来查询本交易的状态,查看是否执行成功。
注意:
此接口需要先计算交易的哈希和签名,直接调用较为复杂。
开发者可以使用 Javascript SDK 中的函数接口发送交易。

请求参数

字段类型描述
timeint64交易产生时间。UnixEpoch起始,单位纳秒
expirationint64交易过期时间。UnixEpoch起始,单位纳秒。如果造块节点在过期时间之后才收到交易,则不会执行
gas_ratiodoubleGAS倍率。本交易按照默认GAS的 gas_ratio 倍来支付费用。倍率越高,越会被优先执行。合理的取值范围是 [1.0, 100.0]
gas_limitdouble交易最大允许的GAS,最少设置为 50000
delayint64延迟交易中使用。延迟执行的纳秒数。非延迟交易设为0
chain_iduint32网络 ID
actionsrepeated Action交易中的具体调用
amount_limitrepeated AmountLimit交易的 token 限制。可以指定多种 token 和对应的数量限制。如果交易超过这些限制,则执行失败
publisherstring交易发送者的 ID
publisher_sigsrepeated Signaturepublisher 的签名,签名过程如下。publisher 可以提供多个签名,对应多种不同的权限。可以参考权限系统的文档
signersrepeated string除 publisher 之外的签名人 ID。可以为空
signaturesrepeated Signaturesigners 的签名。每个 signer 可以有一个或多个签名,因此长度不低于 signers 长度

Signature

字段类型描述
algorithmstring加密算法。目前仅支持 "ED25519" 和 "SECP256K1"
signaturestring合约序列化后使用 sha3 做 hash,之后使用私钥做签名。Base64 编码。细节见对应文档
public_keystring本签名使用的公钥。Base64 编码

响应格式

字段类型描述
hashstring交易的 hash
pre_tx_receiptTxReceipt被RPC节点预先执行的交易的receipt,需要 RPC 节点打开预执行开关才会返回这个字段

交易签名

交易的签名过程分为三步:将交易结构体转为字节数组;使用 sha3 算法对字节数组计算哈希;使用私钥对哈希进行签名。

  • 交易结构体转字节数组

    交易结构体转字节数组算法为,将交易的每个字段按照声明顺序转成字节数组,然后在不定长类型(比如 string 和结构体)前加上长度,并拼接。各种字段类型转成字节数组的方式见下表:

    字段类型转换方法示例
    int按照大端序转成字节数组如 int64(1023) 对应的字节数组为 [0 0 0 0 0 0 3 255]
    string将字符串中每个字符对应的字节进行拼接并在前面加上长度如 "aiou" 对应的字节数组为 [0 0 0 4 105 111 115 116]
    数组将数组的每个元素转为字节数组并拼接,再在其前面加上数组的长度如 ["aiou" "aiou"] 对应的字节数组为 [0 0 0 2 0 0 0 4 105 111 115 116 0 0 0 4 105 111 115 116]
    map将字典的每对 key:value 分别转成字节数组并拼接, 然后按照 key 升序排列后拼接每一对,再在其前面加上 map 的长度如 ["b":"aiou", "a":"aiou"] 对应的字节数组为 [0 0 0 2 0 0 0 1 97 0 0 0 4 105 111 115 116 0 0 0 1 98 0 0 0 4 105 111 115 116]

    交易字段声明顺序为 "time"、"expiration"、"gas_ratio"、"gas_limit"、 "delay"、"chain_id"、"reserved"、"signers"、"actions"、"amount_limit"、"signatures",所以交易结构体转字节数组伪代码为:

    func TxToBytes(t transaction) []byte {
        return Int64ToBytes(t.time) + Int64ToBytes(t. expiration) + 
            Int64ToBytes(int64(t.gas_ratio * 100)) + Int64ToBytes(int64(t.gas_limit * 100)) +     // 注意 gas_ratio 和 gas_limit 需要乘以 100 并转成 int64
            Int64ToBytes(t.delay) + Int32ToBytes(t.chain_id) + 
            BytesToBytes(t.reserved) + // reserved 为预留字段,只需要在序列化的时候写入空字节数组即可,RPC 请求参数不需要带上此字段
            ArrayToBytes(t.signers) + ArrayToBytes(t.actions)  +
            ArrayToBytes(t.amount_limit) + ArrayToBytes(t.signatures)
    }
    

    golang 的实现可参考 go-aiou。 javascript 的实现可参考 aiou.js。

  • 使用 sha3 算法对字节数组计算哈希

    需要利用各个语言对应的 sha3 库对上一步的结果计算哈希,得到哈希的字节数组。

  • 使用私钥对哈希进行签名

    aiou 支持两种非对称加密算法:"Ed25519" 和 "Secp256k1"。两种算法签名的过程一样:先生成公私钥对,然后使用私钥对上一步的哈希字节数组进行签名。
    publisher_sigs 签名的私钥必须跟交易字段中的 "publisher" 账户对应,signatures 签名的私钥必须跟交易字段中的 "signers" 账户对应。signatures 用于多重签名,不是必需的,但 publisher_sigs 签名必须要有。交易执行花费的 gas 会从 publisher 账户扣除。

请求示例

假设账户 testaccount 要发送一笔交易,给 anothertest 账户转账 100 aiou。

  • 构建交易

    {
        "time": 1544709662543340000,
        "expiration": 1544709692318715000,
        "gas_ratio": 1,
        "gas_limit": 500000,
        "delay": 0,
        "chain_id": 1024,
        "signers": [],
        "actions": [
            {
                "contract": "token.aiou",
                "action_name": "transfer",
                "data": "[\"aiou\", \"testaccount\", \"anothertest\", \"100\", \"this is an example transfer\"]",
            },
        ],
        "amount_limit": [
            {
                "token": "*",
                "value": "unlimited",
            },
        ],
        "signatures": [],
    }
    
  • 计算哈希

    利用上述算法序列化后并 sha3 后,得到哈希值 "/gB8TJQibGI7Kem1v4vJPcJ7vHP48GuShYfd/7NhZ3w="。

  • 计算签名

    假设 testaccount 账户的公私钥算法为 ED25519,公钥为 "lDS+SdM+aiVHbDyXapvrsgyKxFg9mJuHWPZb/INBRWY=",私钥为 "gkpobuI3gbFGstgfdymLBQAGR67ulguDzNmLXEJSWaGUNL5J0z5qJUdsPJdqm+uyDIrEWD2Ym4dY9lv8g0FFZg==",利用私钥对上一步的哈希签名,得到 "/K1HM0OEbfJ4+D3BmalpLmb03WS7BeCz4nVHBNbDrx3/A31aN2RJNxyEKhv+VSoWctfevDNRnL1kadRVxSt8CA=="

  • 发送交易

    现在完整的交易请求参数为:

    {
        "time": 1544709662543340000,
        "expiration": 1544709692318715000,
        "gas_ratio": 1,
        "gas_limit": 500000,
        "delay": 0,
        "chain_id": 1024,
        "signers": [],
        "actions": [
            {
                "contract": "token.aiou",
                "action_name": "transfer",
                "data": "[\"aiou\", \"testaccount\", \"anothertest\", \"100\", \"this is an example transfer\"]",
            },
        ],
        "amount_limit": [
            {
                "token": "*",
                "value": "unlimited",
            },
        ],
        "signatures": [],
        "publisher": "testaccount",
        "publisher_sigs": [
            {
                "algorithm": "ED25519",
                "public_key": "lDS+SdM+aiVHbDyXapvrsgyKxFg9mJuHWPZb/INBRWY=",
                "signature": "/K1HM0OEbfJ4+D3BmalpLmb03WS7BeCz4nVHBNbDrx3/A31aN2RJNxyEKhv+VSoWctfevDNRnL1kadRVxSt8CA==",
            },
        ],
    }
    

    对上述结构进行 json 序列化后,发送如下 rpc 请求即可:

    curl -X POST http://127.0.0.1:30001/sendTx -d '{"actions":[{"action_name":"transfer","contract":"token.aiou","data":"[\"aiou\", \"testaccount\", \"anothertest\", \"100\", \"this is an example transfer\"]"}],"amount_limit":[{"token":"*","value":"unlimited"}],"delay":0,"chain_id":1024, "expiration": 1544709692318715000,"gas_limit":500000,"gas_ratio":1,"publisher":"testaccount","publisher_sigs":[{"algorithm":"ED25519","public_key":"lDS+SdM+aiVHbDyXapvrsgyKxFg9mJuHWPZb/INBRWY=","signature":"/K1HM0OEbfJ4+D3BmalpLmb03WS7BeCz4nVHBNbDrx3/A31aN2RJNxyEKhv+VSoWctfevDNRnL1kadRVxSt8CA=="}],"signatures":[],"signers":[],"time": 1544709662543340000}'
    

/execTx


POST

概要:
把交易发到节点,立刻执行,但是不会被上链共识,也不会被持久化。
本接口可以用来在测试合约的执行结果是否符合预期。当然,由于调用时间不同,execTx 的行为不能保证和正式链上执行完全一致。

请求格式

本接口请求格式和 /sendTx 相同。

响应格式

本接口响应格式和 /getTxReceiptByTxHash 相同。

/subscribe


POST

概要: 订阅事件,包括智能合约中触发的事件和交易执行完的事件。

请求格式

一个请求格式的例子

curl -X POST http://127.0.0.1:30001/subscribe -d '{"topics":["CONTRACT_RECEIPT"], "filter":{"contract_id":"token.aiou"}}'
字段类型描述
topicsrepeated enum订阅的事件主题,枚举类型有两种值,CONTRACT_EVENT-合约中触发的事件, CONTRACT_RECEIPT-交易执行完的事件
filterFilter收到的事件会按照 filter 中的字段过滤,若不传这一字段,则会收到所有 topics 中的事件数据

Filter

字段类型描述
contract_idstring智能合约的 id

响应格式

一个成功响应的例子

{"result":{"event":{"topic":"CONTRACT_RECEIPT","data":"[\"contribute\",\"producer00001\",\"900\"]","time":"1545646637413936000"}}}
{"result":{"event":{"topic":"CONTRACT_RECEIPT","data":"[\"contribute\",\"producer00001\",\"900\"]","time":"1545646637711757000"}}}
{"result":{"event":{"topic":"CONTRACT_RECEIPT","data":"[\"contribute\",\"producer00001\",\"900\"]","time":"1545646638013188000"}}}
{"result":{"event":{"topic":"CONTRACT_RECEIPT","data":"[\"contribute\",\"producer00001\",\"900\"]","time":"1545646638317840000"}}}
...
字段类型描述
topicenum事件的主题,CONTRACT_EVENT-合约中触发的事件, CONTRACT_RECEIPT-交易执行完的事件
datastring事件数据
timeint64事件的时间戳

/getCandidateBonus/{name}/{by_longest_chain}


GET

概要: 获取节点可领取的投票收益

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getCandidateBonus/erebus/1
字段类型描述
namestring节点账户名
by_longest_chainbooltrue - 从最长链得到数据,false - 从不可逆块得到数据

响应格式

一个成功响应的例子

200 OK
{
    "bonus": 111866.61819617149
}
字段类型描述
bonusdouble可领取的投票收益

/getVoterBonus/{name}/{by_longest_chain}


GET

概要: 获取投票者可领取的投票收益

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getVoterBonus/admin/1
字段类型描述
namestring投票者账户名
by_longest_chainbooltrue - 从最长链得到数据,false - 从不可逆块得到数据

响应格式

一个成功响应的例子

200 OK
{
    "bonus": 94875.58356478,
    "detail":
    {
        "dapppub": 15414.37339835,
        "aiouamerica": 17212.96477434,
        "laomao": 9895.73931972,
        "metanyx": 29877.55014659,
        "sutler": 20924.99488913,
        "tokenpocket": 1549.96103665
    }
}
字段类型描述
bonusdouble可领取的总投票收益
detailmap<string, double>从每个候选人得到的收益

/getTokenInfo/{symbol}/{by_longest_chain}


GET

概要: 获取 token 信息

请求格式

一个请求格式的例子

curl http://127.0.0.1:30001/getTokenInfo/aiou/1
字段类型描述
symbolstringtoken 名字
by_longest_chainbooltrue - 从最长链得到数据,false - 从不可逆块得到数据

响应格式

一个成功响应的例子

200 OK
{
    "symbol": "aiou",
    "full_name": "aiou",
    "issuer": "issue.aiou",
    "total_supply": "9000000000000000000",
    "current_supply": "2100000000000000000",
    "decimal": 8,
    "can_transfer": true,
    "only_issuer_can_transfer": false,
    "total_supply_float": 90000000000,
    "current_supply_float": 21000000000
}
字段类型描述
symbolstringtoken 名字
full_namestringtoken 全称
issuerstringtoken 发行人
total_supplystringtoken 总发行量,其值等于 total_supply_float 乘以 decimal
current_supplystringtoken 当前发行量,其值等于 current_supply_float 乘以 decimal
total_supply_floatdoubletoken 总发行量
current_supply_floatdoubletoken 当前发行量
decimalinttoken 小数位
can_transferbooltoken 能否进行转账
only_issuer_can_transferbool是否只能由代币发行者转账
← Become Servi NodeSystem Contract →
  • /getNodeInfo
    • 请求格式
    • 响应格式
    • NetworkInfo
  • /getChainInfo
    • 请求格式
    • 响应格式
  • /getGasRatio
    • 请求格式
    • 响应格式
  • /getRAMInfo
    • 请求格式
    • 响应格式
  • /getTxByHash/{hash}
    • 请求格式
    • 响应格式
    • Transaction
    • Action
    • AmountLimit
    • TxReceipt
    • Receipt
  • /getTxReceiptByTxHash/{hash}
    • 请求格式
    • 响应格式
  • /getBlockByHash/{hash}/{complete}
    • 请求格式
    • 响应格式
    • Block
    • Info
  • /getBlockByNumber/{number}/{complete}
    • 请求格式
    • 响应格式
  • /getAccount/{name}/{by_longest_chain}
    • 请求格式
    • 响应格式
    • GasInfo
    • PledgeInfo
    • RAMInfo
    • Permission
    • Item
    • Group
    • FrozenBalance
    • VoteInfo
  • /getTokenBalance/{account}/{token}/{by_longest_chain}
    • 请求格式
    • 响应格式
  • /getContract/{id}/{by_longest_chain}
    • 请求格式
    • 响应格式
    • ABI
  • /getContractStorage
    • 请求格式
    • 响应格式
  • /getContractStorageFields
    • 请求格式
    • 响应格式
  • /getBatchContractStorage
    • 请求格式
    • KeyField
    • 响应格式
  • /sendTx
    • 请求参数
    • Signature
    • 响应格式
    • 交易签名
    • 请求示例
  • /execTx
    • 请求格式
    • 响应格式
  • /subscribe
    • 请求格式
    • Filter
    • 响应格式
  • /getCandidateBonus/{name}/{by_longest_chain}
    • 请求格式
    • 响应格式
  • /getVoterBonus/{name}/{by_longest_chain}
    • 请求格式
    • 响应格式
  • /getTokenInfo/{symbol}/{by_longest_chain}
    • 请求格式
    • 响应格式
AIOU Chain Docs
Community
BlogGitHubStar
Facebook Open Source
Copyright © 2021 Your Name or Your Company Name