跳转至

关联交易

原文:https://docs.elrond.com/developers/relayed-transactions

中继交易(或元交易)是由所谓的中继者付费的交易。换句话说,如果中继者愿意为交互付费,与智能合约交互的地址不一定要有任何 EGLD 来付费。

更多细节和规格可以在Elrond规格上找到。

转发交易类型

目前,有两个版本的中继交易:v1 和 v2。最后,它们都有相同的效果,但 v2 在气体使用方面进行了优化,这是我们的推荐。

转述交易版本 1

中继交易版本 1 依赖于将内部交易 JSON 序列化并作为参数提供给relayedTx协议函数。

它看起来像是:

RelayedV1Transaction {
 Sender: <Relayer address>
 Receiver: <Address that signed the inner transaction>
 Value: 0
 GasLimit: <move_balance_cost> + length(Data) * <gas_per_data_byte> + <inner transaction gas limit>
 Data: "relayedTx" +
          "@" + <JSON serialized inner transaction in hexadecimal encoding>
} 

内部交易可以具有如下格式:

RelayedV1InnerTransaction {
 Sender: <Receiver of the relayed transaction>
 Receiver: <Smart Contract address>
 Value: 0
 GasLimit: <to be determined for each case>
 Data: "functionName" +
          "@" + <argument in hexadecimal encoding>
          ...
} 

然而,与常规交易的 JSON 序列化不同,必须签名的内部交易具有不同的结构:

type Transaction struct {
    Nonce           uint64        
    Value           *math_big.Int 
    ReceiverAddress []byte            
    SenderAddress   []byte                
    GasPrice        uint64        
    GasLimit        uint64        
    Data            []byte        
    ChainID         []byte        
    Version         uint32        
    Signature       []byte        
    Options         uint32        
} 

请注意,与常规的前端 交易结构相比,存在一些差异,例如:

  • SenderAddressReceiverAddress必须是字节数组,而不是 bech32 字符串地址
  • Value必须是大整数,而不是字符串
  • ChainID必须是字节数组而不是字符串
  • Signature必须是字节数组,而不是它的十六进制版本

准备使用 erdjs 中继 v1 交易

erdjs通过使用一个允许用户准备这种交易的构建器,内置了对中继交易版本 1 的支持。

资源:

举例

下面是一个中继 v1 交易的示例。其意图是:

erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx将调用合约erd1qqqqqqqqqqqqqpgqrchxzx5uu8sv3ceg8nx8cxc0gesezure5awqn46gtd的函数add,而erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th将支付计算费用

{
  "nonce":2627,
  "value":"0",
  "receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx",
  "sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th",
  "gasPrice":1000000000,
  "gasLimit":61040000,
  "data":"cmVsYXllZFR4QDdiMjI2ZTZmNmU2MzY1MjIzYTMxMzkzODJjMjI3MzY1NmU2NDY1NzIyMjNhMjI2NzQ1NmU1NzRmNjU1NzZkNmQ0MTMwNjMzMDZhNmI3MTc2NGQzNTQyNDE3MDdhNjE2NDRiNDY1NzRlNTM0ZjY5NDE3NjQzNTc1MTYzNzc2ZDQ3NTA2NzNkMjIyYzIyNzI2NTYzNjU2OTc2NjU3MjIyM2EyMjQxNDE0MTQxNDE0MTQxNDE0MTQxNDE0NjQxNDIzNDc1NTk1MjcxNjMzNDY1NDQ0OTM0Nzk2NzM4N2E0ODc3NjI0NDMwNWE2ODZiNTg0MjM1NzAzMTc3M2QyMjJjMjI3NjYxNmM3NTY1MjIzYTMwMmMyMjY3NjE3MzUwNzI2OTYzNjUyMjNhMzEzMDMwMzAzMDMwMzAzMDMwMzAyYzIyNjc2MTczNGM2OTZkNjk3NDIyM2EzNjMwMzAzMDMwMzAzMDMwMmMyMjY0NjE3NDYxMjIzYTIyNTk1NzUyNmIyMjJjMjI3MzY5Njc2ZTYxNzQ3NTcyNjUyMjNhMjI0ZTMwNzIzMTcwNmYzNzZiNzY0ZjU0NGI0OTQ3NDcyZjc1NmI2NzcyMzg1YTYyNTc2NDU4NjczMTY2NTEzMDc2NmQ3NTYyMzU3OTM0NGY3MzUzNDE3MTM0N2EyZjU5Mzc2YzQ2NTI3OTU3NzM2NzM0NGUyYjZmNGE2OTQ5NDk1Nzc3N2E2YjZkNmM2YTQ5NDE3MjZkNjkzMTY5NTg0ODU0NzkzNDRiNjc0MTQxM2QzZDIyMmMyMjYzNjg2MTY5NmU0OTQ0MjIzYTIyNTY0MTNkM2QyMjJjMjI3NjY1NzI3MzY5NmY2ZTIyM2EzMTdk",
  "chainID":"T",
  "signature": "44889e788581c8913a00e03f711f9ed3522119030a48fe6c1b3434656670b4b93867213f7a7b5453eafe0884f7447361e1154d26c6e7b2cfa40510159e0e1008",
  "version":1
} 

数据字段(从 base64 解码为字符串后)转换为:

relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414234755952716334654449347967387a48776244305a686b5842357031773d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225957526b222c227369676e6174757265223a224e307231706f376b764f544b4947472f756b6772385a625764586731665130766d75623579344f73534171347a2f59376c465279577367344e2b6f4a69494957777a6b6d6c6a4941726d69316958485479344b6741413d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a317d 

此外,内部交易很容易被解码(十六进制字符串到字符串),导致:

{
   "nonce":198,
   "sender":"gEnWOeWmmA0c0jkqvM5BApzadKFWNSOiAvCWQcwmGPg=",
   "receiver":"AAAAAAAAAAAFAB4uYRqc4eDI4yg8zHwbD0ZhkXB5p1w=",
   "value":0,
   "gasPrice":1000000000,
   "gasLimit":60000000,
   "data":"YWRk",
   "signature":"N0r1po7kvOTKIGG/ukgr8ZbWdXg1fQ0vmub5y4OsSAq4z/Y7lFRyWsg4N+oJiIIWwzkmljIArmi1iXHTy4KgAA==",
   "chainID":"VA==",
   "version":1
} 

解码 base64 字段,我们将得到:

  • 发送者:T0
  • 接收者:erd1qqqqqqqqqqqqqpgqrchxzx5uu8sv3ceg8nx8cxc0gesezure5awqn46gtd
  • 数据:add
  • 链 ID: T
  • 签名:374af5a68ee4bce4ca2061bfba482bf196d67578357d0d2f9ae6f9cb83ac480ab8cff63b9454725ac83837ea09888216c33926963200ae68b58971d3cb82a000

关于中继交易的气体限制,让我们检查一下数学。

gasLimit = <move_balance_cost> + length(Data) * <gas_per_data_byte> + <inner transaction gas limit>
gasLimit =          50_000     +      660     *        1500         +         60_000_000
gasLimit = 61040000  // just like the gas limit set in the relayed transaction 

转述交易版本 2

与版本 1 相比,中继交易版本 2 仅具有包含在数据字段中的内部交易的某些字段,使得有效载荷更小,因此 tx 费用更小。它还消除了在中继和内部交易之间计算匹配气体限值的需要。

它看起来像是:

RelayedV1Transaction {
    Sender: <Relayer address>
    Receiver: <Address that signed the inner transaction>
    Value: 0
    GasLimit: <move_balance_cost> + length(Data) * <gas_per_data_byte> + <gas needed for the inner transaction>
    Data: "relayedTxV2" +
          "@" + <Smart Contract address to be called in hexadecimal encoding>
          "@" + <nonce of the receiver in hexadecimal encoding>
          "@" + <data field (function name + args) in hexadecimal encoding>
          "@" + <the signature of the inner transaction in hexadecimal encoding>
} 

注意到所需的参数,内部交易有一些限制:它不能有看涨价值或自定义油价。

因此,当想要建立这样的交易时,步骤应该是:

  • 创建内部交易(确保gasLimit设置为 0)
  • 签名吧
  • 获取接收者、nonce、数据和签名字段,并在中继的交易中使用它们

准备使用 erdjs 中继 v2 交易

erdjs通过使用一个允许用户准备这种交易的构建器,内置了对中继交易版本 2 的支持。

资源:

举例

下面是一个中继 v2 交易的示例。其意图是:

erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx将调用合约erd1qqqqqqqqqqqqqpgqrchxzx5uu8sv3ceg8nx8cxc0gesezure5awqn46gtd的函数add,而erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th将支付计算费用

{
   "nonce":37,
   "value":"0",
   "receiver":"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx",
   "sender":"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th",
   "gasPrice":1000000000,
   "gasLimit":60372500,
   "data":"cmVsYXllZFR4VjJAMDAwMDAwMDAwMDAwMDAwMDA1MDAxZTJlNjExYTljZTFlMGM4ZTMyODNjY2M3YzFiMGY0NjYxOTE3MDc5YTc1Y0AwZkA2MTY0NjRAOWFiZDEzZjRmNTNmM2YyMzU5Nzc0NGQ2NWZjNWQzNTFiYjY3NzNlMDVhOTU0YjQxOWMwOGQxODU5M2QxYzY5MjYyNzlhNGQxNjE0NGQzZjg2NmE1NDg3ODAzMTQyZmNmZjBlYWI2YWQ1ODgyMDk5NjlhY2I3YWJlZDIxMDIwMGI=",
   "chainID":"T",
   "signature":"2a448b92c16a564a0b1dc8d02fb3a73408decc0aa47d0780a4faa108234d767dc262057b376a9f3c4d9283018c90cb751b55d27c42f59d63cce3ca6213a5ac0a",
   "version":1
} 

解码数据字段(base64 到 string)后,我们将得到:

relayedTxV2@000000000000000005001e2e611a9ce1e0c8e3283ccc7c1b0f4661917079a75c@0f@616464@9abd13f4f53f3f23597744d65fc5d351bb6773e05a954b419c08d18593d1c6926279a4d16144d3f866a5487803142fcff0eab6ad588209969acb7abed210200b 

解码论点(这里有用的资源)我们会得到:

  • 第一个参数:000000000000000005001e2e611a9ce1e0c8e3283ccc7c1b0f4661917079a75c = > erd1qqqqqqqqqqqqqpgqrchxzx5uu8sv3ceg8nx8cxc0gesezure5awqn46gtd(要调用的 sc 地址)
  • 第二个参数:0f = > 15(内部交易的 nonce)
  • 第三个参数:616464 = > add(要调用的函数——本例中不需要参数)
  • 第四个参数:9abd13f4f53f3f23597744d65fc5d351bb6773e05a954b419c08d18593d1c6926279a4d16144d3f866a5487803142fcff0eab6ad588209969acb7abed210200b(内部交易签名)


回到顶部