WIP: trade-bot: add missing JavaTypeAdapter to TradeBotData.bitcoinAmount

Also: unify "receiveAddress" to "receivingAddress"

Fix missed changes from "recipient" to "partner" in BTCACCT, etc.
This commit is contained in:
catbref 2020-08-03 15:52:17 +01:00
parent ea9b0d4588
commit a351756883
7 changed files with 56 additions and 54 deletions

View File

@ -26,7 +26,7 @@ public class CrossChainBitcoinRedeemRequest {
public byte[] secret; public byte[] secret;
@Schema(description = "Bitcoin HASH160(public key) for receiving funds, or omit to derive from private key", example = "u17kBVKkKSp12oUzaxFwNnq1JZf") @Schema(description = "Bitcoin HASH160(public key) for receiving funds, or omit to derive from private key", example = "u17kBVKkKSp12oUzaxFwNnq1JZf")
public byte[] receivePublicKeyHash; public byte[] receivingAccountInfo;
public CrossChainBitcoinRedeemRequest() { public CrossChainBitcoinRedeemRequest() {
} }

View File

@ -28,7 +28,7 @@ public class TradeBotCreateRequest {
public int tradeTimeout; public int tradeTimeout;
@Schema(description = "Bitcoin address for receiving", example = "1NCTG9oLk41bU6pcehLNo9DVJup77EHAVx") @Schema(description = "Bitcoin address for receiving", example = "1NCTG9oLk41bU6pcehLNo9DVJup77EHAVx")
public String receiveAddress; public String receivingAddress;
public TradeBotCreateRequest() { public TradeBotCreateRequest() {
} }

View File

@ -853,10 +853,10 @@ public class CrossChainResource {
if (redeemRequest.secret == null || redeemRequest.secret.length != BTCACCT.SECRET_LENGTH) if (redeemRequest.secret == null || redeemRequest.secret.length != BTCACCT.SECRET_LENGTH)
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA);
if (redeemRequest.receivePublicKeyHash == null) if (redeemRequest.receivingAccountInfo == null)
redeemRequest.receivePublicKeyHash = redeemKey.getPubKeyHash(); redeemRequest.receivingAccountInfo = redeemKey.getPubKeyHash();
if (redeemRequest.receivePublicKeyHash.length != 20) if (redeemRequest.receivingAccountInfo.length != 20)
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PUBLIC_KEY); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PUBLIC_KEY);
// Extract data from cross-chain trading AT // Extract data from cross-chain trading AT
@ -899,7 +899,7 @@ public class CrossChainResource {
Coin redeemAmount = Coin.valueOf(p2shBalance - redeemRequest.bitcoinMinerFee.unscaledValue().longValue()); Coin redeemAmount = Coin.valueOf(p2shBalance - redeemRequest.bitcoinMinerFee.unscaledValue().longValue());
org.bitcoinj.core.Transaction redeemTransaction = BTCP2SH.buildRedeemTransaction(redeemAmount, redeemKey, fundingOutputs, redeemScriptBytes, redeemRequest.secret, redeemRequest.receivePublicKeyHash); org.bitcoinj.core.Transaction redeemTransaction = BTCP2SH.buildRedeemTransaction(redeemAmount, redeemKey, fundingOutputs, redeemScriptBytes, redeemRequest.secret, redeemRequest.receivingAccountInfo);
boolean wasBroadcast = BTC.getInstance().broadcastTransaction(redeemTransaction); boolean wasBroadcast = BTC.getInstance().broadcastTransaction(redeemTransaction);
if (!wasBroadcast) if (!wasBroadcast)
@ -961,15 +961,15 @@ public class CrossChainResource {
public String tradeBotCreator(TradeBotCreateRequest tradeBotCreateRequest) { public String tradeBotCreator(TradeBotCreateRequest tradeBotCreateRequest) {
Security.checkApiCallAllowed(request); Security.checkApiCallAllowed(request);
Address receiveAddress; Address receivingAddress;
try { try {
receiveAddress = Address.fromString(BTC.getInstance().getNetworkParameters(), tradeBotCreateRequest.receiveAddress); receivingAddress = Address.fromString(BTC.getInstance().getNetworkParameters(), tradeBotCreateRequest.receivingAddress);
} catch (AddressFormatException e) { } catch (AddressFormatException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
} }
// We only support P2PKH addresses at this time // We only support P2PKH addresses at this time
if (receiveAddress.getOutputScriptType() != ScriptType.P2PKH) if (receivingAddress.getOutputScriptType() != ScriptType.P2PKH)
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
if (tradeBotCreateRequest.tradeTimeout < 60) if (tradeBotCreateRequest.tradeTimeout < 60)

View File

@ -108,17 +108,17 @@ public class TradeBot {
byte[] tradeForeignPublicKey = deriveTradeForeignPublicKey(tradePrivateKey); byte[] tradeForeignPublicKey = deriveTradeForeignPublicKey(tradePrivateKey);
byte[] tradeForeignPublicKeyHash = Crypto.hash160(tradeForeignPublicKey); byte[] tradeForeignPublicKeyHash = Crypto.hash160(tradeForeignPublicKey);
// Convert Bitcoin receive address into public key hash (we only support P2PKH at this time) // Convert Bitcoin receiving address into public key hash (we only support P2PKH at this time)
Address bitcoinReceiveAddress; Address bitcoinReceivingAddress;
try { try {
bitcoinReceiveAddress = Address.fromString(BTC.getInstance().getNetworkParameters(), tradeBotCreateRequest.receiveAddress); bitcoinReceivingAddress = Address.fromString(BTC.getInstance().getNetworkParameters(), tradeBotCreateRequest.receivingAddress);
} catch (AddressFormatException e) { } catch (AddressFormatException e) {
throw new DataException("Unsupported Bitcoin receive address: " + tradeBotCreateRequest.receiveAddress); throw new DataException("Unsupported Bitcoin receiving address: " + tradeBotCreateRequest.receivingAddress);
} }
if (bitcoinReceiveAddress.getOutputScriptType() != ScriptType.P2PKH) if (bitcoinReceivingAddress.getOutputScriptType() != ScriptType.P2PKH)
throw new DataException("Unsupported Bitcoin receive address: " + tradeBotCreateRequest.receiveAddress); throw new DataException("Unsupported Bitcoin receiving address: " + tradeBotCreateRequest.receivingAddress);
byte[] bitcoinReceivePublicKeyHash = bitcoinReceiveAddress.getHash(); byte[] bitcoinReceivingAccountInfo = bitcoinReceivingAddress.getHash();
PublicKeyAccount creator = new PublicKeyAccount(repository, tradeBotCreateRequest.creatorPublicKey); PublicKeyAccount creator = new PublicKeyAccount(repository, tradeBotCreateRequest.creatorPublicKey);
@ -151,7 +151,7 @@ public class TradeBot {
tradeNativePublicKey, tradeNativePublicKeyHash, tradeNativeAddress, tradeNativePublicKey, tradeNativePublicKeyHash, tradeNativeAddress,
secretB, hashOfSecretB, secretB, hashOfSecretB,
tradeForeignPublicKey, tradeForeignPublicKeyHash, tradeForeignPublicKey, tradeForeignPublicKeyHash,
tradeBotCreateRequest.bitcoinAmount, null, null, null, bitcoinReceivePublicKeyHash); tradeBotCreateRequest.bitcoinAmount, null, null, null, bitcoinReceivingAccountInfo);
repository.getCrossChainRepository().save(tradeBotData); repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges(); repository.saveChanges();
@ -718,9 +718,9 @@ public class TradeBot {
Coin redeemAmount = Coin.ZERO; // The real funds are in P2SH-A Coin redeemAmount = Coin.ZERO; // The real funds are in P2SH-A
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey()); ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = BTC.getInstance().getUnspentOutputs(p2shAddress); List<TransactionOutput> fundingOutputs = BTC.getInstance().getUnspentOutputs(p2shAddress);
byte[] receivePublicKeyHash = tradeBotData.getReceivingAccountInfo(); byte[] receivingAccountInfo = tradeBotData.getReceivingAccountInfo();
Transaction p2shRedeemTransaction = BTCP2SH.buildRedeemTransaction(redeemAmount, redeemKey, fundingOutputs, redeemScriptBytes, tradeBotData.getSecret(), receivePublicKeyHash); Transaction p2shRedeemTransaction = BTCP2SH.buildRedeemTransaction(redeemAmount, redeemKey, fundingOutputs, redeemScriptBytes, tradeBotData.getSecret(), receivingAccountInfo);
if (!BTC.getInstance().broadcastTransaction(p2shRedeemTransaction)) { if (!BTC.getInstance().broadcastTransaction(p2shRedeemTransaction)) {
// We couldn't redeem P2SH-B at this time // We couldn't redeem P2SH-B at this time
@ -787,8 +787,8 @@ public class TradeBot {
// Send 'redeem' MESSAGE to AT using both secrets // Send 'redeem' MESSAGE to AT using both secrets
byte[] secretA = tradeBotData.getSecret(); byte[] secretA = tradeBotData.getSecret();
String qortalReceiveAddress = Base58.encode(tradeBotData.getReceivingAccountInfo()); // Actually contains whole address, not just PKH String qortalReceivingAddress = Base58.encode(tradeBotData.getReceivingAccountInfo()); // Actually contains whole address, not just PKH
byte[] messageData = BTCACCT.buildRedeemMessage(secretA, secretB, qortalReceiveAddress); byte[] messageData = BTCACCT.buildRedeemMessage(secretA, secretB, qortalReceivingAddress);
PrivateKeyAccount sender = new PrivateKeyAccount(repository, tradeBotData.getTradePrivateKey()); PrivateKeyAccount sender = new PrivateKeyAccount(repository, tradeBotData.getTradePrivateKey());
MessageTransaction messageTransaction = MessageTransaction.build(repository, sender, Group.NO_GROUP, tradeBotData.getAtAddress(), messageData, false, false); MessageTransaction messageTransaction = MessageTransaction.build(repository, sender, Group.NO_GROUP, tradeBotData.getAtAddress(), messageData, false, false);
@ -809,10 +809,10 @@ public class TradeBot {
repository.getCrossChainRepository().save(tradeBotData); repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges(); repository.saveChanges();
String receiveAddress = tradeBotData.getTradeNativeAddress(); String receivingAddress = tradeBotData.getTradeNativeAddress();
LOGGER.info(() -> String.format("P2SH-B %s redeemed, using secrets to redeem AT %s. Funds should arrive at %s", LOGGER.info(() -> String.format("P2SH-B %s redeemed, using secrets to redeem AT %s. Funds should arrive at %s",
p2shAddress, tradeBotData.getAtAddress(), receiveAddress)); p2shAddress, tradeBotData.getAtAddress(), receivingAddress));
} }
/** /**
@ -873,9 +873,9 @@ public class TradeBot {
Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedBitcoin); Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedBitcoin);
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey()); ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = BTC.getInstance().getUnspentOutputs(p2shAddress); List<TransactionOutput> fundingOutputs = BTC.getInstance().getUnspentOutputs(p2shAddress);
byte[] receivePublicKeyHash = tradeBotData.getReceivingAccountInfo(); byte[] receivingAccountInfo = tradeBotData.getReceivingAccountInfo();
Transaction p2shRedeemTransaction = BTCP2SH.buildRedeemTransaction(redeemAmount, redeemKey, fundingOutputs, redeemScriptBytes, secretA, receivePublicKeyHash); Transaction p2shRedeemTransaction = BTCP2SH.buildRedeemTransaction(redeemAmount, redeemKey, fundingOutputs, redeemScriptBytes, secretA, receivingAccountInfo);
if (!BTC.getInstance().broadcastTransaction(p2shRedeemTransaction)) { if (!BTC.getInstance().broadcastTransaction(p2shRedeemTransaction)) {
// We couldn't redeem P2SH-A at this time // We couldn't redeem P2SH-A at this time
@ -887,9 +887,9 @@ public class TradeBot {
repository.getCrossChainRepository().save(tradeBotData); repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges(); repository.saveChanges();
String receiveAddress = BTC.getInstance().pkhToAddress(receivePublicKeyHash); String receivingAddress = BTC.getInstance().pkhToAddress(receivingAccountInfo);
LOGGER.info(() -> String.format("P2SH-A %s redeemed. Funds should arrive at %s", tradeBotData.getAtAddress(), receiveAddress)); LOGGER.info(() -> String.format("P2SH-A %s redeemed. Funds should arrive at %s", tradeBotData.getAtAddress(), receivingAddress));
} }
/** /**

View File

@ -88,10 +88,10 @@ import com.google.common.primitives.Bytes;
* <ul> * <ul>
* <li>secret-A</li> * <li>secret-A</li>
* <li>secret-B</li> * <li>secret-B</li>
* <li>Qortal receive address of her chosing</li> * <li>Qortal receiving address of her chosing</li>
* </ul> * </ul>
* </li> * </li>
* <li>AT's QORT funds are sent to Qortal receive address</li> * <li>AT's QORT funds are sent to Qortal receiving address</li>
* </ul> * </ul>
* </li> * </li>
* <li>Bob checks AT, extracts secret-A * <li>Bob checks AT, extracts secret-A
@ -124,7 +124,7 @@ public class BTCACCT {
+ 8 /*lockTimeB*/ + 8 /*lockTimeB*/
+ 24 /*hash of secret-A (padded from 20 to 24)*/ + 24 /*hash of secret-A (padded from 20 to 24)*/
+ 8 /*lockTimeA*/; + 8 /*lockTimeA*/;
public static final int REDEEM_MESSAGE_LENGTH = 32 /*secret*/ + 32 /*secret*/ + 32 /*partner's Qortal receive address padded from 25 to 32*/; public static final int REDEEM_MESSAGE_LENGTH = 32 /*secret*/ + 32 /*secret*/ + 32 /*partner's Qortal receiving address padded from 25 to 32*/;
public static final int CANCEL_MESSAGE_LENGTH = 32 /*AT creator's Qortal address*/; public static final int CANCEL_MESSAGE_LENGTH = 32 /*AT creator's Qortal address*/;
public enum Mode { public enum Mode {
@ -195,7 +195,7 @@ public class BTCACCT {
final int addrHashOfSecretAPointer = addrCounter++; final int addrHashOfSecretAPointer = addrCounter++;
final int addrRedeemMessageSecretBOffset = addrCounter++; final int addrRedeemMessageSecretBOffset = addrCounter++;
final int addrRedeemMessageReceiveAddressOffset = addrCounter++; final int addrRedeemMessageReceivingAddressOffset = addrCounter++;
final int addrMessageDataPointer = addrCounter++; final int addrMessageDataPointer = addrCounter++;
final int addrMessageDataLength = addrCounter++; final int addrMessageDataLength = addrCounter++;
@ -290,7 +290,7 @@ public class BTCACCT {
assert dataByteBuffer.position() == addrHashOfSecretBPointer * MachineState.VALUE_SIZE : "addrHashOfSecretBPointer incorrect"; assert dataByteBuffer.position() == addrHashOfSecretBPointer * MachineState.VALUE_SIZE : "addrHashOfSecretBPointer incorrect";
dataByteBuffer.putLong(addrHashOfSecretB); dataByteBuffer.putLong(addrHashOfSecretB);
// Index into data segment of recipient address, used by SET_B_IND // Index into data segment of partner's Qortal address, used by SET_B_IND
assert dataByteBuffer.position() == addrQortalPartnerAddressPointer * MachineState.VALUE_SIZE : "addrQortalPartnerAddressPointer incorrect"; assert dataByteBuffer.position() == addrQortalPartnerAddressPointer * MachineState.VALUE_SIZE : "addrQortalPartnerAddressPointer incorrect";
dataByteBuffer.putLong(addrQortalPartnerAddress1); dataByteBuffer.putLong(addrQortalPartnerAddress1);
@ -318,8 +318,8 @@ public class BTCACCT {
assert dataByteBuffer.position() == addrRedeemMessageSecretBOffset * MachineState.VALUE_SIZE : "addrRedeemMessageSecretBOffset incorrect"; assert dataByteBuffer.position() == addrRedeemMessageSecretBOffset * MachineState.VALUE_SIZE : "addrRedeemMessageSecretBOffset incorrect";
dataByteBuffer.putLong(32L); dataByteBuffer.putLong(32L);
// Offset into 'redeem' MESSAGE data payload for extracting Qortal receive address // Offset into 'redeem' MESSAGE data payload for extracting Qortal receiving address
assert dataByteBuffer.position() == addrRedeemMessageReceiveAddressOffset * MachineState.VALUE_SIZE : "addrRedeemMessageReceiveAddressOffset incorrect"; assert dataByteBuffer.position() == addrRedeemMessageReceivingAddressOffset * MachineState.VALUE_SIZE : "addrRedeemMessageReceivingAddressOffset incorrect";
dataByteBuffer.putLong(64L); dataByteBuffer.putLong(64L);
// Source location and length for hashing any passed secret // Source location and length for hashing any passed secret
@ -540,12 +540,12 @@ public class BTCACCT {
codeByteBuffer.put(OpCode.BNZ_DAT.compile(addrResult, calcOffset(codeByteBuffer, labelPayout))); codeByteBuffer.put(OpCode.BNZ_DAT.compile(addrResult, calcOffset(codeByteBuffer, labelPayout)));
codeByteBuffer.put(OpCode.JMP_ADR.compile(labelRedeemTxnLoop == null ? 0 : labelRedeemTxnLoop)); codeByteBuffer.put(OpCode.JMP_ADR.compile(labelRedeemTxnLoop == null ? 0 : labelRedeemTxnLoop));
/* Success! Pay arranged amount to receive address */ /* Success! Pay arranged amount to receiving address */
labelPayout = codeByteBuffer.position(); labelPayout = codeByteBuffer.position();
// Extract Qortal receive address from next 32 bytes of message from transaction into B register // Extract Qortal receiving address from next 32 bytes of message from transaction into B register
codeByteBuffer.put(OpCode.EXT_FUN_DAT.compile(QortalFunctionCode.PUT_PARTIAL_MESSAGE_FROM_TX_IN_A_INTO_B.value, addrRedeemMessageReceiveAddressOffset)); codeByteBuffer.put(OpCode.EXT_FUN_DAT.compile(QortalFunctionCode.PUT_PARTIAL_MESSAGE_FROM_TX_IN_A_INTO_B.value, addrRedeemMessageReceivingAddressOffset));
// Pay AT's balance to recipient // Pay AT's balance to receiving address
codeByteBuffer.put(OpCode.EXT_FUN_DAT.compile(FunctionCode.PAY_TO_ADDRESS_IN_B, addrQortAmount)); codeByteBuffer.put(OpCode.EXT_FUN_DAT.compile(FunctionCode.PAY_TO_ADDRESS_IN_B, addrQortAmount));
// Set redeemed mode // Set redeemed mode
codeByteBuffer.put(OpCode.SET_VAL.compile(addrMode, Mode.REDEEMED.value)); codeByteBuffer.put(OpCode.SET_VAL.compile(addrMode, Mode.REDEEMED.value));
@ -678,7 +678,7 @@ public class BTCACCT {
// Skip pointer to message sender // Skip pointer to message sender
dataByteBuffer.position(dataByteBuffer.position() + 8); dataByteBuffer.position(dataByteBuffer.position() + 8);
// Skip 'trade' message data offset for recipient's bitcoin PKH // Skip 'trade' message data offset for partner's bitcoin PKH
dataByteBuffer.position(dataByteBuffer.position() + 8); dataByteBuffer.position(dataByteBuffer.position() + 8);
// Skip pointer to partner's bitcoin PKH // Skip pointer to partner's bitcoin PKH
@ -693,7 +693,7 @@ public class BTCACCT {
// Skip 'redeem' message data offset for secret-B // Skip 'redeem' message data offset for secret-B
dataByteBuffer.position(dataByteBuffer.position() + 8); dataByteBuffer.position(dataByteBuffer.position() + 8);
// Skip 'redeem' message data offset for partner's Qortal receive address // Skip 'redeem' message data offset for partner's Qortal receiving address
dataByteBuffer.position(dataByteBuffer.position() + 8); dataByteBuffer.position(dataByteBuffer.position() + 8);
// Skip pointer to message data // Skip pointer to message data
@ -751,9 +751,9 @@ public class BTCACCT {
dataByteBuffer.position(dataByteBuffer.position() + 32 - hashOfSecretA.length); // skip to 32 bytes dataByteBuffer.position(dataByteBuffer.position() + 32 - hashOfSecretA.length); // skip to 32 bytes
// Potential partner's Bitcoin PKH // Potential partner's Bitcoin PKH
byte[] recipientBitcoinPKH = new byte[20]; byte[] partnerBitcoinPKH = new byte[20];
dataByteBuffer.get(recipientBitcoinPKH); dataByteBuffer.get(partnerBitcoinPKH);
dataByteBuffer.position(dataByteBuffer.position() + 32 - recipientBitcoinPKH.length); // skip to 32 bytes dataByteBuffer.position(dataByteBuffer.position() + 32 - partnerBitcoinPKH.length); // skip to 32 bytes
long modeValue = dataByteBuffer.getLong(); long modeValue = dataByteBuffer.getLong();
Mode mode = Mode.valueOf((int) (modeValue & 0xffL)); Mode mode = Mode.valueOf((int) (modeValue & 0xffL));
@ -764,7 +764,7 @@ public class BTCACCT {
tradeData.tradeRefundHeight = new Timestamp(tradeRefundTimestamp).blockHeight; tradeData.tradeRefundHeight = new Timestamp(tradeRefundTimestamp).blockHeight;
tradeData.qortalPartnerAddress = qortalRecipient; tradeData.qortalPartnerAddress = qortalRecipient;
tradeData.hashOfSecretA = hashOfSecretA; tradeData.hashOfSecretA = hashOfSecretA;
tradeData.partnerBitcoinPKH = recipientBitcoinPKH; tradeData.partnerBitcoinPKH = partnerBitcoinPKH;
tradeData.lockTimeA = lockTimeA; tradeData.lockTimeA = lockTimeA;
tradeData.lockTimeB = lockTimeB; tradeData.lockTimeB = lockTimeB;
} else { } else {
@ -775,9 +775,9 @@ public class BTCACCT {
} }
/** Returns 'offer' MESSAGE payload for trade partner to send to AT creator's trade address. */ /** Returns 'offer' MESSAGE payload for trade partner to send to AT creator's trade address. */
public static byte[] buildOfferMessage(byte[] recipientBitcoinPKH, byte[] hashOfSecretA, int lockTimeA) { public static byte[] buildOfferMessage(byte[] partnerBitcoinPKH, byte[] hashOfSecretA, int lockTimeA) {
byte[] lockTimeABytes = BitTwiddling.toBEByteArray((long) lockTimeA); byte[] lockTimeABytes = BitTwiddling.toBEByteArray((long) lockTimeA);
return Bytes.concat(recipientBitcoinPKH, hashOfSecretA, lockTimeABytes); return Bytes.concat(partnerBitcoinPKH, hashOfSecretA, lockTimeABytes);
} }
/** Returns info extracted from 'offer' MESSAGE payload sent by trade partner to AT creator's trade address, or null if not valid. */ /** Returns info extracted from 'offer' MESSAGE payload sent by trade partner to AT creator's trade address, or null if not valid. */
@ -796,11 +796,11 @@ public class BTCACCT {
/** Returns 'trade' MESSAGE payload for AT creator to send to AT. */ /** Returns 'trade' MESSAGE payload for AT creator to send to AT. */
public static byte[] buildTradeMessage(String partnerQortalTradeAddress, byte[] partnerBitcoinPKH, byte[] hashOfSecretA, int lockTimeA, int lockTimeB) { public static byte[] buildTradeMessage(String partnerQortalTradeAddress, byte[] partnerBitcoinPKH, byte[] hashOfSecretA, int lockTimeA, int lockTimeB) {
byte[] data = new byte[TRADE_MESSAGE_LENGTH]; byte[] data = new byte[TRADE_MESSAGE_LENGTH];
byte[] recipientQortalAddressBytes = Base58.decode(partnerQortalTradeAddress); byte[] partnerQortalAddressBytes = Base58.decode(partnerQortalTradeAddress);
byte[] lockTimeABytes = BitTwiddling.toBEByteArray((long) lockTimeA); byte[] lockTimeABytes = BitTwiddling.toBEByteArray((long) lockTimeA);
byte[] lockTimeBBytes = BitTwiddling.toBEByteArray((long) lockTimeB); byte[] lockTimeBBytes = BitTwiddling.toBEByteArray((long) lockTimeB);
System.arraycopy(recipientQortalAddressBytes, 0, data, 0, recipientQortalAddressBytes.length); System.arraycopy(partnerQortalAddressBytes, 0, data, 0, partnerQortalAddressBytes.length);
System.arraycopy(partnerBitcoinPKH, 0, data, 32, partnerBitcoinPKH.length); System.arraycopy(partnerBitcoinPKH, 0, data, 32, partnerBitcoinPKH.length);
System.arraycopy(lockTimeBBytes, 0, data, 56, lockTimeBBytes.length); System.arraycopy(lockTimeBBytes, 0, data, 56, lockTimeBBytes.length);
System.arraycopy(hashOfSecretA, 0, data, 64, hashOfSecretA.length); System.arraycopy(hashOfSecretA, 0, data, 64, hashOfSecretA.length);
@ -820,13 +820,13 @@ public class BTCACCT {
} }
/** Returns 'redeem' MESSAGE payload for trade partner/ to send to AT. */ /** Returns 'redeem' MESSAGE payload for trade partner/ to send to AT. */
public static byte[] buildRedeemMessage(byte[] secretA, byte[] secretB, String qortalReceiveAddress) { public static byte[] buildRedeemMessage(byte[] secretA, byte[] secretB, String qortalReceivingAddress) {
byte[] data = new byte[REDEEM_MESSAGE_LENGTH]; byte[] data = new byte[REDEEM_MESSAGE_LENGTH];
byte[] qortalReceiveAddressBytes = Base58.decode(qortalReceiveAddress); byte[] qortalReceivingAddressBytes = Base58.decode(qortalReceivingAddress);
System.arraycopy(secretA, 0, data, 0, secretA.length); System.arraycopy(secretA, 0, data, 0, secretA.length);
System.arraycopy(secretB, 0, data, 32, secretB.length); System.arraycopy(secretB, 0, data, 32, secretB.length);
System.arraycopy(qortalReceiveAddressBytes, 0, data, 64, qortalReceiveAddressBytes.length); System.arraycopy(qortalReceivingAddressBytes, 0, data, 64, qortalReceivingAddressBytes.length);
return data; return data;
} }

View File

@ -163,10 +163,10 @@ public class BTCP2SH {
* @param fundingOutput output from transaction that funded P2SH address * @param fundingOutput output from transaction that funded P2SH address
* @param redeemScriptBytes the redeemScript itself, in byte[] form * @param redeemScriptBytes the redeemScript itself, in byte[] form
* @param secret actual 32-byte secret used when building redeemScript * @param secret actual 32-byte secret used when building redeemScript
* @param receivePublicKeyHash PKH used for output * @param receivingAccountInfo Bitcoin PKH used for output
* @return Signed Bitcoin transaction for redeeming P2SH * @return Signed Bitcoin transaction for redeeming P2SH
*/ */
public static Transaction buildRedeemTransaction(Coin redeemAmount, ECKey redeemKey, List<TransactionOutput> fundingOutputs, byte[] redeemScriptBytes, byte[] secret, byte[] receivePublicKeyHash) { public static Transaction buildRedeemTransaction(Coin redeemAmount, ECKey redeemKey, List<TransactionOutput> fundingOutputs, byte[] redeemScriptBytes, byte[] secret, byte[] receivingAccountInfo) {
Function<byte[], Script> redeemSigScriptBuilder = (txSigBytes) -> { Function<byte[], Script> redeemSigScriptBuilder = (txSigBytes) -> {
// Build scriptSig with... // Build scriptSig with...
ScriptBuilder scriptBuilder = new ScriptBuilder(); ScriptBuilder scriptBuilder = new ScriptBuilder();
@ -187,7 +187,7 @@ public class BTCP2SH {
return scriptBuilder.build(); return scriptBuilder.build();
}; };
return buildP2shTransaction(redeemAmount, redeemKey, fundingOutputs, redeemScriptBytes, null, redeemSigScriptBuilder, receivePublicKeyHash); return buildP2shTransaction(redeemAmount, redeemKey, fundingOutputs, redeemScriptBytes, null, redeemSigScriptBuilder, receivingAccountInfo);
} }
/** Returns 'secret', if any, given list of raw bitcoin transactions. */ /** Returns 'secret', if any, given list of raw bitcoin transactions. */

View File

@ -8,6 +8,7 @@ import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@ -46,6 +47,7 @@ public class TradeBotData {
private byte[] tradeForeignPublicKey; private byte[] tradeForeignPublicKey;
private byte[] tradeForeignPublicKeyHash; private byte[] tradeForeignPublicKeyHash;
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
private long bitcoinAmount; private long bitcoinAmount;
// Never expose this via API // Never expose this via API