forked from Qortal/qortal
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a95a37277c | ||
|
8aed84e6af | ||
|
b1f184c493 | ||
|
d66dd51bf6 | ||
|
0baed55a44 |
2
pom.xml
2
pom.xml
@@ -7,7 +7,7 @@
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<skipTests>true</skipTests>
|
||||
<altcoinj.version>6628cfd</altcoinj.version>
|
||||
<altcoinj.version>02e0d3d</altcoinj.version>
|
||||
<bitcoinj.version>0.15.10</bitcoinj.version>
|
||||
<bouncycastle.version>1.64</bouncycastle.version>
|
||||
<build.timestamp>${maven.build.timestamp}</build.timestamp>
|
||||
|
@@ -7,23 +7,23 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class RavencoinSendRequest {
|
||||
public class DigibyteSendRequest {
|
||||
|
||||
@Schema(description = "Ravencoin BIP32 extended private key", example = "tprv___________________________________________________________________________________________________________")
|
||||
@Schema(description = "Digibyte BIP32 extended private key", example = "tprv___________________________________________________________________________________________________________")
|
||||
public String xprv58;
|
||||
|
||||
@Schema(description = "Recipient's Ravencoin address ('legacy' P2PKH only)", example = "1RvnCoinEaterAddressDontSendf59kuE")
|
||||
@Schema(description = "Recipient's Digibyte address ('legacy' P2PKH only)", example = "1DigByteEaterAddressDontSendf59kuE")
|
||||
public String receivingAddress;
|
||||
|
||||
@Schema(description = "Amount of RVN to send", type = "number")
|
||||
@Schema(description = "Amount of DGB to send", type = "number")
|
||||
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
|
||||
public long ravencoinAmount;
|
||||
public long digibyteAmount;
|
||||
|
||||
@Schema(description = "Transaction fee per byte (optional). Default is 0.00000100 RVN (100 sats) per byte", example = "0.00000100", type = "number")
|
||||
@Schema(description = "Transaction fee per byte (optional). Default is 0.00000100 DGB (100 sats) per byte", example = "0.00000100", type = "number")
|
||||
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
|
||||
public Long feePerByte;
|
||||
|
||||
public RavencoinSendRequest() {
|
||||
public DigibyteSendRequest() {
|
||||
}
|
||||
|
||||
}
|
@@ -23,14 +23,14 @@ import org.qortal.api.ApiError;
|
||||
import org.qortal.api.ApiErrors;
|
||||
import org.qortal.api.ApiExceptionFactory;
|
||||
import org.qortal.api.Security;
|
||||
import org.qortal.api.model.crosschain.RavencoinSendRequest;
|
||||
import org.qortal.crosschain.Ravencoin;
|
||||
import org.qortal.api.model.crosschain.DigibyteSendRequest;
|
||||
import org.qortal.crosschain.Digibyte;
|
||||
import org.qortal.crosschain.ForeignBlockchainException;
|
||||
import org.qortal.crosschain.SimpleTransaction;
|
||||
|
||||
@Path("/crosschain/rvn")
|
||||
@Tag(name = "Cross-Chain (Ravencoin)")
|
||||
public class CrossChainRavencoinResource {
|
||||
@Path("/crosschain/dgb")
|
||||
@Tag(name = "Cross-Chain (Digibyte)")
|
||||
public class CrossChainDigibyteResource {
|
||||
|
||||
@Context
|
||||
HttpServletRequest request;
|
||||
@@ -38,7 +38,7 @@ public class CrossChainRavencoinResource {
|
||||
@POST
|
||||
@Path("/walletbalance")
|
||||
@Operation(
|
||||
summary = "Returns RVN balance for hierarchical, deterministic BIP32 wallet",
|
||||
summary = "Returns DGB balance for hierarchical, deterministic BIP32 wallet",
|
||||
description = "Supply BIP32 'm' private/public key in base58, starting with 'xprv'/'xpub' for mainnet, 'tprv'/'tpub' for testnet",
|
||||
requestBody = @RequestBody(
|
||||
required = true,
|
||||
@@ -59,16 +59,16 @@ public class CrossChainRavencoinResource {
|
||||
)
|
||||
@ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE})
|
||||
@SecurityRequirement(name = "apiKey")
|
||||
public String getRavencoinWalletBalance(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String key58) {
|
||||
public String getDigibyteWalletBalance(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String key58) {
|
||||
Security.checkApiCallAllowed(request);
|
||||
|
||||
Ravencoin ravencoin = Ravencoin.getInstance();
|
||||
Digibyte digibyte = Digibyte.getInstance();
|
||||
|
||||
if (!ravencoin.isValidDeterministicKey(key58))
|
||||
if (!digibyte.isValidDeterministicKey(key58))
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY);
|
||||
|
||||
try {
|
||||
Long balance = ravencoin.getWalletBalanceFromTransactions(key58);
|
||||
Long balance = digibyte.getWalletBalanceFromTransactions(key58);
|
||||
if (balance == null)
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE);
|
||||
|
||||
@@ -103,16 +103,16 @@ public class CrossChainRavencoinResource {
|
||||
)
|
||||
@ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE})
|
||||
@SecurityRequirement(name = "apiKey")
|
||||
public List<SimpleTransaction> getRavencoinWalletTransactions(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String key58) {
|
||||
public List<SimpleTransaction> getDigibyteWalletTransactions(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String key58) {
|
||||
Security.checkApiCallAllowed(request);
|
||||
|
||||
Ravencoin ravencoin = Ravencoin.getInstance();
|
||||
Digibyte digibyte = Digibyte.getInstance();
|
||||
|
||||
if (!ravencoin.isValidDeterministicKey(key58))
|
||||
if (!digibyte.isValidDeterministicKey(key58))
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY);
|
||||
|
||||
try {
|
||||
return ravencoin.getWalletTransactions(key58);
|
||||
return digibyte.getWalletTransactions(key58);
|
||||
} catch (ForeignBlockchainException e) {
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE);
|
||||
}
|
||||
@@ -121,14 +121,14 @@ public class CrossChainRavencoinResource {
|
||||
@POST
|
||||
@Path("/send")
|
||||
@Operation(
|
||||
summary = "Sends RVN from hierarchical, deterministic BIP32 wallet to specific address",
|
||||
description = "Currently only supports 'legacy' P2PKH Ravencoin addresses. Supply BIP32 'm' private key in base58, starting with 'xprv' for mainnet, 'tprv' for testnet",
|
||||
summary = "Sends DGB from hierarchical, deterministic BIP32 wallet to specific address",
|
||||
description = "Currently supports 'legacy' P2PKH Digibyte addresses and Native SegWit (P2WPKH) addresses. Supply BIP32 'm' private key in base58, starting with 'xprv' for mainnet, 'tprv' for testnet",
|
||||
requestBody = @RequestBody(
|
||||
required = true,
|
||||
content = @Content(
|
||||
mediaType = MediaType.APPLICATION_JSON,
|
||||
schema = @Schema(
|
||||
implementation = RavencoinSendRequest.class
|
||||
implementation = DigibyteSendRequest.class
|
||||
)
|
||||
)
|
||||
),
|
||||
@@ -140,33 +140,33 @@ public class CrossChainRavencoinResource {
|
||||
)
|
||||
@ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA, ApiError.INVALID_ADDRESS, ApiError.FOREIGN_BLOCKCHAIN_BALANCE_ISSUE, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE})
|
||||
@SecurityRequirement(name = "apiKey")
|
||||
public String sendBitcoin(@HeaderParam(Security.API_KEY_HEADER) String apiKey, RavencoinSendRequest ravencoinSendRequest) {
|
||||
public String sendBitcoin(@HeaderParam(Security.API_KEY_HEADER) String apiKey, DigibyteSendRequest digibyteSendRequest) {
|
||||
Security.checkApiCallAllowed(request);
|
||||
|
||||
if (ravencoinSendRequest.ravencoinAmount <= 0)
|
||||
if (digibyteSendRequest.digibyteAmount <= 0)
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA);
|
||||
|
||||
if (ravencoinSendRequest.feePerByte != null && ravencoinSendRequest.feePerByte <= 0)
|
||||
if (digibyteSendRequest.feePerByte != null && digibyteSendRequest.feePerByte <= 0)
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA);
|
||||
|
||||
Ravencoin ravencoin = Ravencoin.getInstance();
|
||||
Digibyte digibyte = Digibyte.getInstance();
|
||||
|
||||
if (!ravencoin.isValidAddress(ravencoinSendRequest.receivingAddress))
|
||||
if (!digibyte.isValidAddress(digibyteSendRequest.receivingAddress))
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
|
||||
|
||||
if (!ravencoin.isValidDeterministicKey(ravencoinSendRequest.xprv58))
|
||||
if (!digibyte.isValidDeterministicKey(digibyteSendRequest.xprv58))
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY);
|
||||
|
||||
Transaction spendTransaction = ravencoin.buildSpend(ravencoinSendRequest.xprv58,
|
||||
ravencoinSendRequest.receivingAddress,
|
||||
ravencoinSendRequest.ravencoinAmount,
|
||||
ravencoinSendRequest.feePerByte);
|
||||
Transaction spendTransaction = digibyte.buildSpend(digibyteSendRequest.xprv58,
|
||||
digibyteSendRequest.receivingAddress,
|
||||
digibyteSendRequest.digibyteAmount,
|
||||
digibyteSendRequest.feePerByte);
|
||||
|
||||
if (spendTransaction == null)
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.FOREIGN_BLOCKCHAIN_BALANCE_ISSUE);
|
||||
|
||||
try {
|
||||
ravencoin.broadcastTransaction(spendTransaction);
|
||||
digibyte.broadcastTransaction(spendTransaction);
|
||||
} catch (ForeignBlockchainException e) {
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE);
|
||||
}
|
@@ -45,9 +45,9 @@ import static java.util.stream.Collectors.toMap;
|
||||
* <li>Trade-bot entries</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
public class DigibyteACCTv3TradeBot implements AcctTradeBot {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(RavencoinACCTv3TradeBot.class);
|
||||
private static final Logger LOGGER = LogManager.getLogger(DigibyteACCTv3TradeBot.class);
|
||||
|
||||
public enum State implements TradeBot.StateNameAndValueSupplier {
|
||||
BOB_WAITING_FOR_AT_CONFIRM(10, false, false),
|
||||
@@ -91,18 +91,18 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
/** Maximum time Bob waits for his AT creation transaction to be confirmed into a block. (milliseconds) */
|
||||
private static final long MAX_AT_CONFIRMATION_PERIOD = 24 * 60 * 60 * 1000L; // ms
|
||||
|
||||
private static RavencoinACCTv3TradeBot instance;
|
||||
private static DigibyteACCTv3TradeBot instance;
|
||||
|
||||
private final List<String> endStates = Arrays.asList(State.BOB_DONE, State.BOB_REFUNDED, State.ALICE_DONE, State.ALICE_REFUNDING_A, State.ALICE_REFUNDED).stream()
|
||||
.map(State::name)
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
|
||||
private RavencoinACCTv3TradeBot() {
|
||||
private DigibyteACCTv3TradeBot() {
|
||||
}
|
||||
|
||||
public static synchronized RavencoinACCTv3TradeBot getInstance() {
|
||||
public static synchronized DigibyteACCTv3TradeBot getInstance() {
|
||||
if (instance == null)
|
||||
instance = new RavencoinACCTv3TradeBot();
|
||||
instance = new DigibyteACCTv3TradeBot();
|
||||
|
||||
return instance;
|
||||
}
|
||||
@@ -113,7 +113,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new trade-bot entry from the "Bob" viewpoint, i.e. OFFERing QORT in exchange for RVN.
|
||||
* Creates a new trade-bot entry from the "Bob" viewpoint, i.e. OFFERing QORT in exchange for DGB.
|
||||
* <p>
|
||||
* Generates:
|
||||
* <ul>
|
||||
@@ -122,14 +122,14 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
* Derives:
|
||||
* <ul>
|
||||
* <li>'native' (as in Qortal) public key, public key hash, address (starting with Q)</li>
|
||||
* <li>'foreign' (as in Ravencoin) public key, public key hash</li>
|
||||
* <li>'foreign' (as in Digibyte) public key, public key hash</li>
|
||||
* </ul>
|
||||
* A Qortal AT is then constructed including the following as constants in the 'data segment':
|
||||
* <ul>
|
||||
* <li>'native'/Qortal 'trade' address - used as a MESSAGE contact</li>
|
||||
* <li>'foreign'/Ravencoin public key hash - used by Alice's P2SH scripts to allow redeem</li>
|
||||
* <li>'foreign'/Digibyte public key hash - used by Alice's P2SH scripts to allow redeem</li>
|
||||
* <li>QORT amount on offer by Bob</li>
|
||||
* <li>RVN amount expected in return by Bob (from Alice)</li>
|
||||
* <li>DGB amount expected in return by Bob (from Alice)</li>
|
||||
* <li>trading timeout, in case things go wrong and everyone needs to refund</li>
|
||||
* </ul>
|
||||
* Returns a DEPLOY_AT transaction that needs to be signed and broadcast to the Qortal network.
|
||||
@@ -151,17 +151,17 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
byte[] tradeForeignPublicKey = TradeBot.deriveTradeForeignPublicKey(tradePrivateKey);
|
||||
byte[] tradeForeignPublicKeyHash = Crypto.hash160(tradeForeignPublicKey);
|
||||
|
||||
// Convert Ravencoin receiving address into public key hash (we only support P2PKH at this time)
|
||||
Address ravencoinReceivingAddress;
|
||||
// Convert Digibyte receiving address into public key hash (we only support P2PKH at this time)
|
||||
Address digibyteReceivingAddress;
|
||||
try {
|
||||
ravencoinReceivingAddress = Address.fromString(Ravencoin.getInstance().getNetworkParameters(), tradeBotCreateRequest.receivingAddress);
|
||||
digibyteReceivingAddress = Address.fromString(Digibyte.getInstance().getNetworkParameters(), tradeBotCreateRequest.receivingAddress);
|
||||
} catch (AddressFormatException e) {
|
||||
throw new DataException("Unsupported Ravencoin receiving address: " + tradeBotCreateRequest.receivingAddress);
|
||||
throw new DataException("Unsupported Digibyte receiving address: " + tradeBotCreateRequest.receivingAddress);
|
||||
}
|
||||
if (ravencoinReceivingAddress.getOutputScriptType() != ScriptType.P2PKH)
|
||||
throw new DataException("Unsupported Ravencoin receiving address: " + tradeBotCreateRequest.receivingAddress);
|
||||
if (digibyteReceivingAddress.getOutputScriptType() != ScriptType.P2PKH)
|
||||
throw new DataException("Unsupported Digibyte receiving address: " + tradeBotCreateRequest.receivingAddress);
|
||||
|
||||
byte[] ravencoinReceivingAccountInfo = ravencoinReceivingAddress.getHash();
|
||||
byte[] digibyteReceivingAccountInfo = digibyteReceivingAddress.getHash();
|
||||
|
||||
PublicKeyAccount creator = new PublicKeyAccount(repository, tradeBotCreateRequest.creatorPublicKey);
|
||||
|
||||
@@ -172,11 +172,11 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
byte[] signature = null;
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, creator.getPublicKey(), fee, signature);
|
||||
|
||||
String name = "QORT/RVN ACCT";
|
||||
String description = "QORT/RVN cross-chain trade";
|
||||
String name = "QORT/DGB ACCT";
|
||||
String description = "QORT/DGB cross-chain trade";
|
||||
String aTType = "ACCT";
|
||||
String tags = "ACCT QORT RVN";
|
||||
byte[] creationBytes = RavencoinACCTv3.buildQortalAT(tradeNativeAddress, tradeForeignPublicKeyHash, tradeBotCreateRequest.qortAmount,
|
||||
String tags = "ACCT QORT DGB";
|
||||
byte[] creationBytes = DigibyteACCTv3.buildQortalAT(tradeNativeAddress, tradeForeignPublicKeyHash, tradeBotCreateRequest.qortAmount,
|
||||
tradeBotCreateRequest.foreignAmount, tradeBotCreateRequest.tradeTimeout);
|
||||
long amount = tradeBotCreateRequest.fundingQortAmount;
|
||||
|
||||
@@ -189,14 +189,14 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
DeployAtTransaction.ensureATAddress(deployAtTransactionData);
|
||||
String atAddress = deployAtTransactionData.getAtAddress();
|
||||
|
||||
TradeBotData tradeBotData = new TradeBotData(tradePrivateKey, RavencoinACCTv3.NAME,
|
||||
TradeBotData tradeBotData = new TradeBotData(tradePrivateKey, DigibyteACCTv3.NAME,
|
||||
State.BOB_WAITING_FOR_AT_CONFIRM.name(), State.BOB_WAITING_FOR_AT_CONFIRM.value,
|
||||
creator.getAddress(), atAddress, timestamp, tradeBotCreateRequest.qortAmount,
|
||||
tradeNativePublicKey, tradeNativePublicKeyHash, tradeNativeAddress,
|
||||
null, null,
|
||||
SupportedBlockchain.RAVENCOIN.name(),
|
||||
SupportedBlockchain.DIGIBYTE.name(),
|
||||
tradeForeignPublicKey, tradeForeignPublicKeyHash,
|
||||
tradeBotCreateRequest.foreignAmount, null, null, null, ravencoinReceivingAccountInfo);
|
||||
tradeBotCreateRequest.foreignAmount, null, null, null, digibyteReceivingAccountInfo);
|
||||
|
||||
TradeBot.updateTradeBotState(repository, tradeBotData, () -> String.format("Built AT %s. Waiting for deployment", atAddress));
|
||||
|
||||
@@ -212,15 +212,15 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a trade-bot entry from the 'Alice' viewpoint, i.e. matching RVN to an existing offer.
|
||||
* Creates a trade-bot entry from the 'Alice' viewpoint, i.e. matching DGB to an existing offer.
|
||||
* <p>
|
||||
* Requires a chosen trade offer from Bob, passed by <tt>crossChainTradeData</tt>
|
||||
* and access to a Ravencoin wallet via <tt>xprv58</tt>.
|
||||
* and access to a Digibyte wallet via <tt>xprv58</tt>.
|
||||
* <p>
|
||||
* The <tt>crossChainTradeData</tt> contains the current trade offer state
|
||||
* as extracted from the AT's data segment.
|
||||
* <p>
|
||||
* Access to a funded wallet is via a Ravencoin BIP32 hierarchical deterministic key,
|
||||
* Access to a funded wallet is via a Digibyte BIP32 hierarchical deterministic key,
|
||||
* passed via <tt>xprv58</tt>.
|
||||
* <b>This key will be stored in your node's database</b>
|
||||
* to allow trade-bot to create/fund the necessary P2SH transactions!
|
||||
@@ -230,15 +230,15 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
* As an example, the xprv58 can be extract from a <i>legacy, password-less</i>
|
||||
* Electrum wallet by going to the console tab and entering:<br>
|
||||
* <tt>wallet.keystore.xprv</tt><br>
|
||||
* which should result in a base58 string starting with either 'xprv' (for Ravencoin main-net)
|
||||
* or 'tprv' for (Ravencoin test-net).
|
||||
* which should result in a base58 string starting with either 'xprv' (for Digibyte main-net)
|
||||
* or 'tprv' for (Digibyte test-net).
|
||||
* <p>
|
||||
* It is envisaged that the value in <tt>xprv58</tt> will actually come from a Qortal-UI-managed wallet.
|
||||
* <p>
|
||||
* If sufficient funds are available, <b>this method will actually fund the P2SH-A</b>
|
||||
* with the Ravencoin amount expected by 'Bob'.
|
||||
* with the Digibyte amount expected by 'Bob'.
|
||||
* <p>
|
||||
* If the Ravencoin transaction is successfully broadcast to the network then
|
||||
* If the Digibyte transaction is successfully broadcast to the network then
|
||||
* we also send a MESSAGE to Bob's trade-bot to let them know.
|
||||
* <p>
|
||||
* The trade-bot entry is saved to the repository and the cross-chain trading process commences.
|
||||
@@ -246,7 +246,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
* @param repository
|
||||
* @param crossChainTradeData chosen trade OFFER that Alice wants to match
|
||||
* @param xprv58 funded wallet xprv in base58
|
||||
* @return true if P2SH-A funding transaction successfully broadcast to Ravencoin network, false otherwise
|
||||
* @return true if P2SH-A funding transaction successfully broadcast to Digibyte network, false otherwise
|
||||
* @throws DataException
|
||||
*/
|
||||
public ResponseResult startResponse(Repository repository, ATData atData, ACCT acct, CrossChainTradeData crossChainTradeData, String xprv58, String receivingAddress) throws DataException {
|
||||
@@ -266,12 +266,12 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
long now = NTP.getTime();
|
||||
int lockTimeA = crossChainTradeData.tradeTimeout * 60 + (int) (now / 1000L);
|
||||
|
||||
TradeBotData tradeBotData = new TradeBotData(tradePrivateKey, RavencoinACCTv3.NAME,
|
||||
TradeBotData tradeBotData = new TradeBotData(tradePrivateKey, DigibyteACCTv3.NAME,
|
||||
State.ALICE_WAITING_FOR_AT_LOCK.name(), State.ALICE_WAITING_FOR_AT_LOCK.value,
|
||||
receivingAddress, crossChainTradeData.qortalAtAddress, now, crossChainTradeData.qortAmount,
|
||||
tradeNativePublicKey, tradeNativePublicKeyHash, tradeNativeAddress,
|
||||
secretA, hashOfSecretA,
|
||||
SupportedBlockchain.RAVENCOIN.name(),
|
||||
SupportedBlockchain.DIGIBYTE.name(),
|
||||
tradeForeignPublicKey, tradeForeignPublicKeyHash,
|
||||
crossChainTradeData.expectedForeignAmount, xprv58, null, lockTimeA, receivingPublicKeyHash);
|
||||
|
||||
@@ -282,9 +282,9 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
// Check we have enough funds via xprv58 to fund P2SH to cover expectedForeignAmount
|
||||
long p2shFee;
|
||||
try {
|
||||
p2shFee = Ravencoin.getInstance().getP2shFee(now);
|
||||
p2shFee = Digibyte.getInstance().getP2shFee(now);
|
||||
} catch (ForeignBlockchainException e) {
|
||||
LOGGER.debug("Couldn't estimate Ravencoin fees?");
|
||||
LOGGER.debug("Couldn't estimate Digibyte fees?");
|
||||
return ResponseResult.NETWORK_ISSUE;
|
||||
}
|
||||
|
||||
@@ -294,17 +294,17 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
|
||||
// P2SH-A to be funded
|
||||
byte[] redeemScriptBytes = BitcoinyHTLC.buildScript(tradeForeignPublicKeyHash, lockTimeA, crossChainTradeData.creatorForeignPKH, hashOfSecretA);
|
||||
String p2shAddress = Ravencoin.getInstance().deriveP2shAddress(redeemScriptBytes);
|
||||
String p2shAddress = Digibyte.getInstance().deriveP2shAddress(redeemScriptBytes);
|
||||
|
||||
// Build transaction for funding P2SH-A
|
||||
Transaction p2shFundingTransaction = Ravencoin.getInstance().buildSpend(tradeBotData.getForeignKey(), p2shAddress, amountA);
|
||||
Transaction p2shFundingTransaction = Digibyte.getInstance().buildSpend(tradeBotData.getForeignKey(), p2shAddress, amountA);
|
||||
if (p2shFundingTransaction == null) {
|
||||
LOGGER.debug("Unable to build P2SH-A funding transaction - lack of funds?");
|
||||
return ResponseResult.BALANCE_ISSUE;
|
||||
}
|
||||
|
||||
try {
|
||||
Ravencoin.getInstance().broadcastTransaction(p2shFundingTransaction);
|
||||
Digibyte.getInstance().broadcastTransaction(p2shFundingTransaction);
|
||||
} catch (ForeignBlockchainException e) {
|
||||
// We couldn't fund P2SH-A at this time
|
||||
LOGGER.debug("Couldn't broadcast P2SH-A funding transaction?");
|
||||
@@ -312,7 +312,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
}
|
||||
|
||||
// Attempt to send MESSAGE to Bob's Qortal trade address
|
||||
byte[] messageData = RavencoinACCTv3.buildOfferMessage(tradeBotData.getTradeForeignPublicKeyHash(), tradeBotData.getHashOfSecret(), tradeBotData.getLockTimeA());
|
||||
byte[] messageData = DigibyteACCTv3.buildOfferMessage(tradeBotData.getTradeForeignPublicKeyHash(), tradeBotData.getHashOfSecret(), tradeBotData.getLockTimeA());
|
||||
String messageRecipient = crossChainTradeData.qortalCreatorTradeAddress;
|
||||
|
||||
boolean isMessageAlreadySent = repository.getMessageRepository().exists(tradeBotData.getTradeNativePublicKey(), messageRecipient, messageData);
|
||||
@@ -382,7 +382,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
}
|
||||
|
||||
if (tradeBotState.requiresTradeData) {
|
||||
tradeData = RavencoinACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
tradeData = DigibyteACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
if (tradeData == null) {
|
||||
LOGGER.warn(() -> String.format("Unable to fetch ACCT trade data for AT %s from repository", tradeBotData.getAtAddress()));
|
||||
return;
|
||||
@@ -463,7 +463,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
* <p>
|
||||
* Details from Alice are used to derive P2SH-A address and this is checked for funding balance.
|
||||
* <p>
|
||||
* Assuming P2SH-A has at least expected Ravencoin balance,
|
||||
* Assuming P2SH-A has at least expected Digibyte balance,
|
||||
* Bob's trade-bot constructs a zero-fee, PoW MESSAGE to send to Bob's AT with more trade details.
|
||||
* <p>
|
||||
* On processing this MESSAGE, Bob's AT should switch into 'TRADE' mode and only trade with Alice.
|
||||
@@ -481,7 +481,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
return;
|
||||
}
|
||||
|
||||
Ravencoin ravencoin = Ravencoin.getInstance();
|
||||
Digibyte digibyte = Digibyte.getInstance();
|
||||
|
||||
String address = tradeBotData.getTradeNativeAddress();
|
||||
List<MessageTransactionData> messageTransactionsData = repository.getMessageRepository().getMessagesByParticipants(null, address, null, null, null);
|
||||
@@ -490,27 +490,27 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
if (messageTransactionData.isText())
|
||||
continue;
|
||||
|
||||
// We're expecting: HASH160(secret-A), Alice's Ravencoin pubkeyhash and lockTime-A
|
||||
// We're expecting: HASH160(secret-A), Alice's Digibyte pubkeyhash and lockTime-A
|
||||
byte[] messageData = messageTransactionData.getData();
|
||||
RavencoinACCTv3.OfferMessageData offerMessageData = RavencoinACCTv3.extractOfferMessageData(messageData);
|
||||
DigibyteACCTv3.OfferMessageData offerMessageData = DigibyteACCTv3.extractOfferMessageData(messageData);
|
||||
if (offerMessageData == null)
|
||||
continue;
|
||||
|
||||
byte[] aliceForeignPublicKeyHash = offerMessageData.partnerRavencoinPKH;
|
||||
byte[] aliceForeignPublicKeyHash = offerMessageData.partnerDigibytePKH;
|
||||
byte[] hashOfSecretA = offerMessageData.hashOfSecretA;
|
||||
int lockTimeA = (int) offerMessageData.lockTimeA;
|
||||
long messageTimestamp = messageTransactionData.getTimestamp();
|
||||
int refundTimeout = RavencoinACCTv3.calcRefundTimeout(messageTimestamp, lockTimeA);
|
||||
int refundTimeout = DigibyteACCTv3.calcRefundTimeout(messageTimestamp, lockTimeA);
|
||||
|
||||
// Determine P2SH-A address and confirm funded
|
||||
byte[] redeemScriptA = BitcoinyHTLC.buildScript(aliceForeignPublicKeyHash, lockTimeA, tradeBotData.getTradeForeignPublicKeyHash(), hashOfSecretA);
|
||||
String p2shAddressA = ravencoin.deriveP2shAddress(redeemScriptA);
|
||||
String p2shAddressA = digibyte.deriveP2shAddress(redeemScriptA);
|
||||
|
||||
long feeTimestamp = calcFeeTimestamp(lockTimeA, crossChainTradeData.tradeTimeout);
|
||||
long p2shFee = Ravencoin.getInstance().getP2shFee(feeTimestamp);
|
||||
long p2shFee = Digibyte.getInstance().getP2shFee(feeTimestamp);
|
||||
final long minimumAmountA = tradeBotData.getForeignAmount() + p2shFee;
|
||||
|
||||
BitcoinyHTLC.Status htlcStatusA = BitcoinyHTLC.determineHtlcStatus(ravencoin.getBlockchainProvider(), p2shAddressA, minimumAmountA);
|
||||
BitcoinyHTLC.Status htlcStatusA = BitcoinyHTLC.determineHtlcStatus(digibyte.getBlockchainProvider(), p2shAddressA, minimumAmountA);
|
||||
|
||||
switch (htlcStatusA) {
|
||||
case UNFUNDED:
|
||||
@@ -540,7 +540,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
String aliceNativeAddress = Crypto.toAddress(messageTransactionData.getCreatorPublicKey());
|
||||
|
||||
// Build outgoing message, padding each part to 32 bytes to make it easier for AT to consume
|
||||
byte[] outgoingMessageData = RavencoinACCTv3.buildTradeMessage(aliceNativeAddress, aliceForeignPublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
byte[] outgoingMessageData = DigibyteACCTv3.buildTradeMessage(aliceNativeAddress, aliceForeignPublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
String messageRecipient = tradeBotData.getAtAddress();
|
||||
|
||||
boolean isMessageAlreadySent = repository.getMessageRepository().exists(tradeBotData.getTradeNativePublicKey(), messageRecipient, outgoingMessageData);
|
||||
@@ -579,7 +579,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
* <p>
|
||||
* If all is well, trade-bot then redeems AT using Alice's secret-A, releasing Bob's QORT to Alice.
|
||||
* <p>
|
||||
* In revealing a valid secret-A, Bob can then redeem the RVN funds from P2SH-A.
|
||||
* In revealing a valid secret-A, Bob can then redeem the DGB funds from P2SH-A.
|
||||
* <p>
|
||||
* @throws ForeignBlockchainException
|
||||
*/
|
||||
@@ -588,19 +588,19 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
if (aliceUnexpectedState(repository, tradeBotData, atData, crossChainTradeData))
|
||||
return;
|
||||
|
||||
Ravencoin ravencoin = Ravencoin.getInstance();
|
||||
Digibyte digibyte = Digibyte.getInstance();
|
||||
int lockTimeA = tradeBotData.getLockTimeA();
|
||||
|
||||
// Refund P2SH-A if we've passed lockTime-A
|
||||
if (NTP.getTime() >= lockTimeA * 1000L) {
|
||||
byte[] redeemScriptA = BitcoinyHTLC.buildScript(tradeBotData.getTradeForeignPublicKeyHash(), lockTimeA, crossChainTradeData.creatorForeignPKH, tradeBotData.getHashOfSecret());
|
||||
String p2shAddressA = ravencoin.deriveP2shAddress(redeemScriptA);
|
||||
String p2shAddressA = digibyte.deriveP2shAddress(redeemScriptA);
|
||||
|
||||
long feeTimestamp = calcFeeTimestamp(lockTimeA, crossChainTradeData.tradeTimeout);
|
||||
long p2shFee = Ravencoin.getInstance().getP2shFee(feeTimestamp);
|
||||
long p2shFee = Digibyte.getInstance().getP2shFee(feeTimestamp);
|
||||
long minimumAmountA = crossChainTradeData.expectedForeignAmount + p2shFee;
|
||||
|
||||
BitcoinyHTLC.Status htlcStatusA = BitcoinyHTLC.determineHtlcStatus(ravencoin.getBlockchainProvider(), p2shAddressA, minimumAmountA);
|
||||
BitcoinyHTLC.Status htlcStatusA = BitcoinyHTLC.determineHtlcStatus(digibyte.getBlockchainProvider(), p2shAddressA, minimumAmountA);
|
||||
|
||||
switch (htlcStatusA) {
|
||||
case UNFUNDED:
|
||||
@@ -646,7 +646,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
}
|
||||
|
||||
long recipientMessageTimestamp = messageTransactionsData.get(0).getTimestamp();
|
||||
int refundTimeout = RavencoinACCTv3.calcRefundTimeout(recipientMessageTimestamp, lockTimeA);
|
||||
int refundTimeout = DigibyteACCTv3.calcRefundTimeout(recipientMessageTimestamp, lockTimeA);
|
||||
|
||||
// Our calculated refundTimeout should match AT's refundTimeout
|
||||
if (refundTimeout != crossChainTradeData.refundTimeout) {
|
||||
@@ -660,7 +660,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
// Send 'redeem' MESSAGE to AT using both secret
|
||||
byte[] secretA = tradeBotData.getSecret();
|
||||
String qortalReceivingAddress = Base58.encode(tradeBotData.getReceivingAccountInfo()); // Actually contains whole address, not just PKH
|
||||
byte[] messageData = RavencoinACCTv3.buildRedeemMessage(secretA, qortalReceivingAddress);
|
||||
byte[] messageData = DigibyteACCTv3.buildRedeemMessage(secretA, qortalReceivingAddress);
|
||||
String messageRecipient = tradeBotData.getAtAddress();
|
||||
|
||||
boolean isMessageAlreadySent = repository.getMessageRepository().exists(tradeBotData.getTradeNativePublicKey(), messageRecipient, messageData);
|
||||
@@ -687,15 +687,15 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
}
|
||||
|
||||
/**
|
||||
* Trade-bot is waiting for Alice to redeem Bob's AT, thus revealing secret-A which is required to spend the RVN funds from P2SH-A.
|
||||
* Trade-bot is waiting for Alice to redeem Bob's AT, thus revealing secret-A which is required to spend the DGB funds from P2SH-A.
|
||||
* <p>
|
||||
* It's possible that Bob's AT has reached its trading timeout and automatically refunded QORT back to Bob. In which case,
|
||||
* trade-bot is done with this specific trade and finalizes in refunded state.
|
||||
* <p>
|
||||
* Assuming trade-bot can extract a valid secret-A from Alice's MESSAGE then trade-bot uses that to redeem the RVN funds from P2SH-A
|
||||
* to Bob's 'foreign'/Ravencoin trade legacy-format address, as derived from trade private key.
|
||||
* Assuming trade-bot can extract a valid secret-A from Alice's MESSAGE then trade-bot uses that to redeem the DGB funds from P2SH-A
|
||||
* to Bob's 'foreign'/Digibyte trade legacy-format address, as derived from trade private key.
|
||||
* <p>
|
||||
* (This could potentially be 'improved' to send RVN to any address of Bob's choosing by changing the transaction output).
|
||||
* (This could potentially be 'improved' to send DGB to any address of Bob's choosing by changing the transaction output).
|
||||
* <p>
|
||||
* If trade-bot successfully broadcasts the transaction, then this specific trade is done.
|
||||
* @throws ForeignBlockchainException
|
||||
@@ -709,14 +709,14 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
|
||||
// If AT is REFUNDED or CANCELLED then something has gone wrong
|
||||
if (crossChainTradeData.mode == AcctMode.REFUNDED || crossChainTradeData.mode == AcctMode.CANCELLED) {
|
||||
// Alice hasn't redeemed the QORT, so there is no point in trying to redeem the RVN
|
||||
// Alice hasn't redeemed the QORT, so there is no point in trying to redeem the DGB
|
||||
TradeBot.updateTradeBotState(repository, tradeBotData, State.BOB_REFUNDED,
|
||||
() -> String.format("AT %s has auto-refunded - trade aborted", tradeBotData.getAtAddress()));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] secretA = RavencoinACCTv3.getInstance().findSecretA(repository, crossChainTradeData);
|
||||
byte[] secretA = DigibyteACCTv3.getInstance().findSecretA(repository, crossChainTradeData);
|
||||
if (secretA == null) {
|
||||
LOGGER.debug(() -> String.format("Unable to find secret-A from redeem message to AT %s?", tradeBotData.getAtAddress()));
|
||||
return;
|
||||
@@ -724,18 +724,18 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
|
||||
// Use secret-A to redeem P2SH-A
|
||||
|
||||
Ravencoin ravencoin = Ravencoin.getInstance();
|
||||
Digibyte digibyte = Digibyte.getInstance();
|
||||
|
||||
byte[] receivingAccountInfo = tradeBotData.getReceivingAccountInfo();
|
||||
int lockTimeA = crossChainTradeData.lockTimeA;
|
||||
byte[] redeemScriptA = BitcoinyHTLC.buildScript(crossChainTradeData.partnerForeignPKH, lockTimeA, crossChainTradeData.creatorForeignPKH, crossChainTradeData.hashOfSecretA);
|
||||
String p2shAddressA = ravencoin.deriveP2shAddress(redeemScriptA);
|
||||
String p2shAddressA = digibyte.deriveP2shAddress(redeemScriptA);
|
||||
|
||||
// Fee for redeem/refund is subtracted from P2SH-A balance.
|
||||
long feeTimestamp = calcFeeTimestamp(lockTimeA, crossChainTradeData.tradeTimeout);
|
||||
long p2shFee = Ravencoin.getInstance().getP2shFee(feeTimestamp);
|
||||
long p2shFee = Digibyte.getInstance().getP2shFee(feeTimestamp);
|
||||
long minimumAmountA = crossChainTradeData.expectedForeignAmount + p2shFee;
|
||||
BitcoinyHTLC.Status htlcStatusA = BitcoinyHTLC.determineHtlcStatus(ravencoin.getBlockchainProvider(), p2shAddressA, minimumAmountA);
|
||||
BitcoinyHTLC.Status htlcStatusA = BitcoinyHTLC.determineHtlcStatus(digibyte.getBlockchainProvider(), p2shAddressA, minimumAmountA);
|
||||
|
||||
switch (htlcStatusA) {
|
||||
case UNFUNDED:
|
||||
@@ -756,17 +756,17 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
case FUNDED: {
|
||||
Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
|
||||
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
|
||||
List<TransactionOutput> fundingOutputs = ravencoin.getUnspentOutputs(p2shAddressA);
|
||||
List<TransactionOutput> fundingOutputs = digibyte.getUnspentOutputs(p2shAddressA);
|
||||
|
||||
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(ravencoin.getNetworkParameters(), redeemAmount, redeemKey,
|
||||
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(digibyte.getNetworkParameters(), redeemAmount, redeemKey,
|
||||
fundingOutputs, redeemScriptA, secretA, receivingAccountInfo);
|
||||
|
||||
ravencoin.broadcastTransaction(p2shRedeemTransaction);
|
||||
digibyte.broadcastTransaction(p2shRedeemTransaction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String receivingAddress = ravencoin.pkhToAddress(receivingAccountInfo);
|
||||
String receivingAddress = digibyte.pkhToAddress(receivingAccountInfo);
|
||||
|
||||
TradeBot.updateTradeBotState(repository, tradeBotData, State.BOB_DONE,
|
||||
() -> String.format("P2SH-A %s redeemed. Funds should arrive at %s", tradeBotData.getAtAddress(), receivingAddress));
|
||||
@@ -784,21 +784,21 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
if (NTP.getTime() <= lockTimeA * 1000L)
|
||||
return;
|
||||
|
||||
Ravencoin ravencoin = Ravencoin.getInstance();
|
||||
Digibyte digibyte = Digibyte.getInstance();
|
||||
|
||||
// We can't refund P2SH-A until median block time has passed lockTime-A (see BIP113)
|
||||
int medianBlockTime = ravencoin.getMedianBlockTime();
|
||||
int medianBlockTime = digibyte.getMedianBlockTime();
|
||||
if (medianBlockTime <= lockTimeA)
|
||||
return;
|
||||
|
||||
byte[] redeemScriptA = BitcoinyHTLC.buildScript(tradeBotData.getTradeForeignPublicKeyHash(), lockTimeA, crossChainTradeData.creatorForeignPKH, tradeBotData.getHashOfSecret());
|
||||
String p2shAddressA = ravencoin.deriveP2shAddress(redeemScriptA);
|
||||
String p2shAddressA = digibyte.deriveP2shAddress(redeemScriptA);
|
||||
|
||||
// Fee for redeem/refund is subtracted from P2SH-A balance.
|
||||
long feeTimestamp = calcFeeTimestamp(lockTimeA, crossChainTradeData.tradeTimeout);
|
||||
long p2shFee = Ravencoin.getInstance().getP2shFee(feeTimestamp);
|
||||
long p2shFee = Digibyte.getInstance().getP2shFee(feeTimestamp);
|
||||
long minimumAmountA = crossChainTradeData.expectedForeignAmount + p2shFee;
|
||||
BitcoinyHTLC.Status htlcStatusA = BitcoinyHTLC.determineHtlcStatus(ravencoin.getBlockchainProvider(), p2shAddressA, minimumAmountA);
|
||||
BitcoinyHTLC.Status htlcStatusA = BitcoinyHTLC.determineHtlcStatus(digibyte.getBlockchainProvider(), p2shAddressA, minimumAmountA);
|
||||
|
||||
switch (htlcStatusA) {
|
||||
case UNFUNDED:
|
||||
@@ -820,16 +820,16 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
|
||||
case FUNDED:{
|
||||
Coin refundAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
|
||||
ECKey refundKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
|
||||
List<TransactionOutput> fundingOutputs = ravencoin.getUnspentOutputs(p2shAddressA);
|
||||
List<TransactionOutput> fundingOutputs = digibyte.getUnspentOutputs(p2shAddressA);
|
||||
|
||||
// Determine receive address for refund
|
||||
String receiveAddress = ravencoin.getUnusedReceiveAddress(tradeBotData.getForeignKey());
|
||||
Address receiving = Address.fromString(ravencoin.getNetworkParameters(), receiveAddress);
|
||||
String receiveAddress = digibyte.getUnusedReceiveAddress(tradeBotData.getForeignKey());
|
||||
Address receiving = Address.fromString(digibyte.getNetworkParameters(), receiveAddress);
|
||||
|
||||
Transaction p2shRefundTransaction = BitcoinyHTLC.buildRefundTransaction(ravencoin.getNetworkParameters(), refundAmount, refundKey,
|
||||
Transaction p2shRefundTransaction = BitcoinyHTLC.buildRefundTransaction(digibyte.getNetworkParameters(), refundAmount, refundKey,
|
||||
fundingOutputs, redeemScriptA, lockTimeA, receiving.getHash());
|
||||
|
||||
ravencoin.broadcastTransaction(p2shRefundTransaction);
|
||||
digibyte.broadcastTransaction(p2shRefundTransaction);
|
||||
break;
|
||||
}
|
||||
}
|
@@ -100,7 +100,7 @@ public class TradeBot implements Listener {
|
||||
acctTradeBotSuppliers.put(DogecoinACCTv1.class, DogecoinACCTv1TradeBot::getInstance);
|
||||
acctTradeBotSuppliers.put(DogecoinACCTv2.class, DogecoinACCTv2TradeBot::getInstance);
|
||||
acctTradeBotSuppliers.put(DogecoinACCTv3.class, DogecoinACCTv3TradeBot::getInstance);
|
||||
acctTradeBotSuppliers.put(RavencoinACCTv3.class, RavencoinACCTv3TradeBot::getInstance);
|
||||
acctTradeBotSuppliers.put(DigibyteACCTv3.class, DigibyteACCTv3TradeBot::getInstance);
|
||||
}
|
||||
|
||||
private static TradeBot instance;
|
||||
|
@@ -10,22 +10,22 @@ import org.bitcoinj.core.Context;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
import org.bitcoinj.params.RegTestParams;
|
||||
import org.bitcoinj.params.TestNet3Params;
|
||||
import org.libdohj.params.RavencoinMainNetParams;
|
||||
import org.libdohj.params.DigibyteMainNetParams;
|
||||
import org.qortal.crosschain.ElectrumX.Server;
|
||||
import org.qortal.crosschain.ElectrumX.Server.ConnectionType;
|
||||
import org.qortal.settings.Settings;
|
||||
|
||||
public class Ravencoin extends Bitcoiny {
|
||||
public class Digibyte extends Bitcoiny {
|
||||
|
||||
public static final String CURRENCY_CODE = "RVN";
|
||||
public static final String CURRENCY_CODE = "DGB";
|
||||
|
||||
private static final Coin DEFAULT_FEE_PER_KB = Coin.valueOf(1125000); // 0.01125 RVN per 1000 bytes
|
||||
private static final Coin DEFAULT_FEE_PER_KB = Coin.valueOf(100000); // 0.001 DGB per 1000 bytes
|
||||
|
||||
private static final long MINIMUM_ORDER_AMOUNT = 1000000; // 0.01 RVN minimum order, to avoid dust errors
|
||||
private static final long MINIMUM_ORDER_AMOUNT = 1000000; // 0.01 DGB minimum order, to avoid dust errors
|
||||
|
||||
// Temporary values until a dynamic fee system is written.
|
||||
private static final long MAINNET_FEE = 1000000L;
|
||||
private static final long NON_MAINNET_FEE = 1000000L; // enough for TESTNET3 and should be OK for REGTEST
|
||||
private static final long MAINNET_FEE = 10000L;
|
||||
private static final long NON_MAINNET_FEE = 10000L; // enough for TESTNET3 and should be OK for REGTEST
|
||||
|
||||
private static final Map<ConnectionType, Integer> DEFAULT_ELECTRUMX_PORTS = new EnumMap<>(ConnectionType.class);
|
||||
static {
|
||||
@@ -33,30 +33,26 @@ public class Ravencoin extends Bitcoiny {
|
||||
DEFAULT_ELECTRUMX_PORTS.put(ConnectionType.SSL, 50002);
|
||||
}
|
||||
|
||||
public enum RavencoinNet {
|
||||
public enum DigibyteNet {
|
||||
MAIN {
|
||||
@Override
|
||||
public NetworkParameters getParams() {
|
||||
return RavencoinMainNetParams.get();
|
||||
return DigibyteMainNetParams.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Server> getServers() {
|
||||
return Arrays.asList(
|
||||
// Servers chosen on NO BASIS WHATSOEVER from various sources!
|
||||
// Status verified at https://1209k.com/bitcoin-eye/ele.php?chain=rvn
|
||||
new Server("aethyn.com", ConnectionType.SSL, 50002),
|
||||
new Server("electrum2.rvn.rocks", ConnectionType.SSL, 50002),
|
||||
new Server("rvn-dashboard.com", ConnectionType.SSL, 50002),
|
||||
new Server("rvn4lyfe.com", ConnectionType.SSL, 50002),
|
||||
new Server("electrum1.cipig.net", ConnectionType.SSL, 20051),
|
||||
new Server("electrum2.cipig.net", ConnectionType.SSL, 20051),
|
||||
new Server("electrum3.cipig.net", ConnectionType.SSL, 20051));
|
||||
// Status verified at https://1209k.com/bitcoin-eye/ele.php?chain=dgb
|
||||
new Server("electrum1.cipig.net", ConnectionType.SSL, 20059),
|
||||
new Server("electrum2.cipig.net", ConnectionType.SSL, 20059),
|
||||
new Server("electrum3.cipig.net", ConnectionType.SSL, 20059));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGenesisHash() {
|
||||
return "0000006b444bc2f2ffe627be9d9e7e7a0730000870ef6eb6da46c8eae389df90";
|
||||
return "7497ea1b465eb39f1c8f507bc877078fe016d6fcb6dfad3a64c98dcc6e1e8496";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -78,7 +74,7 @@ public class Ravencoin extends Bitcoiny {
|
||||
|
||||
@Override
|
||||
public String getGenesisHash() {
|
||||
return "000000ecfc5e6324a079542221d00e10362bdc894d56500c414060eea8a3ad5a";
|
||||
return "308ea0711d5763be2995670dd9ca9872753561285a84da1d58be58acaa822252";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -117,27 +113,27 @@ public class Ravencoin extends Bitcoiny {
|
||||
public abstract long getP2shFee(Long timestamp) throws ForeignBlockchainException;
|
||||
}
|
||||
|
||||
private static Ravencoin instance;
|
||||
private static Digibyte instance;
|
||||
|
||||
private final RavencoinNet ravencoinNet;
|
||||
private final DigibyteNet digibyteNet;
|
||||
|
||||
// Constructors and instance
|
||||
|
||||
private Ravencoin(RavencoinNet ravencoinNet, BitcoinyBlockchainProvider blockchain, Context bitcoinjContext, String currencyCode) {
|
||||
private Digibyte(DigibyteNet digibyteNet, BitcoinyBlockchainProvider blockchain, Context bitcoinjContext, String currencyCode) {
|
||||
super(blockchain, bitcoinjContext, currencyCode);
|
||||
this.ravencoinNet = ravencoinNet;
|
||||
this.digibyteNet = digibyteNet;
|
||||
|
||||
LOGGER.info(() -> String.format("Starting Ravencoin support using %s", this.ravencoinNet.name()));
|
||||
LOGGER.info(() -> String.format("Starting Digibyte support using %s", this.digibyteNet.name()));
|
||||
}
|
||||
|
||||
public static synchronized Ravencoin getInstance() {
|
||||
public static synchronized Digibyte getInstance() {
|
||||
if (instance == null) {
|
||||
RavencoinNet ravencoinNet = Settings.getInstance().getRavencoinNet();
|
||||
DigibyteNet digibyteNet = Settings.getInstance().getDigibyteNet();
|
||||
|
||||
BitcoinyBlockchainProvider electrumX = new ElectrumX("Ravencoin-" + ravencoinNet.name(), ravencoinNet.getGenesisHash(), ravencoinNet.getServers(), DEFAULT_ELECTRUMX_PORTS);
|
||||
Context bitcoinjContext = new Context(ravencoinNet.getParams());
|
||||
BitcoinyBlockchainProvider electrumX = new ElectrumX("Digibyte-" + digibyteNet.name(), digibyteNet.getGenesisHash(), digibyteNet.getServers(), DEFAULT_ELECTRUMX_PORTS);
|
||||
Context bitcoinjContext = new Context(digibyteNet.getParams());
|
||||
|
||||
instance = new Ravencoin(ravencoinNet, electrumX, bitcoinjContext, CURRENCY_CODE);
|
||||
instance = new Digibyte(digibyteNet, electrumX, bitcoinjContext, CURRENCY_CODE);
|
||||
}
|
||||
|
||||
return instance;
|
||||
@@ -162,14 +158,14 @@ public class Ravencoin extends Bitcoiny {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns estimated RVN fee, in sats per 1000bytes, optionally for historic timestamp.
|
||||
* Returns estimated DGB fee, in sats per 1000bytes, optionally for historic timestamp.
|
||||
*
|
||||
* @param timestamp optional milliseconds since epoch, or null for 'now'
|
||||
* @return sats per 1000bytes, or throws ForeignBlockchainException if something went wrong
|
||||
*/
|
||||
@Override
|
||||
public long getP2shFee(Long timestamp) throws ForeignBlockchainException {
|
||||
return this.ravencoinNet.getP2shFee(timestamp);
|
||||
return this.digibyteNet.getP2shFee(timestamp);
|
||||
}
|
||||
|
||||
}
|
@@ -29,7 +29,7 @@ import static org.ciyam.at.OpCode.calcOffset;
|
||||
*
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>Bob generates Ravencoin & Qortal 'trade' keys
|
||||
* <li>Bob generates Digibyte & Qortal 'trade' keys
|
||||
* <ul>
|
||||
* <li>private key required to sign P2SH redeem tx</li>
|
||||
* <li>private key could be used to create 'secret' (e.g. double-SHA256)</li>
|
||||
@@ -42,12 +42,12 @@ import static org.ciyam.at.OpCode.calcOffset;
|
||||
* </li>
|
||||
* <li>Alice finds Qortal AT and wants to trade
|
||||
* <ul>
|
||||
* <li>Alice generates Ravencoin & Qortal 'trade' keys</li>
|
||||
* <li>Alice funds Ravencoin P2SH-A</li>
|
||||
* <li>Alice generates Digibyte & Qortal 'trade' keys</li>
|
||||
* <li>Alice funds Digibyte P2SH-A</li>
|
||||
* <li>Alice sends 'offer' MESSAGE to Bob from her Qortal trade address, containing:
|
||||
* <ul>
|
||||
* <li>hash-of-secret-A</li>
|
||||
* <li>her 'trade' Ravencoin PKH</li>
|
||||
* <li>her 'trade' Digibyte PKH</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
@@ -58,7 +58,7 @@ import static org.ciyam.at.OpCode.calcOffset;
|
||||
* <li>Sends 'trade' MESSAGE to Qortal AT from his trade address, containing:
|
||||
* <ul>
|
||||
* <li>Alice's trade Qortal address</li>
|
||||
* <li>Alice's trade Ravencoin PKH</li>
|
||||
* <li>Alice's trade Digibyte PKH</li>
|
||||
* <li>hash-of-secret-A</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
@@ -77,18 +77,18 @@ import static org.ciyam.at.OpCode.calcOffset;
|
||||
* </li>
|
||||
* <li>Bob checks AT, extracts secret-A
|
||||
* <ul>
|
||||
* <li>Bob redeems P2SH-A using his Ravencoin trade key and secret-A</li>
|
||||
* <li>P2SH-A RVN funds end up at Ravencoin address determined by redeem transaction output(s)</li>
|
||||
* <li>Bob redeems P2SH-A using his Digibyte trade key and secret-A</li>
|
||||
* <li>P2SH-A DGB funds end up at Digibyte address determined by redeem transaction output(s)</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
public class RavencoinACCTv3 implements ACCT {
|
||||
public class DigibyteACCTv3 implements ACCT {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(RavencoinACCTv3.class);
|
||||
private static final Logger LOGGER = LogManager.getLogger(DigibyteACCTv3.class);
|
||||
|
||||
public static final String NAME = RavencoinACCTv3.class.getSimpleName();
|
||||
public static final byte[] CODE_BYTES_HASH = HashCode.fromString("91395fa1ec0dfa35beddb0a7f4cc0a1bede157c38787ddb0af0cf03dfdc10f77").asBytes(); // SHA256 of AT code bytes
|
||||
public static final String NAME = DigibyteACCTv3.class.getSimpleName();
|
||||
public static final byte[] CODE_BYTES_HASH = HashCode.fromString("e6a7dcd87296fae3ce7d80183bf7660c8e2cb4f8746c6a0421a17148f87a0e1d").asBytes(); // SHA256 of AT code bytes
|
||||
|
||||
public static final int SECRET_LENGTH = 32;
|
||||
|
||||
@@ -98,27 +98,27 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
public static final int MODE_BYTE_OFFSET = MachineState.HEADER_LENGTH + (MODE_VALUE_OFFSET * MachineState.VALUE_SIZE);
|
||||
|
||||
public static class OfferMessageData {
|
||||
public byte[] partnerRavencoinPKH;
|
||||
public byte[] partnerDigibytePKH;
|
||||
public byte[] hashOfSecretA;
|
||||
public long lockTimeA;
|
||||
}
|
||||
public static final int OFFER_MESSAGE_LENGTH = 20 /*partnerRavencoinPKH*/ + 20 /*hashOfSecretA*/ + 8 /*lockTimeA*/;
|
||||
public static final int OFFER_MESSAGE_LENGTH = 20 /*partnerDigibytePKH*/ + 20 /*hashOfSecretA*/ + 8 /*lockTimeA*/;
|
||||
public static final int TRADE_MESSAGE_LENGTH = 32 /*partner's Qortal trade address (padded from 25 to 32)*/
|
||||
+ 24 /*partner's Ravencoin PKH (padded from 20 to 24)*/
|
||||
+ 24 /*partner's Digibyte PKH (padded from 20 to 24)*/
|
||||
+ 8 /*AT trade timeout (minutes)*/
|
||||
+ 24 /*hash of secret-A (padded from 20 to 24)*/
|
||||
+ 8 /*lockTimeA*/;
|
||||
public static final int REDEEM_MESSAGE_LENGTH = 32 /*secret-A*/ + 32 /*partner's Qortal receiving address padded from 25 to 32*/;
|
||||
public static final int CANCEL_MESSAGE_LENGTH = 32 /*AT creator's Qortal address*/;
|
||||
|
||||
private static RavencoinACCTv3 instance;
|
||||
private static DigibyteACCTv3 instance;
|
||||
|
||||
private RavencoinACCTv3() {
|
||||
private DigibyteACCTv3() {
|
||||
}
|
||||
|
||||
public static synchronized RavencoinACCTv3 getInstance() {
|
||||
public static synchronized DigibyteACCTv3 getInstance() {
|
||||
if (instance == null)
|
||||
instance = new RavencoinACCTv3();
|
||||
instance = new DigibyteACCTv3();
|
||||
|
||||
return instance;
|
||||
}
|
||||
@@ -135,7 +135,7 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
|
||||
@Override
|
||||
public ForeignBlockchain getBlockchain() {
|
||||
return Ravencoin.getInstance();
|
||||
return Digibyte.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,14 +145,14 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
* 32-byte secret to the AT, before the AT automatically refunds the AT's creator.
|
||||
*
|
||||
* @param creatorTradeAddress AT creator's trade Qortal address
|
||||
* @param ravencoinPublicKeyHash 20-byte HASH160 of creator's trade Ravencoin public key
|
||||
* @param digibytePublicKeyHash 20-byte HASH160 of creator's trade Digibyte public key
|
||||
* @param qortAmount how much QORT to pay trade partner if they send correct 32-byte secrets to AT
|
||||
* @param ravencoinAmount how much RVN the AT creator is expecting to trade
|
||||
* @param digibyteAmount how much DGB the AT creator is expecting to trade
|
||||
* @param tradeTimeout suggested timeout for entire trade
|
||||
*/
|
||||
public static byte[] buildQortalAT(String creatorTradeAddress, byte[] ravencoinPublicKeyHash, long qortAmount, long ravencoinAmount, int tradeTimeout) {
|
||||
if (ravencoinPublicKeyHash.length != 20)
|
||||
throw new IllegalArgumentException("Ravencoin public key hash should be 20 bytes");
|
||||
public static byte[] buildQortalAT(String creatorTradeAddress, byte[] digibytePublicKeyHash, long qortAmount, long digibyteAmount, int tradeTimeout) {
|
||||
if (digibytePublicKeyHash.length != 20)
|
||||
throw new IllegalArgumentException("Digibyte public key hash should be 20 bytes");
|
||||
|
||||
// Labels for data segment addresses
|
||||
int addrCounter = 0;
|
||||
@@ -164,11 +164,11 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
final int addrCreatorTradeAddress3 = addrCounter++;
|
||||
final int addrCreatorTradeAddress4 = addrCounter++;
|
||||
|
||||
final int addrRavencoinPublicKeyHash = addrCounter;
|
||||
final int addrDigibytePublicKeyHash = addrCounter;
|
||||
addrCounter += 4;
|
||||
|
||||
final int addrQortAmount = addrCounter++;
|
||||
final int addrRavencoinAmount = addrCounter++;
|
||||
final int addrDigibyteAmount = addrCounter++;
|
||||
final int addrTradeTimeout = addrCounter++;
|
||||
|
||||
final int addrMessageTxnType = addrCounter++;
|
||||
@@ -179,8 +179,8 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
final int addrQortalPartnerAddressPointer = addrCounter++;
|
||||
final int addrMessageSenderPointer = addrCounter++;
|
||||
|
||||
final int addrTradeMessagePartnerRavencoinPKHOffset = addrCounter++;
|
||||
final int addrPartnerRavencoinPKHPointer = addrCounter++;
|
||||
final int addrTradeMessagePartnerDigibytePKHOffset = addrCounter++;
|
||||
final int addrPartnerDigibytePKHPointer = addrCounter++;
|
||||
final int addrTradeMessageHashOfSecretAOffset = addrCounter++;
|
||||
final int addrHashOfSecretAPointer = addrCounter++;
|
||||
|
||||
@@ -226,7 +226,7 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
final int addrHashOfSecretA = addrCounter;
|
||||
addrCounter += 4;
|
||||
|
||||
final int addrPartnerRavencoinPKH = addrCounter;
|
||||
final int addrPartnerDigibytePKH = addrCounter;
|
||||
addrCounter += 4;
|
||||
|
||||
final int addrPartnerReceivingAddress = addrCounter;
|
||||
@@ -243,17 +243,17 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
byte[] creatorTradeAddressBytes = Base58.decode(creatorTradeAddress);
|
||||
dataByteBuffer.put(Bytes.ensureCapacity(creatorTradeAddressBytes, 32, 0));
|
||||
|
||||
// Ravencoin public key hash
|
||||
assert dataByteBuffer.position() == addrRavencoinPublicKeyHash * MachineState.VALUE_SIZE : "addrRavencoinPublicKeyHash incorrect";
|
||||
dataByteBuffer.put(Bytes.ensureCapacity(ravencoinPublicKeyHash, 32, 0));
|
||||
// Digibyte public key hash
|
||||
assert dataByteBuffer.position() == addrDigibytePublicKeyHash * MachineState.VALUE_SIZE : "addrDigibytePublicKeyHash incorrect";
|
||||
dataByteBuffer.put(Bytes.ensureCapacity(digibytePublicKeyHash, 32, 0));
|
||||
|
||||
// Redeem Qort amount
|
||||
assert dataByteBuffer.position() == addrQortAmount * MachineState.VALUE_SIZE : "addrQortAmount incorrect";
|
||||
dataByteBuffer.putLong(qortAmount);
|
||||
|
||||
// Expected Ravencoin amount
|
||||
assert dataByteBuffer.position() == addrRavencoinAmount * MachineState.VALUE_SIZE : "addrRavencoinAmount incorrect";
|
||||
dataByteBuffer.putLong(ravencoinAmount);
|
||||
// Expected Digibyte amount
|
||||
assert dataByteBuffer.position() == addrDigibyteAmount * MachineState.VALUE_SIZE : "addrDigibyteAmount incorrect";
|
||||
dataByteBuffer.putLong(digibyteAmount);
|
||||
|
||||
// Suggested trade timeout (minutes)
|
||||
assert dataByteBuffer.position() == addrTradeTimeout * MachineState.VALUE_SIZE : "addrTradeTimeout incorrect";
|
||||
@@ -283,13 +283,13 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
assert dataByteBuffer.position() == addrMessageSenderPointer * MachineState.VALUE_SIZE : "addrMessageSenderPointer incorrect";
|
||||
dataByteBuffer.putLong(addrMessageSender1);
|
||||
|
||||
// Offset into 'trade' MESSAGE data payload for extracting partner's Ravencoin PKH
|
||||
assert dataByteBuffer.position() == addrTradeMessagePartnerRavencoinPKHOffset * MachineState.VALUE_SIZE : "addrTradeMessagePartnerRavencoinPKHOffset incorrect";
|
||||
// Offset into 'trade' MESSAGE data payload for extracting partner's Digibyte PKH
|
||||
assert dataByteBuffer.position() == addrTradeMessagePartnerDigibytePKHOffset * MachineState.VALUE_SIZE : "addrTradeMessagePartnerDigibytePKHOffset incorrect";
|
||||
dataByteBuffer.putLong(32L);
|
||||
|
||||
// Index into data segment of partner's Ravencoin PKH, used by GET_B_IND
|
||||
assert dataByteBuffer.position() == addrPartnerRavencoinPKHPointer * MachineState.VALUE_SIZE : "addrPartnerRavencoinPKHPointer incorrect";
|
||||
dataByteBuffer.putLong(addrPartnerRavencoinPKH);
|
||||
// Index into data segment of partner's Digibyte PKH, used by GET_B_IND
|
||||
assert dataByteBuffer.position() == addrPartnerDigibytePKHPointer * MachineState.VALUE_SIZE : "addrPartnerDigibytePKHPointer incorrect";
|
||||
dataByteBuffer.putLong(addrPartnerDigibytePKH);
|
||||
|
||||
// Offset into 'trade' MESSAGE data payload for extracting hash-of-secret-A
|
||||
assert dataByteBuffer.position() == addrTradeMessageHashOfSecretAOffset * MachineState.VALUE_SIZE : "addrTradeMessageHashOfSecretAOffset incorrect";
|
||||
@@ -341,13 +341,13 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
// Use AT creation 'timestamp' as starting point for finding transactions sent to AT
|
||||
codeByteBuffer.put(OpCode.EXT_FUN_RET.compile(FunctionCode.GET_CREATION_TIMESTAMP, addrLastTxnTimestamp));
|
||||
|
||||
/* NOP - to ensure DIGIBYTE ACCT is unique */
|
||||
codeByteBuffer.put(OpCode.NOP.compile());
|
||||
|
||||
// Load B register with AT creator's address so we can save it into addrCreatorAddress1-4
|
||||
codeByteBuffer.put(OpCode.EXT_FUN.compile(FunctionCode.PUT_CREATOR_INTO_B));
|
||||
codeByteBuffer.put(OpCode.EXT_FUN_DAT.compile(FunctionCode.GET_B_IND, addrCreatorAddressPointer));
|
||||
|
||||
/* NOP - to ensure RAVENCOIN ACCT is unique */
|
||||
codeByteBuffer.put(OpCode.NOP.compile());
|
||||
|
||||
// Set restart position to after this opcode
|
||||
codeByteBuffer.put(OpCode.SET_PCS.compile());
|
||||
|
||||
@@ -429,10 +429,10 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
// Save B register into data segment starting at addrQortalPartnerAddress1 (as pointed to by addrQortalPartnerAddressPointer)
|
||||
codeByteBuffer.put(OpCode.EXT_FUN_DAT.compile(FunctionCode.GET_B_IND, addrQortalPartnerAddressPointer));
|
||||
|
||||
// Extract trade partner's Ravencoin public key hash (PKH) from message into B
|
||||
codeByteBuffer.put(OpCode.EXT_FUN_DAT.compile(QortalFunctionCode.PUT_PARTIAL_MESSAGE_FROM_TX_IN_A_INTO_B.value, addrTradeMessagePartnerRavencoinPKHOffset));
|
||||
// Store partner's Ravencoin PKH (we only really use values from B1-B3)
|
||||
codeByteBuffer.put(OpCode.EXT_FUN_DAT.compile(FunctionCode.GET_B_IND, addrPartnerRavencoinPKHPointer));
|
||||
// Extract trade partner's Digibyte public key hash (PKH) from message into B
|
||||
codeByteBuffer.put(OpCode.EXT_FUN_DAT.compile(QortalFunctionCode.PUT_PARTIAL_MESSAGE_FROM_TX_IN_A_INTO_B.value, addrTradeMessagePartnerDigibytePKHOffset));
|
||||
// Store partner's Digibyte PKH (we only really use values from B1-B3)
|
||||
codeByteBuffer.put(OpCode.EXT_FUN_DAT.compile(FunctionCode.GET_B_IND, addrPartnerDigibytePKHPointer));
|
||||
// Extract AT trade timeout (minutes) (from B4)
|
||||
codeByteBuffer.put(OpCode.EXT_FUN_RET.compile(FunctionCode.GET_B4, addrRefundTimeout));
|
||||
|
||||
@@ -543,7 +543,7 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
// We're finished forever (finishing auto-refunds remaining balance to AT creator)
|
||||
codeByteBuffer.put(OpCode.FIN_IMD.compile());
|
||||
} catch (CompilationException e) {
|
||||
throw new IllegalStateException("Unable to compile RVN-QORT ACCT?", e);
|
||||
throw new IllegalStateException("Unable to compile DGB-QORT ACCT?", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
byte[] codeBytes = new byte[codeByteBuffer.limit()];
|
||||
codeByteBuffer.get(codeBytes);
|
||||
|
||||
assert Arrays.equals(Crypto.digest(codeBytes), RavencoinACCTv3.CODE_BYTES_HASH)
|
||||
assert Arrays.equals(Crypto.digest(codeBytes), DigibyteACCTv3.CODE_BYTES_HASH)
|
||||
: String.format("BTCACCT.CODE_BYTES_HASH mismatch: expected %s, actual %s", HashCode.fromBytes(CODE_BYTES_HASH), HashCode.fromBytes(Crypto.digest(codeBytes)));
|
||||
|
||||
final short ciyamAtVersion = 2;
|
||||
@@ -590,7 +590,7 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
|
||||
CrossChainTradeData tradeData = new CrossChainTradeData();
|
||||
|
||||
tradeData.foreignBlockchain = SupportedBlockchain.RAVENCOIN.name();
|
||||
tradeData.foreignBlockchain = SupportedBlockchain.DIGIBYTE.name();
|
||||
tradeData.acctName = NAME;
|
||||
|
||||
tradeData.qortalAtAddress = atAddress;
|
||||
@@ -611,7 +611,7 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
tradeData.qortalCreatorTradeAddress = Base58.encode(addressBytes);
|
||||
dataByteBuffer.position(dataByteBuffer.position() + 32 - addressBytes.length);
|
||||
|
||||
// Creator's Ravencoin/foreign public key hash
|
||||
// Creator's Digibyte/foreign public key hash
|
||||
tradeData.creatorForeignPKH = new byte[20];
|
||||
dataByteBuffer.get(tradeData.creatorForeignPKH);
|
||||
dataByteBuffer.position(dataByteBuffer.position() + 32 - tradeData.creatorForeignPKH.length); // skip to 32 bytes
|
||||
@@ -622,7 +622,7 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
// Redeem payout
|
||||
tradeData.qortAmount = dataByteBuffer.getLong();
|
||||
|
||||
// Expected RVN amount
|
||||
// Expected DGB amount
|
||||
tradeData.expectedForeignAmount = dataByteBuffer.getLong();
|
||||
|
||||
// Trade timeout
|
||||
@@ -646,10 +646,10 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
// Skip pointer to message sender
|
||||
dataByteBuffer.position(dataByteBuffer.position() + 8);
|
||||
|
||||
// Skip 'trade' message data offset for partner's Ravencoin PKH
|
||||
// Skip 'trade' message data offset for partner's Digibyte PKH
|
||||
dataByteBuffer.position(dataByteBuffer.position() + 8);
|
||||
|
||||
// Skip pointer to partner's Ravencoin PKH
|
||||
// Skip pointer to partner's Digibyte PKH
|
||||
dataByteBuffer.position(dataByteBuffer.position() + 8);
|
||||
|
||||
// Skip 'trade' message data offset for hash-of-secret-A
|
||||
@@ -715,10 +715,10 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
dataByteBuffer.get(hashOfSecretA);
|
||||
dataByteBuffer.position(dataByteBuffer.position() + 32 - hashOfSecretA.length); // skip to 32 bytes
|
||||
|
||||
// Potential partner's Ravencoin PKH
|
||||
byte[] partnerRavencoinPKH = new byte[20];
|
||||
dataByteBuffer.get(partnerRavencoinPKH);
|
||||
dataByteBuffer.position(dataByteBuffer.position() + 32 - partnerRavencoinPKH.length); // skip to 32 bytes
|
||||
// Potential partner's Digibyte PKH
|
||||
byte[] partnerDigibytePKH = new byte[20];
|
||||
dataByteBuffer.get(partnerDigibytePKH);
|
||||
dataByteBuffer.position(dataByteBuffer.position() + 32 - partnerDigibytePKH.length); // skip to 32 bytes
|
||||
|
||||
// Partner's receiving address (if present)
|
||||
byte[] partnerReceivingAddress = new byte[25];
|
||||
@@ -737,7 +737,7 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
tradeData.tradeRefundHeight = new Timestamp(tradeRefundTimestamp).blockHeight;
|
||||
tradeData.qortalPartnerAddress = qortalRecipient;
|
||||
tradeData.hashOfSecretA = hashOfSecretA;
|
||||
tradeData.partnerForeignPKH = partnerRavencoinPKH;
|
||||
tradeData.partnerForeignPKH = partnerDigibytePKH;
|
||||
tradeData.lockTimeA = lockTimeA;
|
||||
|
||||
if (mode == AcctMode.REDEEMED)
|
||||
@@ -763,7 +763,7 @@ public class RavencoinACCTv3 implements ACCT {
|
||||
return null;
|
||||
|
||||
OfferMessageData offerMessageData = new OfferMessageData();
|
||||
offerMessageData.partnerRavencoinPKH = Arrays.copyOfRange(messageData, 0, 20);
|
||||
offerMessageData.partnerDigibytePKH = Arrays.copyOfRange(messageData, 0, 20);
|
||||
offerMessageData.hashOfSecretA = Arrays.copyOfRange(messageData, 20, 40);
|
||||
offerMessageData.lockTimeA = BitTwiddling.longFromBEBytes(messageData, 40);
|
||||
|
@@ -59,17 +59,17 @@ public enum SupportedBlockchain {
|
||||
}
|
||||
},
|
||||
|
||||
RAVENCOIN(Arrays.asList(
|
||||
Triple.valueOf(RavencoinACCTv3.NAME, RavencoinACCTv3.CODE_BYTES_HASH, RavencoinACCTv3::getInstance)
|
||||
DIGIBYTE(Arrays.asList(
|
||||
Triple.valueOf(DigibyteACCTv3.NAME, DigibyteACCTv3.CODE_BYTES_HASH, DigibyteACCTv3::getInstance)
|
||||
)) {
|
||||
@Override
|
||||
public ForeignBlockchain getInstance() {
|
||||
return Ravencoin.getInstance();
|
||||
return Digibyte.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ACCT getLatestAcct() {
|
||||
return RavencoinACCTv3.getInstance();
|
||||
return DigibyteACCTv3.getInstance();
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -26,7 +26,7 @@ import org.qortal.controller.arbitrary.ArbitraryDataStorageManager.*;
|
||||
import org.qortal.crosschain.Bitcoin.BitcoinNet;
|
||||
import org.qortal.crosschain.Litecoin.LitecoinNet;
|
||||
import org.qortal.crosschain.Dogecoin.DogecoinNet;
|
||||
import org.qortal.crosschain.Ravencoin.RavencoinNet;
|
||||
import org.qortal.crosschain.Digibyte.DigibyteNet;
|
||||
import org.qortal.utils.EnumUtils;
|
||||
|
||||
// All properties to be converted to JSON via JAXB
|
||||
@@ -223,7 +223,7 @@ public class Settings {
|
||||
private BitcoinNet bitcoinNet = BitcoinNet.MAIN;
|
||||
private LitecoinNet litecoinNet = LitecoinNet.MAIN;
|
||||
private DogecoinNet dogecoinNet = DogecoinNet.MAIN;
|
||||
private RavencoinNet ravencoinNet = RavencoinNet.MAIN;
|
||||
private DigibyteNet digibyteNet = DigibyteNet.MAIN;
|
||||
// Also crosschain-related:
|
||||
/** Whether to show SysTray pop-up notifications when trade-bot entries change state */
|
||||
private boolean tradebotSystrayEnabled = false;
|
||||
@@ -682,8 +682,8 @@ public class Settings {
|
||||
return this.dogecoinNet;
|
||||
}
|
||||
|
||||
public RavencoinNet getRavencoinNet() {
|
||||
return this.ravencoinNet;
|
||||
public DigibyteNet getDigibyteNet() {
|
||||
return this.digibyteNet;
|
||||
}
|
||||
|
||||
public boolean isTradebotSystrayEnabled() {
|
||||
|
@@ -11,34 +11,34 @@ import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.qortal.crosschain.ForeignBlockchainException;
|
||||
import org.qortal.crosschain.Ravencoin;
|
||||
import org.qortal.crosschain.Digibyte;
|
||||
import org.qortal.crosschain.BitcoinyHTLC;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.test.common.Common;
|
||||
|
||||
public class RavencoinTests extends Common {
|
||||
public class DigibyteTests extends Common {
|
||||
|
||||
private Ravencoin ravencoin;
|
||||
private Digibyte digibyte;
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings(); // TestNet3
|
||||
ravencoin = Ravencoin.getInstance();
|
||||
digibyte = Digibyte.getInstance();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() {
|
||||
Ravencoin.resetForTesting();
|
||||
ravencoin = null;
|
||||
Digibyte.resetForTesting();
|
||||
digibyte = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMedianBlockTime() throws BlockStoreException, ForeignBlockchainException {
|
||||
long before = System.currentTimeMillis();
|
||||
System.out.println(String.format("Ravencoin median blocktime: %d", ravencoin.getMedianBlockTime()));
|
||||
System.out.println(String.format("Digibyte median blocktime: %d", digibyte.getMedianBlockTime()));
|
||||
long afterFirst = System.currentTimeMillis();
|
||||
|
||||
System.out.println(String.format("Ravencoin median blocktime: %d", ravencoin.getMedianBlockTime()));
|
||||
System.out.println(String.format("Digibyte median blocktime: %d", digibyte.getMedianBlockTime()));
|
||||
long afterSecond = System.currentTimeMillis();
|
||||
|
||||
long firstPeriod = afterFirst - before;
|
||||
@@ -57,7 +57,7 @@ public class RavencoinTests extends Common {
|
||||
String p2shAddress = "2N8WCg52ULCtDSMjkgVTm5mtPdCsUptkHWE";
|
||||
|
||||
byte[] expectedSecret = "This string is exactly 32 bytes!".getBytes();
|
||||
byte[] secret = BitcoinyHTLC.findHtlcSecret(ravencoin, p2shAddress);
|
||||
byte[] secret = BitcoinyHTLC.findHtlcSecret(digibyte, p2shAddress);
|
||||
|
||||
assertNotNull("secret not found", secret);
|
||||
assertTrue("secret incorrect", Arrays.equals(expectedSecret, secret));
|
||||
@@ -71,12 +71,12 @@ public class RavencoinTests extends Common {
|
||||
String recipient = "2N8WCg52ULCtDSMjkgVTm5mtPdCsUptkHWE";
|
||||
long amount = 1000L;
|
||||
|
||||
Transaction transaction = ravencoin.buildSpend(xprv58, recipient, amount);
|
||||
Transaction transaction = digibyte.buildSpend(xprv58, recipient, amount);
|
||||
assertNotNull("insufficient funds", transaction);
|
||||
|
||||
// Check spent key caching doesn't affect outcome
|
||||
|
||||
transaction = ravencoin.buildSpend(xprv58, recipient, amount);
|
||||
transaction = digibyte.buildSpend(xprv58, recipient, amount);
|
||||
assertNotNull("insufficient funds", transaction);
|
||||
}
|
||||
|
||||
@@ -84,19 +84,19 @@ public class RavencoinTests extends Common {
|
||||
public void testGetWalletBalance() {
|
||||
String xprv58 = "tprv8ZgxMBicQKsPdahhFSrCdvC1bsWyzHHZfTneTVqUXN6s1wEtZLwAkZXzFP6TYLg2aQMecZLXLre5bTVGajEB55L1HYJcawpdFG66STVAWPJ";
|
||||
|
||||
Long balance = ravencoin.getWalletBalance(xprv58);
|
||||
Long balance = digibyte.getWalletBalance(xprv58);
|
||||
|
||||
assertNotNull(balance);
|
||||
|
||||
System.out.println(ravencoin.format(balance));
|
||||
System.out.println(digibyte.format(balance));
|
||||
|
||||
// Check spent key caching doesn't affect outcome
|
||||
|
||||
Long repeatBalance = ravencoin.getWalletBalance(xprv58);
|
||||
Long repeatBalance = digibyte.getWalletBalance(xprv58);
|
||||
|
||||
assertNotNull(repeatBalance);
|
||||
|
||||
System.out.println(ravencoin.format(repeatBalance));
|
||||
System.out.println(digibyte.format(repeatBalance));
|
||||
|
||||
assertEquals(balance, repeatBalance);
|
||||
}
|
||||
@@ -105,7 +105,7 @@ public class RavencoinTests extends Common {
|
||||
public void testGetUnusedReceiveAddress() throws ForeignBlockchainException {
|
||||
String xprv58 = "tprv8ZgxMBicQKsPdahhFSrCdvC1bsWyzHHZfTneTVqUXN6s1wEtZLwAkZXzFP6TYLg2aQMecZLXLre5bTVGajEB55L1HYJcawpdFG66STVAWPJ";
|
||||
|
||||
String address = ravencoin.getUnusedReceiveAddress(xprv58);
|
||||
String address = digibyte.getUnusedReceiveAddress(xprv58);
|
||||
|
||||
assertNotNull(address);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package org.qortal.test.crosschain.ravencoinv3;
|
||||
package org.qortal.test.crosschain.digibytev3;
|
||||
|
||||
import com.google.common.hash.HashCode;
|
||||
import com.google.common.primitives.Bytes;
|
||||
@@ -9,7 +9,7 @@ import org.qortal.account.PrivateKeyAccount;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.Block;
|
||||
import org.qortal.crosschain.AcctMode;
|
||||
import org.qortal.crosschain.RavencoinACCTv3;
|
||||
import org.qortal.crosschain.DigibyteACCTv3;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.data.at.ATData;
|
||||
import org.qortal.data.at.ATStateData;
|
||||
@@ -41,15 +41,15 @@ import java.util.function.Function;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class RavencoinACCTv3Tests extends Common {
|
||||
public class DigibyteACCTv3Tests extends Common {
|
||||
|
||||
public static final byte[] secretA = "This string is exactly 32 bytes!".getBytes();
|
||||
public static final byte[] hashOfSecretA = Crypto.hash160(secretA); // daf59884b4d1aec8c1b17102530909ee43c0151a
|
||||
public static final byte[] ravencoinPublicKeyHash = HashCode.fromString("bb00bb11bb22bb33bb44bb55bb66bb77bb88bb99").asBytes();
|
||||
public static final byte[] digibytePublicKeyHash = HashCode.fromString("bb00bb11bb22bb33bb44bb55bb66bb77bb88bb99").asBytes();
|
||||
public static final int tradeTimeout = 20; // blocks
|
||||
public static final long redeemAmount = 80_40200000L;
|
||||
public static final long fundingAmount = 123_45600000L;
|
||||
public static final long ravencoinAmount = 864200L; // 0.00864200 RVN
|
||||
public static final long digibyteAmount = 864200L; // 0.00864200 DGB
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
@@ -62,7 +62,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
public void testCompile() {
|
||||
PrivateKeyAccount tradeAccount = createTradeAccount(null);
|
||||
|
||||
byte[] creationBytes = RavencoinACCTv3.buildQortalAT(tradeAccount.getAddress(), ravencoinPublicKeyHash, redeemAmount, ravencoinAmount, tradeTimeout);
|
||||
byte[] creationBytes = DigibyteACCTv3.buildQortalAT(tradeAccount.getAddress(), digibytePublicKeyHash, redeemAmount, digibyteAmount, tradeTimeout);
|
||||
assertNotNull(creationBytes);
|
||||
|
||||
System.out.println("AT creation bytes: " + HashCode.fromBytes(creationBytes).toString());
|
||||
@@ -136,7 +136,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
long deployersPostDeploymentBalance = deployersInitialBalance - fundingAmount - deployAtFee;
|
||||
|
||||
// Send creator's address to AT, instead of typical partner's address
|
||||
byte[] messageData = RavencoinACCTv3.getInstance().buildCancelMessage(deployer.getAddress());
|
||||
byte[] messageData = DigibyteACCTv3.getInstance().buildCancelMessage(deployer.getAddress());
|
||||
MessageTransaction messageTransaction = sendMessage(repository, deployer, messageData, atAddress);
|
||||
long messageFee = messageTransaction.getTransactionData().getFee();
|
||||
|
||||
@@ -150,7 +150,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
assertTrue(atData.getIsFinished());
|
||||
|
||||
// AT should be in CANCELLED mode
|
||||
CrossChainTradeData tradeData = RavencoinACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
CrossChainTradeData tradeData = DigibyteACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
assertEquals(AcctMode.CANCELLED, tradeData.mode);
|
||||
|
||||
// Check balances
|
||||
@@ -209,7 +209,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
assertTrue(atData.getIsFinished());
|
||||
|
||||
// AT should be in CANCELLED mode
|
||||
CrossChainTradeData tradeData = RavencoinACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
CrossChainTradeData tradeData = DigibyteACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
assertEquals(AcctMode.CANCELLED, tradeData.mode);
|
||||
}
|
||||
}
|
||||
@@ -232,10 +232,10 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
|
||||
long partnersOfferMessageTransactionTimestamp = System.currentTimeMillis();
|
||||
int lockTimeA = calcTestLockTimeA(partnersOfferMessageTransactionTimestamp);
|
||||
int refundTimeout = RavencoinACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
int refundTimeout = DigibyteACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
|
||||
// Send trade info to AT
|
||||
byte[] messageData = RavencoinACCTv3.buildTradeMessage(partner.getAddress(), ravencoinPublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
byte[] messageData = DigibyteACCTv3.buildTradeMessage(partner.getAddress(), digibytePublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
MessageTransaction messageTransaction = sendMessage(repository, tradeAccount, messageData, atAddress);
|
||||
|
||||
Block postDeploymentBlock = BlockUtils.mintBlock(repository);
|
||||
@@ -247,7 +247,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
describeAt(repository, atAddress);
|
||||
|
||||
ATData atData = repository.getATRepository().fromATAddress(atAddress);
|
||||
CrossChainTradeData tradeData = RavencoinACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
CrossChainTradeData tradeData = DigibyteACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
|
||||
// AT should be in TRADE mode
|
||||
assertEquals(AcctMode.TRADING, tradeData.mode);
|
||||
@@ -258,8 +258,8 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
// Check trade partner Qortal address was extracted correctly
|
||||
assertEquals(partner.getAddress(), tradeData.qortalPartnerAddress);
|
||||
|
||||
// Check trade partner's ravencoin PKH was extracted correctly
|
||||
assertTrue(Arrays.equals(ravencoinPublicKeyHash, tradeData.partnerForeignPKH));
|
||||
// Check trade partner's digibyte PKH was extracted correctly
|
||||
assertTrue(Arrays.equals(digibytePublicKeyHash, tradeData.partnerForeignPKH));
|
||||
|
||||
// Test orphaning
|
||||
BlockUtils.orphanToBlock(repository, postDeploymentBlockHeight);
|
||||
@@ -293,10 +293,10 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
|
||||
long partnersOfferMessageTransactionTimestamp = System.currentTimeMillis();
|
||||
int lockTimeA = calcTestLockTimeA(partnersOfferMessageTransactionTimestamp);
|
||||
int refundTimeout = RavencoinACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
int refundTimeout = DigibyteACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
|
||||
// Send trade info to AT BUT NOT FROM AT CREATOR
|
||||
byte[] messageData = RavencoinACCTv3.buildTradeMessage(partner.getAddress(), ravencoinPublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
byte[] messageData = DigibyteACCTv3.buildTradeMessage(partner.getAddress(), digibytePublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
MessageTransaction messageTransaction = sendMessage(repository, bystander, messageData, atAddress);
|
||||
|
||||
BlockUtils.mintBlock(repository);
|
||||
@@ -309,7 +309,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
describeAt(repository, atAddress);
|
||||
|
||||
ATData atData = repository.getATRepository().fromATAddress(atAddress);
|
||||
CrossChainTradeData tradeData = RavencoinACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
CrossChainTradeData tradeData = DigibyteACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
|
||||
// AT should still be in OFFER mode
|
||||
assertEquals(AcctMode.OFFERING, tradeData.mode);
|
||||
@@ -334,10 +334,10 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
|
||||
long partnersOfferMessageTransactionTimestamp = System.currentTimeMillis();
|
||||
int lockTimeA = calcTestLockTimeA(partnersOfferMessageTransactionTimestamp);
|
||||
int refundTimeout = RavencoinACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
int refundTimeout = DigibyteACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
|
||||
// Send trade info to AT
|
||||
byte[] messageData = RavencoinACCTv3.buildTradeMessage(partner.getAddress(), ravencoinPublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
byte[] messageData = DigibyteACCTv3.buildTradeMessage(partner.getAddress(), digibytePublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
MessageTransaction messageTransaction = sendMessage(repository, tradeAccount, messageData, atAddress);
|
||||
|
||||
Block postDeploymentBlock = BlockUtils.mintBlock(repository);
|
||||
@@ -356,7 +356,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
assertTrue(atData.getIsFinished());
|
||||
|
||||
// AT should be in REFUNDED mode
|
||||
CrossChainTradeData tradeData = RavencoinACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
CrossChainTradeData tradeData = DigibyteACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
assertEquals(AcctMode.REFUNDED, tradeData.mode);
|
||||
|
||||
// Test orphaning
|
||||
@@ -388,17 +388,17 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
|
||||
long partnersOfferMessageTransactionTimestamp = System.currentTimeMillis();
|
||||
int lockTimeA = calcTestLockTimeA(partnersOfferMessageTransactionTimestamp);
|
||||
int refundTimeout = RavencoinACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
int refundTimeout = DigibyteACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
|
||||
// Send trade info to AT
|
||||
byte[] messageData = RavencoinACCTv3.buildTradeMessage(partner.getAddress(), ravencoinPublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
byte[] messageData = DigibyteACCTv3.buildTradeMessage(partner.getAddress(), digibytePublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
MessageTransaction messageTransaction = sendMessage(repository, tradeAccount, messageData, atAddress);
|
||||
|
||||
// Give AT time to process message
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
// Send correct secret to AT, from correct account
|
||||
messageData = RavencoinACCTv3.buildRedeemMessage(secretA, partner.getAddress());
|
||||
messageData = DigibyteACCTv3.buildRedeemMessage(secretA, partner.getAddress());
|
||||
messageTransaction = sendMessage(repository, partner, messageData, atAddress);
|
||||
|
||||
// AT should send funds in the next block
|
||||
@@ -412,7 +412,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
assertTrue(atData.getIsFinished());
|
||||
|
||||
// AT should be in REDEEMED mode
|
||||
CrossChainTradeData tradeData = RavencoinACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
CrossChainTradeData tradeData = DigibyteACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
assertEquals(AcctMode.REDEEMED, tradeData.mode);
|
||||
|
||||
// Check balances
|
||||
@@ -459,17 +459,17 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
|
||||
long partnersOfferMessageTransactionTimestamp = System.currentTimeMillis();
|
||||
int lockTimeA = calcTestLockTimeA(partnersOfferMessageTransactionTimestamp);
|
||||
int refundTimeout = RavencoinACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
int refundTimeout = DigibyteACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
|
||||
// Send trade info to AT
|
||||
byte[] messageData = RavencoinACCTv3.buildTradeMessage(partner.getAddress(), ravencoinPublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
byte[] messageData = DigibyteACCTv3.buildTradeMessage(partner.getAddress(), digibytePublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
MessageTransaction messageTransaction = sendMessage(repository, tradeAccount, messageData, atAddress);
|
||||
|
||||
// Give AT time to process message
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
// Send correct secret to AT, but from wrong account
|
||||
messageData = RavencoinACCTv3.buildRedeemMessage(secretA, partner.getAddress());
|
||||
messageData = DigibyteACCTv3.buildRedeemMessage(secretA, partner.getAddress());
|
||||
messageTransaction = sendMessage(repository, bystander, messageData, atAddress);
|
||||
|
||||
// AT should NOT send funds in the next block
|
||||
@@ -483,7 +483,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
assertFalse(atData.getIsFinished());
|
||||
|
||||
// AT should still be in TRADE mode
|
||||
CrossChainTradeData tradeData = RavencoinACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
CrossChainTradeData tradeData = DigibyteACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
assertEquals(AcctMode.TRADING, tradeData.mode);
|
||||
|
||||
// Check balances
|
||||
@@ -517,10 +517,10 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
|
||||
long partnersOfferMessageTransactionTimestamp = System.currentTimeMillis();
|
||||
int lockTimeA = calcTestLockTimeA(partnersOfferMessageTransactionTimestamp);
|
||||
int refundTimeout = RavencoinACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
int refundTimeout = DigibyteACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
|
||||
// Send trade info to AT
|
||||
byte[] messageData = RavencoinACCTv3.buildTradeMessage(partner.getAddress(), ravencoinPublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
byte[] messageData = DigibyteACCTv3.buildTradeMessage(partner.getAddress(), digibytePublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
MessageTransaction messageTransaction = sendMessage(repository, tradeAccount, messageData, atAddress);
|
||||
|
||||
// Give AT time to process message
|
||||
@@ -529,7 +529,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
// Send incorrect secret to AT, from correct account
|
||||
byte[] wrongSecret = new byte[32];
|
||||
RANDOM.nextBytes(wrongSecret);
|
||||
messageData = RavencoinACCTv3.buildRedeemMessage(wrongSecret, partner.getAddress());
|
||||
messageData = DigibyteACCTv3.buildRedeemMessage(wrongSecret, partner.getAddress());
|
||||
messageTransaction = sendMessage(repository, partner, messageData, atAddress);
|
||||
|
||||
// AT should NOT send funds in the next block
|
||||
@@ -543,7 +543,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
assertFalse(atData.getIsFinished());
|
||||
|
||||
// AT should still be in TRADE mode
|
||||
CrossChainTradeData tradeData = RavencoinACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
CrossChainTradeData tradeData = DigibyteACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
assertEquals(AcctMode.TRADING, tradeData.mode);
|
||||
|
||||
long expectedBalance = partnersInitialBalance - messageTransaction.getTransactionData().getFee();
|
||||
@@ -574,10 +574,10 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
|
||||
long partnersOfferMessageTransactionTimestamp = System.currentTimeMillis();
|
||||
int lockTimeA = calcTestLockTimeA(partnersOfferMessageTransactionTimestamp);
|
||||
int refundTimeout = RavencoinACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
int refundTimeout = DigibyteACCTv3.calcRefundTimeout(partnersOfferMessageTransactionTimestamp, lockTimeA);
|
||||
|
||||
// Send trade info to AT
|
||||
byte[] messageData = RavencoinACCTv3.buildTradeMessage(partner.getAddress(), ravencoinPublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
byte[] messageData = DigibyteACCTv3.buildTradeMessage(partner.getAddress(), digibytePublicKeyHash, hashOfSecretA, lockTimeA, refundTimeout);
|
||||
MessageTransaction messageTransaction = sendMessage(repository, tradeAccount, messageData, atAddress);
|
||||
|
||||
// Give AT time to process message
|
||||
@@ -598,7 +598,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
assertFalse(atData.getIsFinished());
|
||||
|
||||
// AT should be in TRADING mode
|
||||
CrossChainTradeData tradeData = RavencoinACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
CrossChainTradeData tradeData = DigibyteACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
assertEquals(AcctMode.TRADING, tradeData.mode);
|
||||
}
|
||||
}
|
||||
@@ -631,7 +631,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
HashCode.fromBytes(codeHash)));
|
||||
|
||||
// Not one of ours?
|
||||
if (!Arrays.equals(codeHash, RavencoinACCTv3.CODE_BYTES_HASH))
|
||||
if (!Arrays.equals(codeHash, DigibyteACCTv3.CODE_BYTES_HASH))
|
||||
continue;
|
||||
|
||||
describeAt(repository, atAddress);
|
||||
@@ -644,7 +644,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
}
|
||||
|
||||
private DeployAtTransaction doDeploy(Repository repository, PrivateKeyAccount deployer, String tradeAddress) throws DataException {
|
||||
byte[] creationBytes = RavencoinACCTv3.buildQortalAT(tradeAddress, ravencoinPublicKeyHash, redeemAmount, ravencoinAmount, tradeTimeout);
|
||||
byte[] creationBytes = DigibyteACCTv3.buildQortalAT(tradeAddress, digibytePublicKeyHash, redeemAmount, digibyteAmount, tradeTimeout);
|
||||
|
||||
long txTimestamp = System.currentTimeMillis();
|
||||
byte[] lastReference = deployer.getLastReference();
|
||||
@@ -655,10 +655,10 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
}
|
||||
|
||||
Long fee = null;
|
||||
String name = "QORT-RVN cross-chain trade";
|
||||
String description = String.format("Qortal-Ravencoin cross-chain trade");
|
||||
String name = "QORT-DGB cross-chain trade";
|
||||
String description = String.format("Qortal-Digibyte cross-chain trade");
|
||||
String atType = "ACCT";
|
||||
String tags = "QORT-RVN ACCT";
|
||||
String tags = "QORT-DGB ACCT";
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(txTimestamp, Group.NO_GROUP, lastReference, deployer.getPublicKey(), fee, null);
|
||||
TransactionData deployAtTransactionData = new DeployAtTransactionData(baseTransactionData, name, description, atType, tags, creationBytes, fundingAmount, Asset.QORT);
|
||||
@@ -721,7 +721,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
|
||||
private void describeAt(Repository repository, String atAddress) throws DataException {
|
||||
ATData atData = repository.getATRepository().fromATAddress(atAddress);
|
||||
CrossChainTradeData tradeData = RavencoinACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
CrossChainTradeData tradeData = DigibyteACCTv3.getInstance().populateTradeData(repository, atData);
|
||||
|
||||
Function<Long, String> epochMilliFormatter = (timestamp) -> LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneOffset.UTC).format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM));
|
||||
int currentBlockHeight = repository.getBlockRepository().getBlockchainHeight();
|
||||
@@ -733,7 +733,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
+ "\tcurrent balance: %s QORT,\n"
|
||||
+ "\tis finished: %b,\n"
|
||||
+ "\tredeem payout: %s QORT,\n"
|
||||
+ "\texpected ravencoin: %s RVN,\n"
|
||||
+ "\texpected digibyte: %s DGB,\n"
|
||||
+ "\tcurrent block height: %d,\n",
|
||||
tradeData.qortalAtAddress,
|
||||
tradeData.mode,
|
||||
@@ -749,7 +749,7 @@ public class RavencoinACCTv3Tests extends Common {
|
||||
System.out.println(String.format("\trefund timeout: %d minutes,\n"
|
||||
+ "\trefund height: block %d,\n"
|
||||
+ "\tHASH160 of secret-A: %s,\n"
|
||||
+ "\tRavencoin P2SH-A nLockTime: %d (%s),\n"
|
||||
+ "\tDigibyte P2SH-A nLockTime: %d (%s),\n"
|
||||
+ "\ttrade partner: %s\n"
|
||||
+ "\tpartner's receiving address: %s",
|
||||
tradeData.refundTimeout,
|
Reference in New Issue
Block a user