教程 | 使用WeBASE進(jìn)行“兩階段交易”
“兩階段交易”是什么?“兩階段交易”是指分成兩個(gè)步驟發(fā)送交易,即對(duì)交易編碼并簽名、將交易提交到鏈上這兩個(gè)階段:
第一階段:構(gòu)造并獲取交易編碼值,并通過(guò)私鑰對(duì)交易編碼值簽名; 第二階段:發(fā)送交易,也就是將已簽名的編碼值發(fā)送到鏈上。


值得一提的是,調(diào)用 /trans/convertRawTxStr/withSign 接口時(shí):
如果傳入了 signUserId 非空,則返回的交易體編碼值是通過(guò) signUserId 對(duì)應(yīng)私鑰簽名后的交易體編碼值。 如果傳入的 signUserId 為空,則返回的是未簽名的交易體編碼值,開(kāi)發(fā)者也可以通過(guò)JAVA-SDK用私鑰對(duì)該值簽名。




public void testSign(TransactionEncoderService encoderService, RawTransaction rawTransaction) {// 未簽名的交易編碼值String encodedTransaction = "0xf8a9a001b41b2cc71fe0bf0450f1fa4d820209b6686a8f226d217be0bc51cd9fc4a020018405f5e100820204941f2dfecfd75b883b51762aef6326d3ae9ad5230180b8644ed3885e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000033132330000000000000000000000000000000000000000000000000000000000010180";// 私鑰String privateKey = "0x123";// ECDSA 加密套件CryptoSuite cryptoSuite = new CryptoSuite(CryptoType.ECDSA_TYPE);// 對(duì)待簽名的編碼值作哈運(yùn)算String hashMessageStr = cryptoSuite.hash(encodedTransaction);System.out.println("hashMessageStr: " + hashMessageStr);// 創(chuàng)建私鑰對(duì)CryptoKeyPair myKeyPair = cryptoSuite.createKeyPair(privateKey);// 對(duì)交易編碼值簽名SignatureResult signedTx = cryptoSuite.sign(hashMessageStr, myKeyPair);// 獲得最終簽名后的交易編碼值byte[] signedTransaction = encoderService.encode(rawTransaction, signedTx);// 轉(zhuǎn)十六進(jìn)制字符串String signedTransactionStr = Numeric.toHexString(signedTransaction);System.out.println("signedTransactionStr: " + signedTransactionStr);}


// 構(gòu)造Function實(shí)例Function function = new Function(funcName, contractFunction.getFinalInputs(),contractFunction.getFinalOutputs());// 編碼FunctionFunctionEncoder functionEncoder = new FunctionEncoder(cryptoSuite);String encodedFunction = functionEncoder.encode(function);
// 構(gòu)造交易體BigInteger randomId = new BigInteger(250, new SecureRandom());BigInteger blockLimit = web3j.getBlockLimit();RawTransaction rawTransaction =RawTransaction.createTransaction(randomId, Constants.GAS_PRICE,Constants.GAS_LIMIT, blockLimit, contractAddress, BigInteger.ZERO, encodedFunction,new BigInteger(Constants.chainId), BigInteger.valueOf(groupId), "");// 編碼交易體RawTransactionTransactionEncoderService encoderService = new TransactionEncoderService(cryptoSuite);byte[] encodedTransaction = encoderService.encode(rawTransaction, null);
對(duì)交易編碼值簽名前,WeBASE-Front 中會(huì)根據(jù)傳入的 user 字段和 isLocal 字段判斷:
如果 user 字段為空,則將 encodedTransaction 轉(zhuǎn)為十六進(jìn)制后返回。該值就是第一階段未簽名的交易編碼值。 如果 user 字段非空, isLocal 字段為 true,則 user 為 WeBASE-Front 本地的用戶私鑰,通過(guò)本地私鑰對(duì)交易編碼值 encodedTransaction 簽名。注意,簽名前還需對(duì) encodedTransaction 進(jìn)行一次哈希運(yùn)算后再簽名。 如果 user 字段非空, isLocal 字段為 false,則 user 為 WeBASE-Sign 托管私鑰的signUserId,通過(guò)簽名服務(wù)對(duì)交易體編碼值 encodedTransaction 簽名。注意,此處簽名前沒(méi)有對(duì) encodedTransaction 進(jìn)行哈希,而是直接轉(zhuǎn)為十六進(jìn)制發(fā)到簽名服務(wù),簽名服務(wù)拿到該值后再做哈希運(yùn)算并簽名返回結(jié)果。
// encodedTransaction轉(zhuǎn)十六進(jìn)制String hashMessageStr = Numeric.toHexString(encodedTransaction);// 通過(guò)WeBASE-Sign簽名EncodeInfo encodeInfo = new EncodeInfo(user, hashMessageStr);String signDataStr = keyStoreService.getSignData(encodeInfo);// 反序列化簽名結(jié)果SignatureResult signData = CommonUtils.stringToSignatureData(signDataStr, cryptoSuite.cryptoTypeConfig);// 加入簽名結(jié)果,再次編碼byte[] signedMessage = encoderService.encode(rawTransaction, userSignResult);// 轉(zhuǎn)為十六進(jìn)制String signResultStr = Numeric.toHexString(signedMessage);
// 通過(guò)CryptoSuite實(shí)例計(jì)算signResultStr的交易哈希值String transHash = cryptoSuite.hash(signResultStr);
即刻使用
上述優(yōu)化及功能所涉及的最新代碼和技術(shù)文檔已同步更新,歡迎體驗(yàn)和star支持。如需咨詢技術(shù)問(wèn)題,歡迎本公眾號(hào)對(duì)話框回復(fù)【小助手】進(jìn)技術(shù)交流群。

評(píng)論
圖片
表情
