ETH转账交易离线签名教程

    2020-11-26 15:13:49 #ETH转账交易离线签名 #ETH转账离线签名 #转账离线签名

    优盾钱包(www.uduncloud.com)提供BTC_ETH_USDT_EOS_XRP等主流erc20代币对接交易所钱包充提币_转账支付归集_API/RPC的php/java开发接口。API快捷接入,多币种多地址钱包余额一键归集、私钥冷存储、多级复签、全终端支持。 点此立即试用


    如果对今年数字货币领域最受关注事件进行排名,排在首位的毫无疑问非BTC减半莫属了位列第二的大多数人可能会认为是以太坊2.0的启动。由此可见,以太坊的影响力和受众之广,那么对于ETH数字资产的管理成为业内刚需,近些年,不少开发者和投资者纷纷涌入区块链钱包的赛道,基于区块链钱包技术开发上大家常会遇到的如何进行ETH转账交易离线签名,接下来我们共同来看看:

    它的原理在于区块链钱包本地将交易转账内容发起离线签名,接着根据 ETH  JSON-RPC方式发送至ETH节点值得注意的是,ETH跟其它ERC20代币的转账离线签名并不相同。

    ETH转账离线签名

     

        /**

     

        * 以太坊(ETH) 转账离线签名

     

        * @param to 转入的区块链钱包地址

     

        * @param nonce ETH nonce

     

        * @param gasPrice gasPrice

     

        * @param gasLimit gasLimit

     

        * @param amount 需要转账eth数量

     

        * @param wallet 区块链钱包对象

     

        * @param password 密码

     

        * @return 签名data

     

        */

     

        public String signedEthTransactionData(String to,


                                                 BigInteger nonce,

     

                                                 BigInteger gasPrice,

     

                                                 BigInteger gasLimit,

     

                                                 BigDecimal amount,

     

                                                 HLWallet wallet,

     

                                                 String password) throws Exception {


     

         // 十进制的转以太坊的Wei, 1ETH = 10^18 Wei

     

         BigDecimal amountInWei = Convert.toWei(amount.toString(), Convert.Unit.ETHER);

     

         RawTransaction rawTransaction = RawTransaction.createEtherTransaction(nonce, gasPrice, gasLimit, to, amountInWei.toBigInteger());

     

         return signData(rawTransaction,wallet,password);

     

        }

     

        private String signData(RawTransaction rawTransaction,

     

                     HLWallet wallet,

     

                     String password) throws Exception {

     

            Credentials credentials = Credentials.create(LWallet.decrypt(password, wallet.walletFile));

     

            byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, ChainId.MAINNET, credentials);

     

            return Numeric.toHexString(signMessage);

     

        }

     

    Nonce值

    避免交易发生重播攻击事件在进行笔交易时,都要有一个nonce随机数,对于所有的账户nonce设置要从0开始,如果nonce等于0的交易结束后,才能接着处理满足nonce等于1的交易,值得一提的时,在原来基础上依次加1的交易才能符合标准接受处理我们也总结了nonce应用条规则可供参考:

     

    1. 如果nonce值过小此时交易则会默认为拒绝。
    2. 如果nonce值过大,此时交易则会被长时间置于队列中
    3. 如果发送某个较大nonce值,接着补齐最先开始nonce到这个较大值之间的nonce,结果是交易依然能够被执行。
    4. 如果交易置于queue中时但对geth客户端停止此时交易queue的交易系统删除

     

     获得nonce根据EIH JSON-RPC方法


     


    ERC-20代币转账交易离线签名


    前面我们也说过ERC-20代币ETH转账并不相同的有必要走智能合约

    可参考方式如下

     

        public String signedContractTransactionData(String contractAddress,

     

                                                     String to,

     

                                                     BigInteger nonce,

     

                                                     BigInteger gasPrice,


                                                     BigInteger gasLimit,

     

                                                     BigDecimal amount,

     

                                                     BigDecimal decimal,

     

                                                     HLWallet wallet,

     

                                                     String password) throws Exception {

     

          //由于所有代币能够规定本身的小数位, 因此实际的转账值=数值 * 10^小数位

     

          BigDecimal realValue = amount.multiply(decimal);

     

          //0xa9059cbb意味着个代币的转账交易方法哈希(transfer) + 对方的转账交易地址哈希 + 转账值的哈希

     

          String data = Params.Abi.transfer + // 0xa9059cbb

     

              Numeric.toHexStringNoPrefixZeroPadded(Numeric.toBigInt(to), 64) +

     

              Numeric.toHexStringNoPrefixZeroPadded(realValue.toBigInteger(), 64);

     

          RawTransaction rawTransaction = RawTransaction.createTransaction(

     

              nonce,

     

              gasPrice,

     

              gasLimit,

     

              contractAddress,

     

              data);

     

           return signData(rawTransaction, wallet, password);

     

        }

     

    这种情况下,咱们必须将转账交易的指令内容根据签名时的data发送出去。ERC-20代币转账交易data组成部分如下.

    1、固定头0xa9059cbb

    2、转入区块链钱包地址

    3、交易转账的数量,wei为单位

    此时有人或许会产生为何偏偏固定头0xa9059cbb的疑问那是由于作为函数原型transfer(address,uint256)的MethodId,跟ETH用来分辨指令的标识类似,详细转换思路时

     

          // transfer -> 0xa9059cbb

     

            String transfer = "transfer(address,uint256)";

     

            byte[] bytes = transfer.getBytes();

     

            byte[] bytes1 = org.web3j.crypto.Hash.sha3(bytes);

     

            String hex = Numeric.toHexString(bytes1, 0, 4, true);

     

            ShadowLog.i("transfer", hex);

     

    接着将转入地址转账数量转化成十六16进制,针对左边补六十四.此时3个参数字符串在一即为最签名时所需要用的data. 由于转入交易地址的类型address转账交易数量的类型uint256都属于静态的,所以可以采用这种的拼接方,假如是动态的状态那就需要改变,详细可借鉴ABI文档.

    另外还有一种无需关心内部参数拼接问题的方法,即对web3j有的封装实现,

     

        public String signContractTransaction(String contractAddress,

     

                            String to,

     

                            BigInteger nonce,

     

                            BigInteger gasPrice,

     

                            BigInteger gasLimit,

     

                            BigDecimal amount,

     

                            BigDecimal decimal,

     

                            HLWallet wallet,

     

                            String password) throws IOException, CipherException {

     

         BigDecimal realValue = amount.multiply(decimal);


         Function function = new Function("transfer",

     

            Arrays.asList(new Address(to),new Uint256(realValue.toBigInteger())),

     

            Collections.emptyList());

     

          String data = FunctionEncoder.encode(function);

     

          RawTransaction rawTransaction = RawTransaction.createTransaction(

     

               nonce,

     

              gasPrice,

     

              gasLimit,

     

              contractAddress,

     

              data);

     

           return signData(rawTransaction, wallet, password);

     

        }


     


    发送请求

    对转账交易签名结束后,根据ETH的JSON-RPC的方法发送出去

    ETH转账交易后在ETH浏览器上的转账结果 ,能够在页面最下方浏览Input Data

     

    0x3078

     

    代币转账最ETH浏览器上的转账结果link,Input Data

    Function: transfer(address _to, uint256 _value)

    MethodID: 0xa9059cbb

    [0]:  000000000000000000000000b7bb6c45800f4531cc1581637868373a06367b48

    [1]:  000000000000000000000000000000000000000000000002d1a51c7e00500000


    现在中小型交易所都不会自己去单独开发一套钱包系统了。不仅因为比特币以太坊等区块节点数据庞大,同步传输慢,而且在服务器和带宽的花费成本比较高。最重要的是养不起这样的一个技术团队!原生钱包这种私钥放在服务器非常不安全,被偷就凉凉了。现在市面上大家用的比较多的优盾钱包就很好用,最赞的就是它的多币种多地址资产一键归集和冷热钱包隔离功能了。

     

    优盾钱包作为全球首家开放式企业级钱包解决方案。API一键对接,支持当下多数主流币种、多资产多地址统一管理、用户提币初审+复核安全模式、系统代付自动放币、多员工多钱包多权限一键分配、资产交易查询、资金流动消息提醒等多种功能。

     

    防黑客技术上:

    API接口信息访问验签、基于HTTPS安全传输,拒绝被监听

    私钥不上传、不触网,并通过二次加密托管在客户端侧

    钱包绑定电脑MAC地址,拒绝非认证设备访问

    冷热钱包分离,大额资产用冷钱包离线保存


    防内鬼技术上:

    员工操作权限管理员一键设置

    员工操作记录管理员一键查询

    员工只接触管理独立小额子钱包

    超额转出交易需管理员复核

    员工在非公司指定电脑设备登录优盾账号需管理员同意


    便捷接入:

    ①免节点同步;

    ②标准接口;

    ③详细接口文档;

    ④接入DEMO;

    ⑤7*24小时技术支持。

    在線客服

    申請試用

    申請試用

    設置