{"content":{"title":"以太坊签名解析","body":"# 以太坊签名解析\r\n\r\n## 签名交易\r\n一个签名交易由(nonce, gasPrice, gasLimit, to, value, data, v, r, s)构成。其中的参数作用如下：\r\n```\r\nnonce: 记录发起交易的账户已执行交易总数。\r\n\r\ngasPrice:该交易每单位gas的价格。\r\n\r\ngasLimit:该交易支付的最高gas上限。\r\n\r\nto：该交易被送往的地址(如果是部署合约交易，to为空，节点看到to是空的就知道这是部署合约交易)。\r\n\r\nvalue：交易发送的以太币总量。\r\n\r\ndata:\r\n若该交易是以太币交易，则data为空；\r\n若是部署合约，则data为合约的bytecode；\r\n若是合约调用，则data为selector+函数参数；\r\n\r\nchainId：防止跨链重放攻击。\r\n\r\n```\r\n\r\n在签名时会先对RLP(nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0)进行Keccak256，然后对其进行签名得到(v,r,s)，最后会对(nonce, gasPrice, gasLimit, to, value, data, v, r, s)再次进行RPL编码，与keccak256，签名。\r\n\r\n\r\n。\r\n\r\n\r\n## 签名消息\r\n签名消息即预签名(presigned message)。在了解什么是签名消息之前我们先要知道发给节点的只能是交易签名+相应参数，即上文中的(v, r, s)与(nonce, gasPrice, gasLimit, to, value, data)。通过观察其中的参数能发现在与合约进行交互时主要通过data来实现，而消息签名就是用来实现对合约的调用，即消息签名是data的一部分。\r\n\r\n以ERC20-Permit举个例子\r\n```\r\n    function permit(\r\n        address owner,\r\n        address spender,\r\n        uint256 value,\r\n        uint256 deadline,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) public virtual {\r\n        if (block.timestamp > deadline) {\r\n            revert ERC2612ExpiredSignature(deadline);\r\n        }\r\n\r\n        bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\r\n\r\n        bytes32 hash = _hashTypedDataV4(structHash);\r\n\r\n        address signer = ECDSA.recover(hash, v, r, s);\r\n        if (signer != owner) {\r\n            revert ERC2612InvalidSigner(signer, owner);\r\n        }\r\n\r\n        _approve(owner, spender, value);\r\n    }\r\n```\r\n当用户调用permit函数时会对“调用permit函数”行为这个进行签名，即签名交易，然后节点将会进行验证。而消息签名则是用户在调用permit函数时输入的参数中的(v,r,s)。\r\n\r\n\r\n## 总结\r\n交易签名是由调用者进行签名，由节点进行验证。而消息签名由他人进行签名，是交易签名中的data的一部分，由合约进行验证，允许调用者以消息签名的签名者的身份对合约进行操作。"},"author":{"user":"https://learnblockchain.cn/people/13107","address":"0x46b724cFB1dC45e01C93a524191F98E8A89d98ee"},"history":null,"timestamp":1714049280,"version":1}