### wsc\_call 立即执行新的消息调用,而无需在区块链上创建事务。该`wsch_call`方法可用于查询内部合同状态,执行编码到合同中的验证,甚至可以测试不实时运行交易的效果。 #### 参量 该方法采用3个参数:一个以只读模式执行的未签名事务对象;执行调用的程序段号;以及可选的状态覆盖集,以允许针对修改后的链状态执行调用。 ##### 1.-`Object`交易调用对象 该*交易调用对象*是强制性的,包含了所有必要的参数执行只读EVM合同法。 | 描述 | 类型 | 字节数 | 可选的 | 描述 | | --- | --- | --- | --- | --- | | `from` | `Address` | 20 | 是 | 模拟已发送交易的地址。默认为本地密钥库中的第一个帐户,`0x00..0`如果没有可用的本地帐户,则为地址。 | | `to` | `Address` | 20 | 没有 | 交易发送到的地址。 | | `gas` | `Quantity` | <8 | 是 | 代码执行的最大gas余量,可以避免无限循环。默认为`2^63`或节点运算符通过指定的任何值`--rpc.gascap`。 | | `gasPrice` | `Quantity` | <32 | 是 | `wei`在执行期间模拟为每单位gas支付的数量。默认为`1 gwei`。 | | `value` | `Quantity` | <32 | 是 | 量`wei`来模拟与交易一起发送。默认为`0`。 | | `data` | `Binary` | 任何 | 是 | 二进制数据发送到目标合同。通常,方法签名的4字节哈希值后跟ABI编码的参数。 例: ~~~ { "from": "0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3", "to": "0xebe8efa441b9302a0d7eaecc277c09d20d684540", "gas": "0x1bd7c", "data": "0xd459fc46000000000000000000000000000000000000000000000000000000000046c650dbb5e8cb2bac4d2ed0b1e6475d37361157738801c494ca482f96527eb48f9eec488c2eba92d31baeccfb6968fad5c21a3df93181b43b4cf253b4d572b64172ef000000000000000000000000000000000000000000000000000000000000008c00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000002b85c0c828d7a98633b4e1b65eac0c017502da909420aeade9a280675013df36bdc71cffdf420cef3d24ba4b3f9b980bfbb26bd5e2dcf7795b3519a3fd22ffbb2000000000000000000000000000000000000000000000000000000000000000238fb6606dc2b5e42d00c653372c153da8560de77bd9afaba94b4ab6e4aa11d565d858c761320dbf23a94018d843772349bd9d92301b0ca9ca983a22d86a70628", } ~~~ ##### 2.`Quantity | Tag`\-块数或字符串`latest`或`pending` 的*块号*是强制性的,并且限定针对其指定的事务应该被执行的上下文(状态)。无法对重组后的块执行调用;或大于128的块(除非该节点是归档节点)。 ##### 3.-`Object`状态替代集 的*状态覆写集*是一个可选的地址到状态映射,其中每个条目指定一些状态之前执行呼叫被短暂地覆盖。每个地址都映射到一个包含以下内容的对象: | 描述 | 类型 | 字节数 | 可选的 | 描述 | | --- | --- | --- | --- | --- | | `balance` | `Quantity` | <32 | 是 | 在执行呼叫之前为帐户设置假余额。 | | `nonce` | `Quantity` | <8 | 是 | 在执行呼叫之前,先为帐户设置伪随机数。 | | `code` | `Binary` | 任何 | 是 | 伪造EVM字节码以在执行调用之前注入帐户。 | | `state` | `Object` | 任何 | 是 | 在执行调用之前,伪造的键值映射将覆盖帐户存储中的**所有**插槽。 | | `stateDiff` | `Object` | 任何 | 是 | 伪造的键值映射可在执行调用之前覆盖帐户存储中的**各个**插槽。 | *状态覆盖集*的目标有很多: * DApp可以使用它来减少需要在链上部署的合同代码的数量。可以简单地返回内部状态或执行预定义验证的代码可以保持脱链状态,并按需提供给节点。 * 通过使用自定义方法扩展部署在链上的代码并调用它们,可以将其用于智能合约分析。这避免了必须下载并重建沙箱中的整个状态以针对其运行自定义代码。 * 通过有选择地覆盖某些代码或状态并查看执行方式如何变化,可将其用于调试已部署的大型合同套件中的智能合同。可能需要专门的工具。 例: ~~~ { "0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3": { "balance": "0xde0b6b3a7640000" }, "0xebe8efa441b9302a0d7eaecc277c09d20d684540": { "code": "0x...", "state": { "" } } } ~~~ #### 返回值 该方法返回一个`Binary`由执行的合同调用的返回值组成的单个值。 #### 简单的例子 通过在localhost(`wsc --rinkeby --rpc`)上公开了带有RPC的同步Rinkeby节点,我们可以对[Checkpoint Oracle]行调用以检索管理员列表: ~~~ $ curl --data '{"method":"wsc_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},"latest"],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545 ~~~ 结果是worldchain ABI编码的帐户列表: ~~~ { "id": 1, "jsonrpc": "2.0", "result": "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000d9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f300000000000000000000000078d1ad571a1a09d60d9bbf25894b44e4c8859595000000000000000000000000286834935f4a8cfb4ff4c77d5770c2775ae2b0e7000000000000000000000000b86e2b0ab5a4b1373e40c51a7c712c70ba2f9f8e" } ~~~ 仅出于完整性考虑,解码后的响应为: ~~~ 0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3, 0x78d1ad571a1a09d60d9bbf25894b44e4c8859595, 0x286834935f4a8cfb4ff4c77d5770c2775ae2b0e7, 0xb86e2b0ab5a4b1373e40c51a7c712c70ba2f9f8e ~~~ #### 覆盖示例 上面的*简单示例*显示了如何调用链上智能合约已经公开的方法。如果我们想访问一些未公开的数据怎么办? 我们可以使用保留相同字段(以保留相同存储布局)的合同检查点oracle合同,但是包含不同方法集的合同: ~~~ pragma solidity ^0.5.10; contract CheckpointOracle { mapping(address => bool) admins; address[] adminList; uint64 sectionIndex; uint height; bytes32 hash; uint sectionSize; uint processConfirms; uint threshold; function VotingThreshold() public view returns (uint) { return threshold; } } ~~~ 通过在localhost(`wsc --rinkeby --rpc`)上公开了带有RPC的同步Rinkeby节点,我们可以对实时行调用,但是可以使用我们自己的版本覆盖其字节代码,该版本具有用于投票阈值字段的访问器: ~~~ $ curl --data '{"method":"wsc_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x0be5b6ba"}, "latest", {"0xebe8efa441b9302a0d7eaecc277c09d20d684540": {"code":"0x6080604052348015600f57600080fd5b506004361060285760003560e01c80630be5b6ba14602d575b600080fd5b60336045565b60408051918252519081900360200190f35b6007549056fea265627a7a723058206f26bd0433456354d8d1228d8fe524678a8aeeb0594851395bdbd35efc2a65f164736f6c634300050a0032"}}],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545 ~~~ 结果是worldchain ABI编码的阈值编号: ~~~ { "id": 1, "jsonrpc": "2.0", "result": "0x0000000000000000000000000000000000000000000000000000000000000002" } ~~~ 仅出于完整性考虑,解码后的响应为:`2`。