@Test public void signMultiSignTransactionTest() throws Exception { Map<String, Object> map = createMultiSignTransfer(); String txHex = map.get("txHex").toString(); MultiSigAccount multiSigAccount = (MultiSigAccount) map.get("multiSigAccount"); String signAddress = AddressTool.getStringAddressByBytes(AddressTool.getAddress(multiSigAccount.getPubKeyList().get(1), chainId)); Map<String, Object> params = new HashMap<>(); params.put(Constants.CHAIN_ID, chainId); params.put("signAddress", signAddress); params.put("password", password); params.put("txHex", txHex); Response cmdResp = ResponseMessageProcessor.requestAndResponse(ModuleE.AC.abbr, "ac_signMultiSignTransaction", params); Log.info("ac_signMultiSignTransaction response:{}", cmdResp); assertNotNull(cmdResp); HashMap result = (HashMap) (((HashMap) cmdResp.getResponseData()).get("ac_signMultiSignTransaction")); assertNotNull(result); String txHash = (String) result.get("txHash"); assertNotNull(txHash); }
@CmdAnnotation(cmd = "ac_signMultiSignTransaction", version = 1.0, description = "多签交易签名/sign MultiSign Transaction") @Parameters(value = { @Parameter(parameterName = "chainId", requestType = @TypeDescriptor(value = int.class), parameterDes = "链id"), @Parameter(parameterName = "tx", parameterType = "String", parameterDes = "交易数据字符串"), @Parameter(parameterName = "signAddress", parameterType = "String", parameterDes = "签名账户地址"), @Parameter(parameterName = "signPassword", parameterType = "String", parameterDes = "签名账户密码") }) @ResponseData(name = "返回值", description = "返回一个Map,包含三个key", responseType = @TypeDescriptor(value = Map.class, mapKeys = { @Key(name = "tx", description = "完整交易序列化字符串,如果交易没达到最小签名数可继续签名"), @Key(name = "txHash", description = "交易hash"), @Key(name = "completed", valueType = boolean.class, description = "true:交易已完成(已广播),false:交易没完成,没有达到最小签名数") })) public Response signMultiSignTransaction(Map params) { Chain chain = null; Object chainIdObj = params == null ? null : params.get(RpcParameterNameConstant.CHAIN_ID); Object passwordObj = params == null ? null : params.get(RpcParameterNameConstant.SIGN_PASSWORD); Object signAddressObj = params == null ? null : params.get(RpcParameterNameConstant.SIGN_ADDREESS); Object txStrObj = params == null ? null : params.get(RpcParameterNameConstant.TX); try { if (params == null || chainIdObj == null || signAddressObj == null || txStrObj == null) { LoggerUtil.LOG.warn("ac_signMultiSignTransaction params is null"); throw new NulsRuntimeException(AccountErrorCode.NULL_PARAMETER); } chain = chainManager.getChain((Integer) chainIdObj); if (null == chain) { throw new NulsRuntimeException(AccountErrorCode.CHAIN_NOT_EXIST); } int chainId = chain.getChainId(); String password = (String) passwordObj; String signAddress = (String) signAddressObj; String txStr = (String) txStrObj; Account account = accountService.getAccount(chainId, signAddress); if (account == null) { throw new NulsRuntimeException(AccountErrorCode.ACCOUNT_NOT_EXIST); } MultiSignTransactionResultDTO multiSignTransactionResultDto = transactionService.signMultiSignTransaction(chain, account, password, txStr); boolean result = false; if (multiSignTransactionResultDto.isBroadcasted()) { result = true; } Transaction tx = multiSignTransactionResultDto.getTransaction(); Map<String, Object> map = new HashMap<>(AccountConstant.INIT_CAPACITY_8); map.put("completed", result); map.put("txHash", tx.getHash().toHex()); map.put("tx", RPCUtil.encode(tx.serialize())); return success(map); } catch (NulsRuntimeException e) { errorLogProcess(chain, e); return failed(e.getErrorCode()); } catch (NulsException e) { errorLogProcess(chain, e); return failed(e.getErrorCode()); } catch (Exception e) { errorLogProcess(chain, e); return failed(AccountErrorCode.SYS_UNKOWN_EXCEPTION); } }
TransactionCmd extends BaseCmd { @CmdAnnotation(cmd = "ac_signMultiSignTransaction", version = 1.0, description = "多签交易签名/sign MultiSign Transaction") @Parameters(value = { @Parameter(parameterName = "chainId", requestType = @TypeDescriptor(value = int.class), parameterDes = "链id"), @Parameter(parameterName = "tx", parameterType = "String", parameterDes = "交易数据字符串"), @Parameter(parameterName = "signAddress", parameterType = "String", parameterDes = "签名账户地址"), @Parameter(parameterName = "signPassword", parameterType = "String", parameterDes = "签名账户密码") }) @ResponseData(name = "返回值", description = "返回一个Map,包含三个key", responseType = @TypeDescriptor(value = Map.class, mapKeys = { @Key(name = "tx", description = "完整交易序列化字符串,如果交易没达到最小签名数可继续签名"), @Key(name = "txHash", description = "交易hash"), @Key(name = "completed", valueType = boolean.class, description = "true:交易已完成(已广播),false:交易没完成,没有达到最小签名数") })) public Response signMultiSignTransaction(Map params) { Chain chain = null; Object chainIdObj = params == null ? null : params.get(RpcParameterNameConstant.CHAIN_ID); Object passwordObj = params == null ? null : params.get(RpcParameterNameConstant.SIGN_PASSWORD); Object signAddressObj = params == null ? null : params.get(RpcParameterNameConstant.SIGN_ADDREESS); Object txStrObj = params == null ? null : params.get(RpcParameterNameConstant.TX); try { if (params == null || chainIdObj == null || signAddressObj == null || txStrObj == null) { LoggerUtil.LOG.warn("ac_signMultiSignTransaction params is null"); throw new NulsRuntimeException(AccountErrorCode.NULL_PARAMETER); } chain = chainManager.getChain((Integer) chainIdObj); if (null == chain) { throw new NulsRuntimeException(AccountErrorCode.CHAIN_NOT_EXIST); } int chainId = chain.getChainId(); String password = (String) passwordObj; String signAddress = (String) signAddressObj; String txStr = (String) txStrObj; Account account = accountService.getAccount(chainId, signAddress); if (account == null) { throw new NulsRuntimeException(AccountErrorCode.ACCOUNT_NOT_EXIST); } MultiSignTransactionResultDTO multiSignTransactionResultDto = transactionService.signMultiSignTransaction(chain, account, password, txStr); boolean result = false; if (multiSignTransactionResultDto.isBroadcasted()) { result = true; } Transaction tx = multiSignTransactionResultDto.getTransaction(); Map<String, Object> map = new HashMap<>(AccountConstant.INIT_CAPACITY_8); map.put("completed", result); map.put("txHash", tx.getHash().toHex()); map.put("tx", RPCUtil.encode(tx.serialize())); return success(map); } catch (NulsRuntimeException e) { errorLogProcess(chain, e); return failed(e.getErrorCode()); } catch (NulsException e) { errorLogProcess(chain, e); return failed(e.getErrorCode()); } catch (Exception e) { errorLogProcess(chain, e); return failed(AccountErrorCode.SYS_UNKOWN_EXCEPTION); } } }
TransactionCmd extends BaseCmd { @CmdAnnotation(cmd = "ac_signMultiSignTransaction", version = 1.0, description = "多签交易签名/sign MultiSign Transaction") @Parameters(value = { @Parameter(parameterName = "chainId", requestType = @TypeDescriptor(value = int.class), parameterDes = "链id"), @Parameter(parameterName = "tx", parameterType = "String", parameterDes = "交易数据字符串"), @Parameter(parameterName = "signAddress", parameterType = "String", parameterDes = "签名账户地址"), @Parameter(parameterName = "signPassword", parameterType = "String", parameterDes = "签名账户密码") }) @ResponseData(name = "返回值", description = "返回一个Map,包含三个key", responseType = @TypeDescriptor(value = Map.class, mapKeys = { @Key(name = "tx", description = "完整交易序列化字符串,如果交易没达到最小签名数可继续签名"), @Key(name = "txHash", description = "交易hash"), @Key(name = "completed", valueType = boolean.class, description = "true:交易已完成(已广播),false:交易没完成,没有达到最小签名数") })) public Response signMultiSignTransaction(Map params) { Chain chain = null; Object chainIdObj = params == null ? null : params.get(RpcParameterNameConstant.CHAIN_ID); Object passwordObj = params == null ? null : params.get(RpcParameterNameConstant.SIGN_PASSWORD); Object signAddressObj = params == null ? null : params.get(RpcParameterNameConstant.SIGN_ADDREESS); Object txStrObj = params == null ? null : params.get(RpcParameterNameConstant.TX); try { if (params == null || chainIdObj == null || signAddressObj == null || txStrObj == null) { LoggerUtil.LOG.warn("ac_signMultiSignTransaction params is null"); throw new NulsRuntimeException(AccountErrorCode.NULL_PARAMETER); } chain = chainManager.getChain((Integer) chainIdObj); if (null == chain) { throw new NulsRuntimeException(AccountErrorCode.CHAIN_NOT_EXIST); } int chainId = chain.getChainId(); String password = (String) passwordObj; String signAddress = (String) signAddressObj; String txStr = (String) txStrObj; Account account = accountService.getAccount(chainId, signAddress); if (account == null) { throw new NulsRuntimeException(AccountErrorCode.ACCOUNT_NOT_EXIST); } MultiSignTransactionResultDTO multiSignTransactionResultDto = transactionService.signMultiSignTransaction(chain, account, password, txStr); boolean result = false; if (multiSignTransactionResultDto.isBroadcasted()) { result = true; } Transaction tx = multiSignTransactionResultDto.getTransaction(); Map<String, Object> map = new HashMap<>(AccountConstant.INIT_CAPACITY_8); map.put("completed", result); map.put("txHash", tx.getHash().toHex()); map.put("tx", RPCUtil.encode(tx.serialize())); return success(map); } catch (NulsRuntimeException e) { errorLogProcess(chain, e); return failed(e.getErrorCode()); } catch (NulsException e) { errorLogProcess(chain, e); return failed(e.getErrorCode()); } catch (Exception e) { errorLogProcess(chain, e); return failed(AccountErrorCode.SYS_UNKOWN_EXCEPTION); } }  }
TransactionCmd extends BaseCmd { @CmdAnnotation(cmd = "ac_signMultiSignTransaction", version = 1.0, description = "多签交易签名/sign MultiSign Transaction") @Parameters(value = { @Parameter(parameterName = "chainId", requestType = @TypeDescriptor(value = int.class), parameterDes = "链id"), @Parameter(parameterName = "tx", parameterType = "String", parameterDes = "交易数据字符串"), @Parameter(parameterName = "signAddress", parameterType = "String", parameterDes = "签名账户地址"), @Parameter(parameterName = "signPassword", parameterType = "String", parameterDes = "签名账户密码") }) @ResponseData(name = "返回值", description = "返回一个Map,包含三个key", responseType = @TypeDescriptor(value = Map.class, mapKeys = { @Key(name = "tx", description = "完整交易序列化字符串,如果交易没达到最小签名数可继续签名"), @Key(name = "txHash", description = "交易hash"), @Key(name = "completed", valueType = boolean.class, description = "true:交易已完成(已广播),false:交易没完成,没有达到最小签名数") })) public Response signMultiSignTransaction(Map params) { Chain chain = null; Object chainIdObj = params == null ? null : params.get(RpcParameterNameConstant.CHAIN_ID); Object passwordObj = params == null ? null : params.get(RpcParameterNameConstant.SIGN_PASSWORD); Object signAddressObj = params == null ? null : params.get(RpcParameterNameConstant.SIGN_ADDREESS); Object txStrObj = params == null ? null : params.get(RpcParameterNameConstant.TX); try { if (params == null || chainIdObj == null || signAddressObj == null || txStrObj == null) { LoggerUtil.LOG.warn("ac_signMultiSignTransaction params is null"); throw new NulsRuntimeException(AccountErrorCode.NULL_PARAMETER); } chain = chainManager.getChain((Integer) chainIdObj); if (null == chain) { throw new NulsRuntimeException(AccountErrorCode.CHAIN_NOT_EXIST); } int chainId = chain.getChainId(); String password = (String) passwordObj; String signAddress = (String) signAddressObj; String txStr = (String) txStrObj; Account account = accountService.getAccount(chainId, signAddress); if (account == null) { throw new NulsRuntimeException(AccountErrorCode.ACCOUNT_NOT_EXIST); } MultiSignTransactionResultDTO multiSignTransactionResultDto = transactionService.signMultiSignTransaction(chain, account, password, txStr); boolean result = false; if (multiSignTransactionResultDto.isBroadcasted()) { result = true; } Transaction tx = multiSignTransactionResultDto.getTransaction(); Map<String, Object> map = new HashMap<>(AccountConstant.INIT_CAPACITY_8); map.put("completed", result); map.put("txHash", tx.getHash().toHex()); map.put("tx", RPCUtil.encode(tx.serialize())); return success(map); } catch (NulsRuntimeException e) { errorLogProcess(chain, e); return failed(e.getErrorCode()); } catch (NulsException e) { errorLogProcess(chain, e); return failed(e.getErrorCode()); } catch (Exception e) { errorLogProcess(chain, e); return failed(AccountErrorCode.SYS_UNKOWN_EXCEPTION); } }  @CmdAnnotation(cmd = "ac_transfer", version = 1.0, description = "创建普通转账交易/create transfer transaction") @Parameters(value = { @Parameter(parameterName = "chainId", requestType = @TypeDescriptor(value = int.class), parameterDes = "链id"), @Parameter(parameterName = "inputs", requestType = @TypeDescriptor(value = List.class, collectionElement = CoinDTO.class), parameterDes = "交易支付方数据"), @Parameter(parameterName = "outputs", requestType = @TypeDescriptor(value = List.class, collectionElement = CoinDTO.class), parameterDes = "交易接受方数据"), @Parameter(parameterName = "remark", parameterType = "String", parameterDes = "交易备注") }) @ResponseData(name = "返回值", description = "返回一个Map", responseType = @TypeDescriptor(value = Map.class, mapKeys = { @Key(name = RpcConstant.VALUE, description = "交易hash") })) Response transfer(Map params); @CmdAnnotation(cmd = "ac_createMultiSignTransfer", version = 1.0, description = "创建多签地址转账交易/create multi sign transfer") @Parameters(value = { @Parameter(parameterName = "chainId", requestType = @TypeDescriptor(value = int.class), parameterDes = "链id"), @Parameter(parameterName = "inputs", requestType = @TypeDescriptor(value = List.class, collectionElement = BaseCoinDTO.class), parameterDes = "交易支付方数据"), @Parameter(parameterName = "outputs", requestType = @TypeDescriptor(value = List.class, collectionElement = MultiSignCoinToDTO.class), parameterDes = "交易接受方数据"), @Parameter(parameterName = "remark", parameterType = "String", parameterDes = "交易备注"), @Parameter(parameterName = "signAddress", parameterType = "String", canNull = true, parameterDes = "第一个签名账户地址(不填则只创建交易不签名)"), @Parameter(parameterName = "signPassword", parameterType = "String", canNull = true, parameterDes = "第一个签名账户密码(不填则只创建交易不签名)") }) @ResponseData(name = "返回值", description = "返回一个Map,包含三个key", responseType = @TypeDescriptor(value = Map.class, mapKeys = { @Key(name = "tx", description = "完整交易序列化字符串,如果交易没达到最小签名数可继续签名"), @Key(name = "txHash", description = "交易hash"), @Key(name = "completed", valueType = boolean.class, description = "true:交易已完成(已广播),false:交易没完成,没有达到最小签名数") })) Response multiSignTransfer(Map params); @CmdAnnotation(cmd = "ac_signMultiSignTransaction", version = 1.0, description = "多签交易签名/sign MultiSign Transaction") @Parameters(value = { @Parameter(parameterName = "chainId", requestType = @TypeDescriptor(value = int.class), parameterDes = "链id"), @Parameter(parameterName = "tx", parameterType = "String", parameterDes = "交易数据字符串"), @Parameter(parameterName = "signAddress", parameterType = "String", parameterDes = "签名账户地址"), @Parameter(parameterName = "signPassword", parameterType = "String", parameterDes = "签名账户密码") }) @ResponseData(name = "返回值", description = "返回一个Map,包含三个key", responseType = @TypeDescriptor(value = Map.class, mapKeys = { @Key(name = "tx", description = "完整交易序列化字符串,如果交易没达到最小签名数可继续签名"), @Key(name = "txHash", description = "交易hash"), @Key(name = "completed", valueType = boolean.class, description = "true:交易已完成(已广播),false:交易没完成,没有达到最小签名数") })) Response signMultiSignTransaction(Map params); }
TransactionCmd extends BaseCmd { @CmdAnnotation(cmd = "ac_signMultiSignTransaction", version = 1.0, description = "多签交易签名/sign MultiSign Transaction") @Parameters(value = { @Parameter(parameterName = "chainId", requestType = @TypeDescriptor(value = int.class), parameterDes = "链id"), @Parameter(parameterName = "tx", parameterType = "String", parameterDes = "交易数据字符串"), @Parameter(parameterName = "signAddress", parameterType = "String", parameterDes = "签名账户地址"), @Parameter(parameterName = "signPassword", parameterType = "String", parameterDes = "签名账户密码") }) @ResponseData(name = "返回值", description = "返回一个Map,包含三个key", responseType = @TypeDescriptor(value = Map.class, mapKeys = { @Key(name = "tx", description = "完整交易序列化字符串,如果交易没达到最小签名数可继续签名"), @Key(name = "txHash", description = "交易hash"), @Key(name = "completed", valueType = boolean.class, description = "true:交易已完成(已广播),false:交易没完成,没有达到最小签名数") })) public Response signMultiSignTransaction(Map params) { Chain chain = null; Object chainIdObj = params == null ? null : params.get(RpcParameterNameConstant.CHAIN_ID); Object passwordObj = params == null ? null : params.get(RpcParameterNameConstant.SIGN_PASSWORD); Object signAddressObj = params == null ? null : params.get(RpcParameterNameConstant.SIGN_ADDREESS); Object txStrObj = params == null ? null : params.get(RpcParameterNameConstant.TX); try { if (params == null || chainIdObj == null || signAddressObj == null || txStrObj == null) { LoggerUtil.LOG.warn("ac_signMultiSignTransaction params is null"); throw new NulsRuntimeException(AccountErrorCode.NULL_PARAMETER); } chain = chainManager.getChain((Integer) chainIdObj); if (null == chain) { throw new NulsRuntimeException(AccountErrorCode.CHAIN_NOT_EXIST); } int chainId = chain.getChainId(); String password = (String) passwordObj; String signAddress = (String) signAddressObj; String txStr = (String) txStrObj; Account account = accountService.getAccount(chainId, signAddress); if (account == null) { throw new NulsRuntimeException(AccountErrorCode.ACCOUNT_NOT_EXIST); } MultiSignTransactionResultDTO multiSignTransactionResultDto = transactionService.signMultiSignTransaction(chain, account, password, txStr); boolean result = false; if (multiSignTransactionResultDto.isBroadcasted()) { result = true; } Transaction tx = multiSignTransactionResultDto.getTransaction(); Map<String, Object> map = new HashMap<>(AccountConstant.INIT_CAPACITY_8); map.put("completed", result); map.put("txHash", tx.getHash().toHex()); map.put("tx", RPCUtil.encode(tx.serialize())); return success(map); } catch (NulsRuntimeException e) { errorLogProcess(chain, e); return failed(e.getErrorCode()); } catch (NulsException e) { errorLogProcess(chain, e); return failed(e.getErrorCode()); } catch (Exception e) { errorLogProcess(chain, e); return failed(AccountErrorCode.SYS_UNKOWN_EXCEPTION); } }  @CmdAnnotation(cmd = "ac_transfer", version = 1.0, description = "创建普通转账交易/create transfer transaction") @Parameters(value = { @Parameter(parameterName = "chainId", requestType = @TypeDescriptor(value = int.class), parameterDes = "链id"), @Parameter(parameterName = "inputs", requestType = @TypeDescriptor(value = List.class, collectionElement = CoinDTO.class), parameterDes = "交易支付方数据"), @Parameter(parameterName = "outputs", requestType = @TypeDescriptor(value = List.class, collectionElement = CoinDTO.class), parameterDes = "交易接受方数据"), @Parameter(parameterName = "remark", parameterType = "String", parameterDes = "交易备注") }) @ResponseData(name = "返回值", description = "返回一个Map", responseType = @TypeDescriptor(value = Map.class, mapKeys = { @Key(name = RpcConstant.VALUE, description = "交易hash") })) Response transfer(Map params); @CmdAnnotation(cmd = "ac_createMultiSignTransfer", version = 1.0, description = "创建多签地址转账交易/create multi sign transfer") @Parameters(value = { @Parameter(parameterName = "chainId", requestType = @TypeDescriptor(value = int.class), parameterDes = "链id"), @Parameter(parameterName = "inputs", requestType = @TypeDescriptor(value = List.class, collectionElement = BaseCoinDTO.class), parameterDes = "交易支付方数据"), @Parameter(parameterName = "outputs", requestType = @TypeDescriptor(value = List.class, collectionElement = MultiSignCoinToDTO.class), parameterDes = "交易接受方数据"), @Parameter(parameterName = "remark", parameterType = "String", parameterDes = "交易备注"), @Parameter(parameterName = "signAddress", parameterType = "String", canNull = true, parameterDes = "第一个签名账户地址(不填则只创建交易不签名)"), @Parameter(parameterName = "signPassword", parameterType = "String", canNull = true, parameterDes = "第一个签名账户密码(不填则只创建交易不签名)") }) @ResponseData(name = "返回值", description = "返回一个Map,包含三个key", responseType = @TypeDescriptor(value = Map.class, mapKeys = { @Key(name = "tx", description = "完整交易序列化字符串,如果交易没达到最小签名数可继续签名"), @Key(name = "txHash", description = "交易hash"), @Key(name = "completed", valueType = boolean.class, description = "true:交易已完成(已广播),false:交易没完成,没有达到最小签名数") })) Response multiSignTransfer(Map params); @CmdAnnotation(cmd = "ac_signMultiSignTransaction", version = 1.0, description = "多签交易签名/sign MultiSign Transaction") @Parameters(value = { @Parameter(parameterName = "chainId", requestType = @TypeDescriptor(value = int.class), parameterDes = "链id"), @Parameter(parameterName = "tx", parameterType = "String", parameterDes = "交易数据字符串"), @Parameter(parameterName = "signAddress", parameterType = "String", parameterDes = "签名账户地址"), @Parameter(parameterName = "signPassword", parameterType = "String", parameterDes = "签名账户密码") }) @ResponseData(name = "返回值", description = "返回一个Map,包含三个key", responseType = @TypeDescriptor(value = Map.class, mapKeys = { @Key(name = "tx", description = "完整交易序列化字符串,如果交易没达到最小签名数可继续签名"), @Key(name = "txHash", description = "交易hash"), @Key(name = "completed", valueType = boolean.class, description = "true:交易已完成(已广播),false:交易没完成,没有达到最小签名数") })) Response signMultiSignTransaction(Map params);  }