一、说明
在dapp开发中涉及到需要在后台程序中使用私钥对消息进行签名的需求,比如签名验签、充提币接口、批量归集usdt等场景下都需要使用私钥在程序后台进行签名。无法通过metamask或者其他web3客户端钱包进行签名,因为客户端钱包签名只适用于个人签名的方式,系统以交互式的方式请求用户个人签名时可以调用metamask钱包进行签名。
但是,后台程序签名要求必须是直接在程序中异步完成签名,并提交请求到链端。
本dapp示例代码包含通过metamask钱包客户端签名的方式,私钥后台签名的方式,已经solidity链端完成签名验签的过程,最后执行代币的充提接口。
dapp前端页面展示效果如下:
二、核心代码分析
1、solidity端签名验签代码如下:
function verify( address _signer, uint256 amount, address to, uint256 _nonce, bytes memory signature ) internal pure returns (bool) { bytes32 messageHash = getMessageHash(amount, to, _nonce); bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash); return recoverSigner(ethSignedMessageHash, signature) == _signer; } function queryVerify(bytes32 _hashedMessage, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) { bytes32 ethSignedMessageHash = getEthSignedMessageHash(_hashedMessage); address signer = ecrecover(ethSignedMessageHash, _v, _r, _s); return signer; }
2、dapp前端ether.js类库引用代码如下:
async function signMessagePriKey() { //创建签名者对象,实际就是创建 Wallet对象 const signer = new ethers.Wallet(privateKey, provider); console.log('signerAddress:', wallet.address); const signature = await wallet.signMessage(message); const signature = await wallet.signMessage(message, { hexPrefixed: false }); const signature = ethers.utils.signMessage(message, privateKey); const signedMessage = web3.eth.accounts.sign(message, privateKey); const signature = await web3.eth.sign(messageHash, account, privateKey); }
以上产生signature的方法都可以成功产生签名消息,但是每个函数产生签名消息的方式是不同的,针对相同的原始消息,使用同一个私钥签名产生的消息值是不同的。因为每个方法签名的方式是不同的,目前主流的方式是对原始消息hash,产生哈希值,然后追加以太坊签名头”\x19Ethereum Signed Message:\n32″,再次hash产生以太坊hash值,然后使用私钥进行签名。部分函数还会在签名消息中追加消息长度length值,通过”\x19Ethereum Signed Message:\n32″值识别为以太坊签名消息,以太坊标记状态的签名消息不会被执行,避免了冒充或者恶意交易攻击。
3、dapp前端页面布局代码如下:
<form> <label for="address-input">提币地址:</label> <input type="text" id="address-input"> <label for="amount-input">提币数量:</label> <input type="number" id="amount-input"> <label for="nonce-input">提币nonce:</label> <input type="number" id="nonce-input"> <p class="form-note">提币数量需要包含精度,提币nonce值需要唯一,nonce步长值为2</p> </form> <div class="button-group"> <button class="connect-wallet-btn" onclick="connWallet()">连接钱包</button> <button class="signmgs-btn" onclick="signMessage()">签名消息(钱包)</button> <button class="signmgs-btn" onclick="signMessagePriKey()">签名消息(私钥)</button> <button class="verifysig-btn" onclick="verifyMessage()">验证签名</button> <button class="execute-contract-btn" onclick="withdraw()">执行提币</button> </div>
前端根据用户form表达是输入,对多个变量值进行hash签名产生正确的签名消息后,提交到链端,由链端完成签名验签,最终完成代币的自动化提币,dapp中会员可以自动实现链上充提币操作。
至此,完成ether.js中私钥方式对消息进行签名并实现链端验签,完成系统会员的代币自动充提所有操作流程。
pdf+视频币安智能链BSC发币教程及多模式组合合约源代码下载:
币安智能链BSC发币(合约部署、开源、锁仓、LP、参数配置、开发、故障处理、工具使用)教程下载:
多模式(燃烧、回流指定营销地址、分红本币及任意币种,邀请推广八代收益,LP加池分红、交易分红、复利分红、NFT分红、自动筑池、动态手续费、定时开盘、回购)组合合约源代码下载:
pdf+视频币安智能链BSC发币教程及多模式组合合约源代码下载地址:
添加VX或者telegram获取全程线上免费指导
评论前必须登录!
注册