mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-22 20:26:50 +00:00
Removed code for providing compatibility with Qora v1
Qortal is never going to continue off the old Qora blockchain, so removed all code regarding compatibility. Removals include: * various blockchain "feature triggers" * special Qora-only broken code for various transaction signatures * "old" asset pricing / trading * pre-group txGroupId field in transactions * compatibility unit tests Possibly safe for roll-out on pre-genesis blockchain?
This commit is contained in:
@@ -11,7 +11,6 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.account.PublicKeyAccount;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.asset.AssetData;
|
||||
import org.qortal.data.asset.OrderData;
|
||||
import org.qortal.data.asset.TradeData;
|
||||
@@ -29,7 +28,6 @@ public class Order {
|
||||
private OrderData orderData;
|
||||
|
||||
// Used quite a bit
|
||||
private final boolean isOurOrderNewPricing;
|
||||
private final long haveAssetId;
|
||||
private final long wantAssetId;
|
||||
|
||||
@@ -47,7 +45,6 @@ public class Order {
|
||||
this.repository = repository;
|
||||
this.orderData = orderData;
|
||||
|
||||
this.isOurOrderNewPricing = this.orderData.getTimestamp() >= BlockChain.getInstance().getNewAssetPricingTimestamp();
|
||||
this.haveAssetId = this.orderData.getHaveAssetId();
|
||||
this.wantAssetId = this.orderData.getWantAssetId();
|
||||
}
|
||||
@@ -130,7 +127,7 @@ public class Order {
|
||||
|
||||
/** Calculate price pair. (e.g. QORT/GOLD)
|
||||
* <p>
|
||||
* Under 'new' pricing scheme, lowest-assetID asset is first,
|
||||
* Lowest-assetID asset is first,
|
||||
* so if QORT has assetID 0 and GOLD has assetID 10, then
|
||||
* the pricing pair is QORT/GOLD.
|
||||
* <p>
|
||||
@@ -141,7 +138,7 @@ public class Order {
|
||||
AssetData haveAssetData = getHaveAsset();
|
||||
AssetData wantAssetData = getWantAsset();
|
||||
|
||||
if (isOurOrderNewPricing && haveAssetId > wantAssetId)
|
||||
if (haveAssetId > wantAssetId)
|
||||
cachedPricePair = wantAssetData.getName() + "/" + haveAssetData.getName();
|
||||
else
|
||||
cachedPricePair = haveAssetData.getName() + "/" + wantAssetData.getName();
|
||||
@@ -151,8 +148,8 @@ public class Order {
|
||||
private BigDecimal calcHaveAssetCommittment() {
|
||||
BigDecimal committedCost = this.orderData.getAmount();
|
||||
|
||||
// If 'new' pricing and "amount" is in want-asset then we need to convert
|
||||
if (isOurOrderNewPricing && haveAssetId < wantAssetId)
|
||||
// If "amount" is in want-asset then we need to convert
|
||||
if (haveAssetId < wantAssetId)
|
||||
committedCost = committedCost.multiply(this.orderData.getPrice()).setScale(8, RoundingMode.HALF_UP);
|
||||
|
||||
return committedCost;
|
||||
@@ -162,8 +159,8 @@ public class Order {
|
||||
private BigDecimal calcHaveAssetRefund() {
|
||||
BigDecimal refund = getAmountLeft();
|
||||
|
||||
// If 'new' pricing and "amount" is in want-asset then we need to convert
|
||||
if (isOurOrderNewPricing && haveAssetId < wantAssetId)
|
||||
// If "amount" is in want-asset then we need to convert
|
||||
if (haveAssetId < wantAssetId)
|
||||
refund = refund.multiply(this.orderData.getPrice()).setScale(8, RoundingMode.HALF_UP);
|
||||
|
||||
return refund;
|
||||
@@ -192,27 +189,19 @@ public class Order {
|
||||
/**
|
||||
* Returns AssetData for asset in effect for "amount" field.
|
||||
* <p>
|
||||
* For 'old' pricing, this is the have-asset.<br>
|
||||
* For 'new' pricing, this is the asset with highest assetID.
|
||||
* This is the asset with highest assetID.
|
||||
*/
|
||||
public AssetData getAmountAsset() throws DataException {
|
||||
if (isOurOrderNewPricing && wantAssetId > haveAssetId)
|
||||
return getWantAsset();
|
||||
else
|
||||
return getHaveAsset();
|
||||
return (wantAssetId > haveAssetId) ? getWantAsset() : getHaveAsset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns AssetData for other (return) asset traded.
|
||||
* <p>
|
||||
* For 'old' pricing, this is the want-asset.<br>
|
||||
* For 'new' pricing, this is the asset with lowest assetID.
|
||||
* This is the asset with lowest assetID.
|
||||
*/
|
||||
public AssetData getReturnAsset() throws DataException {
|
||||
if (isOurOrderNewPricing && haveAssetId < wantAssetId)
|
||||
return getHaveAsset();
|
||||
else
|
||||
return getWantAsset();
|
||||
return (haveAssetId < wantAssetId) ? getHaveAsset() : getWantAsset();
|
||||
}
|
||||
|
||||
// Processing
|
||||
@@ -227,8 +216,6 @@ public class Order {
|
||||
|
||||
// NOTE: the following values are specific to passed orderData, not the same as class instance values!
|
||||
|
||||
final boolean isOrderNewAssetPricing = orderData.getTimestamp() >= BlockChain.getInstance().getNewAssetPricingTimestamp();
|
||||
|
||||
// Cached for readability
|
||||
final long _haveAssetId = orderData.getHaveAssetId();
|
||||
final long _wantAssetId = orderData.getWantAssetId();
|
||||
@@ -236,15 +223,15 @@ public class Order {
|
||||
final AssetData haveAssetData = this.repository.getAssetRepository().fromAssetId(_haveAssetId);
|
||||
final AssetData wantAssetData = this.repository.getAssetRepository().fromAssetId(_wantAssetId);
|
||||
|
||||
final long amountAssetId = (isOurOrderNewPricing && _wantAssetId > _haveAssetId) ? _wantAssetId : _haveAssetId;
|
||||
final long returnAssetId = (isOurOrderNewPricing && _haveAssetId < _wantAssetId) ? _haveAssetId : _wantAssetId;
|
||||
final long amountAssetId = (_wantAssetId > _haveAssetId) ? _wantAssetId : _haveAssetId;
|
||||
final long returnAssetId = (_haveAssetId < _wantAssetId) ? _haveAssetId : _wantAssetId;
|
||||
|
||||
final AssetData amountAssetData = this.repository.getAssetRepository().fromAssetId(amountAssetId);
|
||||
final AssetData returnAssetData = this.repository.getAssetRepository().fromAssetId(returnAssetId);
|
||||
|
||||
LOGGER.debug(String.format("%s %s", orderPrefix, Base58.encode(orderData.getOrderId())));
|
||||
|
||||
LOGGER.trace(String.format("%s have %s, want %s. '%s' pricing scheme.", weThey, haveAssetData.getName(), wantAssetData.getName(), isOrderNewAssetPricing ? "new" : "old"));
|
||||
LOGGER.trace(String.format("%s have %s, want %s.", weThey, haveAssetData.getName(), wantAssetData.getName()));
|
||||
|
||||
LOGGER.trace(String.format("%s amount: %s (ordered) - %s (fulfilled) = %s %s left", ourTheir,
|
||||
orderData.getAmount().stripTrailingZeros().toPlainString(),
|
||||
@@ -266,9 +253,9 @@ public class Order {
|
||||
AssetData wantAssetData = getWantAsset();
|
||||
|
||||
/** The asset while working out amount that matches. */
|
||||
AssetData matchingAssetData = isOurOrderNewPricing ? getAmountAsset() : wantAssetData;
|
||||
AssetData matchingAssetData = getAmountAsset();
|
||||
/** The return asset traded if trade completes. */
|
||||
AssetData returnAssetData = isOurOrderNewPricing ? getReturnAsset() : haveAssetData;
|
||||
AssetData returnAssetData = getReturnAsset();
|
||||
|
||||
// Subtract have-asset from creator
|
||||
Account creator = new PublicKeyAccount(this.repository, this.orderData.getCreatorPublicKey());
|
||||
@@ -281,7 +268,7 @@ public class Order {
|
||||
|
||||
// Fetch corresponding open orders that might potentially match, hence reversed want/have assetIDs.
|
||||
// Returned orders are sorted with lowest "price" first.
|
||||
List<OrderData> orders = assetRepository.getOpenOrdersForTrading(wantAssetId, haveAssetId, isOurOrderNewPricing ? this.orderData.getPrice() : null);
|
||||
List<OrderData> orders = assetRepository.getOpenOrdersForTrading(wantAssetId, haveAssetId, this.orderData.getPrice());
|
||||
LOGGER.trace("Open orders fetched from repository: " + orders.size());
|
||||
|
||||
if (orders.isEmpty())
|
||||
@@ -290,27 +277,7 @@ public class Order {
|
||||
// Attempt to match orders
|
||||
|
||||
/*
|
||||
* Potential matching order example ("old"):
|
||||
*
|
||||
* Our order:
|
||||
* haveAssetId=[GOLD], wantAssetId=0 (QORT), amount=40 (GOLD), price=486 (QORT/GOLD)
|
||||
* This translates to "we have 40 GOLD and want QORT at a price of 486 QORT per GOLD"
|
||||
* If our order matched, we'd end up with 40 * 486 = 19,440 QORT.
|
||||
*
|
||||
* Their order:
|
||||
* haveAssetId=0 (QORT), wantAssetId=[GOLD], amount=20,000 (QORT), price=0.00205761 (GOLD/QORT)
|
||||
* This translates to "they have 20,000 QORT and want GOLD at a price of 0.00205761 GOLD per QORT"
|
||||
*
|
||||
* Their price, converted into 'our' units of QORT/GOLD, is: 1 / 0.00205761 = 486.00074844 QORT/GOLD.
|
||||
* This is better than our requested 486 QORT/GOLD so this order matches.
|
||||
*
|
||||
* Using their price, we end up with 40 * 486.00074844 = 19440.02993760 QORT. They end up with 40 GOLD.
|
||||
*
|
||||
* If their order had 19,440 QORT left, only 19,440 * 0.00205761 = 39.99993840 GOLD would be traded.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Potential matching order example ("new"):
|
||||
* Potential matching order example:
|
||||
*
|
||||
* Our order:
|
||||
* haveAssetId=[GOLD], wantAssetId=0 (QORT), amount=40 (GOLD), price=486 (QORT/GOLD)
|
||||
@@ -333,44 +300,21 @@ public class Order {
|
||||
for (OrderData theirOrderData : orders) {
|
||||
logOrder("Considering order", false, theirOrderData);
|
||||
|
||||
// Not used:
|
||||
// boolean isTheirOrderNewAssetPricing = theirOrderData.getTimestamp() >= BlockChain.getInstance().getNewAssetPricingTimestamp();
|
||||
|
||||
// Determine their order price
|
||||
BigDecimal theirPrice;
|
||||
|
||||
if (isOurOrderNewPricing) {
|
||||
// Pricing units are the same way round for both orders, so no conversion needed.
|
||||
// Orders under 'old' pricing have been converted during repository update.
|
||||
theirPrice = theirOrderData.getPrice();
|
||||
LOGGER.trace(String.format("Their price: %s %s", theirPrice.toPlainString(), getPricePair()));
|
||||
} else {
|
||||
// If our order is 'old' pricing then all other existing orders must be 'old' pricing too
|
||||
// Their order pricing will be inverted, so convert
|
||||
theirPrice = BigDecimal.ONE.setScale(8).divide(theirOrderData.getPrice(), RoundingMode.DOWN);
|
||||
LOGGER.trace(String.format("Their price: %s %s per %s", theirPrice.toPlainString(), wantAssetData.getName(), haveAssetData.getName()));
|
||||
}
|
||||
// Pricing units are the same way round for both orders, so no conversion needed.
|
||||
theirPrice = theirOrderData.getPrice();
|
||||
LOGGER.trace(String.format("Their price: %s %s", theirPrice.toPlainString(), getPricePair()));
|
||||
|
||||
// If their price is worse than what we're willing to accept then we're done as prices only get worse as we iterate through list of orders
|
||||
if (isOurOrderNewPricing) {
|
||||
if (haveAssetId < wantAssetId && theirPrice.compareTo(ourPrice) > 0)
|
||||
break;
|
||||
if (haveAssetId > wantAssetId && theirPrice.compareTo(ourPrice) < 0)
|
||||
break;
|
||||
} else {
|
||||
// 'old' pricing scheme
|
||||
if (theirPrice.compareTo(ourPrice) < 0)
|
||||
break;
|
||||
}
|
||||
if (haveAssetId < wantAssetId && theirPrice.compareTo(ourPrice) > 0)
|
||||
break;
|
||||
if (haveAssetId > wantAssetId && theirPrice.compareTo(ourPrice) < 0)
|
||||
break;
|
||||
|
||||
// Calculate how much we could buy at their price.
|
||||
BigDecimal ourMaxAmount;
|
||||
if (isOurOrderNewPricing)
|
||||
// In 'new' pricing scheme, "amount" is expressed in terms of asset with highest assetID
|
||||
ourMaxAmount = this.getAmountLeft();
|
||||
else
|
||||
// In 'old' pricing scheme, "amount" is expressed in terms of our want-asset.
|
||||
ourMaxAmount = this.getAmountLeft().multiply(theirPrice).setScale(8, RoundingMode.DOWN);
|
||||
// Calculate how much we could buy at their price, "amount" is expressed in terms of asset with highest assetID.
|
||||
BigDecimal ourMaxAmount = this.getAmountLeft();
|
||||
LOGGER.trace("ourMaxAmount (max we could trade at their price): " + ourMaxAmount.stripTrailingZeros().toPlainString() + " " + matchingAssetData.getName());
|
||||
|
||||
// How much is remaining available in their order.
|
||||
@@ -421,11 +365,11 @@ public class Order {
|
||||
throw new DataException(message);
|
||||
}
|
||||
|
||||
BigDecimal tradedWantAmount = (isOurOrderNewPricing && haveAssetId > wantAssetId) ? returnAmountTraded : matchedAmount;
|
||||
BigDecimal tradedHaveAmount = (isOurOrderNewPricing && haveAssetId > wantAssetId) ? matchedAmount : returnAmountTraded;
|
||||
BigDecimal tradedWantAmount = (haveAssetId > wantAssetId) ? returnAmountTraded : matchedAmount;
|
||||
BigDecimal tradedHaveAmount = (haveAssetId > wantAssetId) ? matchedAmount : returnAmountTraded;
|
||||
|
||||
// We also need to know how much have-asset to refund based on price improvement ('new' pricing only and only one direction applies)
|
||||
BigDecimal haveAssetRefund = isOurOrderNewPricing && haveAssetId < wantAssetId ? ourPrice.subtract(theirPrice).abs().multiply(matchedAmount).setScale(8, RoundingMode.DOWN) : BigDecimal.ZERO;
|
||||
// We also need to know how much have-asset to refund based on price improvement (only one direction applies)
|
||||
BigDecimal haveAssetRefund = haveAssetId < wantAssetId ? ourPrice.subtract(theirPrice).abs().multiply(matchedAmount).setScale(8, RoundingMode.DOWN) : BigDecimal.ZERO;
|
||||
|
||||
LOGGER.trace(String.format("We traded %s %s (have-asset) for %s %s (want-asset), saving %s %s (have-asset)",
|
||||
tradedHaveAmount.toPlainString(), haveAssetData.getName(),
|
||||
@@ -440,7 +384,7 @@ public class Order {
|
||||
trade.process();
|
||||
|
||||
// Update our order in terms of fulfilment, etc. but do not save into repository as that's handled by Trade above
|
||||
BigDecimal amountFulfilled = isOurOrderNewPricing ? matchedAmount : returnAmountTraded;
|
||||
BigDecimal amountFulfilled = matchedAmount;
|
||||
this.orderData.setFulfilled(this.orderData.getFulfilled().add(amountFulfilled));
|
||||
LOGGER.trace("Updated our order's fulfilled amount to: " + this.orderData.getFulfilled().stripTrailingZeros().toPlainString() + " " + matchingAssetData.getName());
|
||||
LOGGER.trace("Our order's amount remaining: " + this.getAmountLeft().stripTrailingZeros().toPlainString() + " " + matchingAssetData.getName());
|
||||
|
@@ -4,7 +4,6 @@ import java.math.BigDecimal;
|
||||
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.account.PublicKeyAccount;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.asset.OrderData;
|
||||
import org.qortal.data.asset.TradeData;
|
||||
import org.qortal.repository.AssetRepository;
|
||||
@@ -17,12 +16,11 @@ public class Trade {
|
||||
private Repository repository;
|
||||
private TradeData tradeData;
|
||||
|
||||
private boolean isNewPricing;
|
||||
private AssetRepository assetRepository;
|
||||
|
||||
private OrderData initiatingOrder;
|
||||
private OrderData targetOrder;
|
||||
private BigDecimal newPricingFulfilled;
|
||||
private BigDecimal fulfilled;
|
||||
|
||||
// Constructors
|
||||
|
||||
@@ -30,7 +28,6 @@ public class Trade {
|
||||
this.repository = repository;
|
||||
this.tradeData = tradeData;
|
||||
|
||||
this.isNewPricing = this.tradeData.getTimestamp() > BlockChain.getInstance().getNewAssetPricingTimestamp();
|
||||
this.assetRepository = this.repository.getAssetRepository();
|
||||
}
|
||||
|
||||
@@ -43,9 +40,9 @@ public class Trade {
|
||||
// Note: targetAmount is amount traded FROM target order
|
||||
// Note: initiatorAmount is amount traded FROM initiating order
|
||||
|
||||
// Under 'new' pricing scheme, "amount" and "fulfilled" are the same asset for both orders
|
||||
// "amount" and "fulfilled" are the same asset for both orders
|
||||
// which is the matchedAmount in asset with highest assetID
|
||||
this.newPricingFulfilled = (initiatingOrder.getHaveAssetId() < initiatingOrder.getWantAssetId()) ? this.tradeData.getTargetAmount() : this.tradeData.getInitiatorAmount();
|
||||
this.fulfilled = (initiatingOrder.getHaveAssetId() < initiatingOrder.getWantAssetId()) ? this.tradeData.getTargetAmount() : this.tradeData.getInitiatorAmount();
|
||||
}
|
||||
|
||||
public void process() throws DataException {
|
||||
@@ -55,16 +52,16 @@ public class Trade {
|
||||
// Note: targetAmount is amount traded FROM target order
|
||||
// Note: initiatorAmount is amount traded FROM initiating order
|
||||
|
||||
// Update corresponding Orders on both sides of trade
|
||||
commonPrep();
|
||||
|
||||
initiatingOrder.setFulfilled(initiatingOrder.getFulfilled().add(isNewPricing ? newPricingFulfilled : tradeData.getInitiatorAmount()));
|
||||
// Update corresponding Orders on both sides of trade
|
||||
initiatingOrder.setFulfilled(initiatingOrder.getFulfilled().add(fulfilled));
|
||||
initiatingOrder.setIsFulfilled(Order.isFulfilled(initiatingOrder));
|
||||
// Set isClosed to true if isFulfilled now true
|
||||
initiatingOrder.setIsClosed(initiatingOrder.getIsFulfilled());
|
||||
assetRepository.save(initiatingOrder);
|
||||
|
||||
targetOrder.setFulfilled(targetOrder.getFulfilled().add(isNewPricing ? newPricingFulfilled : tradeData.getTargetAmount()));
|
||||
targetOrder.setFulfilled(targetOrder.getFulfilled().add(fulfilled));
|
||||
targetOrder.setIsFulfilled(Order.isFulfilled(targetOrder));
|
||||
// Set isClosed to true if isFulfilled now true
|
||||
targetOrder.setIsClosed(targetOrder.getIsFulfilled());
|
||||
@@ -89,16 +86,16 @@ public class Trade {
|
||||
// Note: targetAmount is amount traded FROM target order
|
||||
// Note: initiatorAmount is amount traded FROM initiating order
|
||||
|
||||
// Revert corresponding Orders on both sides of trade
|
||||
commonPrep();
|
||||
|
||||
initiatingOrder.setFulfilled(initiatingOrder.getFulfilled().subtract(isNewPricing ? newPricingFulfilled : tradeData.getInitiatorAmount()));
|
||||
// Revert corresponding Orders on both sides of trade
|
||||
initiatingOrder.setFulfilled(initiatingOrder.getFulfilled().subtract(fulfilled));
|
||||
initiatingOrder.setIsFulfilled(Order.isFulfilled(initiatingOrder));
|
||||
// Set isClosed to false if isFulfilled now false
|
||||
initiatingOrder.setIsClosed(initiatingOrder.getIsFulfilled());
|
||||
assetRepository.save(initiatingOrder);
|
||||
|
||||
targetOrder.setFulfilled(targetOrder.getFulfilled().subtract(isNewPricing ? newPricingFulfilled : tradeData.getTargetAmount()));
|
||||
targetOrder.setFulfilled(targetOrder.getFulfilled().subtract(fulfilled));
|
||||
targetOrder.setIsFulfilled(Order.isFulfilled(targetOrder));
|
||||
// Set isClosed to false if isFulfilled now false
|
||||
targetOrder.setIsClosed(targetOrder.getIsFulfilled());
|
||||
|
@@ -1,11 +1,9 @@
|
||||
package org.qortal.at;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import org.ciyam.at.MachineState;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.data.at.ATData;
|
||||
import org.qortal.data.at.ATStateData;
|
||||
@@ -42,66 +40,18 @@ public class AT {
|
||||
int height = this.repository.getBlockRepository().getBlockchainHeight() + 1;
|
||||
byte[] creatorPublicKey = deployATTransactionData.getCreatorPublicKey();
|
||||
long creation = deployATTransactionData.getTimestamp();
|
||||
|
||||
byte[] creationBytes = deployATTransactionData.getCreationBytes();
|
||||
long assetId = deployATTransactionData.getAssetId();
|
||||
short version = (short) ((creationBytes[0] & 0xff) | (creationBytes[1] << 8)); // Little-endian
|
||||
|
||||
if (version >= 2) {
|
||||
MachineState machineState = new MachineState(deployATTransactionData.getCreationBytes());
|
||||
MachineState machineState = new MachineState(deployATTransactionData.getCreationBytes());
|
||||
|
||||
this.atData = new ATData(atAddress, creatorPublicKey, creation, machineState.version, assetId, machineState.getCodeBytes(),
|
||||
machineState.getIsSleeping(), machineState.getSleepUntilHeight(), machineState.getIsFinished(), machineState.getHadFatalError(),
|
||||
machineState.getIsFrozen(), machineState.getFrozenBalance());
|
||||
this.atData = new ATData(atAddress, creatorPublicKey, creation, machineState.version, assetId, machineState.getCodeBytes(),
|
||||
machineState.getIsSleeping(), machineState.getSleepUntilHeight(), machineState.getIsFinished(), machineState.getHadFatalError(),
|
||||
machineState.getIsFrozen(), machineState.getFrozenBalance());
|
||||
|
||||
byte[] stateData = machineState.toBytes();
|
||||
byte[] stateHash = Crypto.digest(stateData);
|
||||
byte[] stateData = machineState.toBytes();
|
||||
byte[] stateHash = Crypto.digest(stateData);
|
||||
|
||||
this.atStateData = new ATStateData(atAddress, height, creation, stateData, stateHash, BigDecimal.ZERO.setScale(8));
|
||||
} else {
|
||||
// Legacy v1 AT
|
||||
// We would deploy these in 'dead' state as they will never be run on Qortal
|
||||
// but this breaks import from Qora1 so something else will have to mark them dead at hard-fork
|
||||
|
||||
// Extract code bytes length
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(deployATTransactionData.getCreationBytes());
|
||||
|
||||
// v1 AT header is: version, reserved, code-pages, data-pages, call-stack-pages, user-stack-pages (all shorts)
|
||||
|
||||
// Number of code pages
|
||||
short numCodePages = byteBuffer.get(2 + 2);
|
||||
|
||||
// Skip header and also "minimum activation amount" (long)
|
||||
byteBuffer.position(6 * 2 + 8);
|
||||
|
||||
int codeLen = 0;
|
||||
|
||||
// Extract actual code length, stored in minimal-size form (byte, short or int)
|
||||
if (numCodePages * 256 < 257) {
|
||||
codeLen = byteBuffer.get() & 0xff;
|
||||
} else if (numCodePages * 256 < Short.MAX_VALUE + 1) {
|
||||
codeLen = byteBuffer.getShort() & 0xffff;
|
||||
} else if (numCodePages * 256 <= Integer.MAX_VALUE) {
|
||||
codeLen = byteBuffer.getInt();
|
||||
}
|
||||
|
||||
// Extract code bytes
|
||||
byte[] codeBytes = new byte[codeLen];
|
||||
byteBuffer.get(codeBytes);
|
||||
|
||||
// Create AT
|
||||
boolean isSleeping = false;
|
||||
Integer sleepUntilHeight = null;
|
||||
boolean isFinished = false;
|
||||
boolean hadFatalError = false;
|
||||
boolean isFrozen = false;
|
||||
Long frozenBalance = null;
|
||||
|
||||
this.atData = new ATData(atAddress, creatorPublicKey, creation, version, Asset.QORT, codeBytes, isSleeping, sleepUntilHeight, isFinished,
|
||||
hadFatalError, isFrozen, frozenBalance);
|
||||
|
||||
this.atStateData = new ATStateData(atAddress, height, creation, null, null, BigDecimal.ZERO.setScale(8));
|
||||
}
|
||||
this.atStateData = new ATStateData(atAddress, height, creation, stateData, stateHash, BigDecimal.ZERO.setScale(8));
|
||||
}
|
||||
|
||||
// Getters / setters
|
||||
@@ -116,9 +66,7 @@ public class AT {
|
||||
ATRepository atRepository = this.repository.getATRepository();
|
||||
atRepository.save(this.atData);
|
||||
|
||||
// For version 2+ we also store initial AT state data
|
||||
if (this.atData.getVersion() >= 2)
|
||||
atRepository.save(this.atStateData);
|
||||
atRepository.save(this.atStateData);
|
||||
}
|
||||
|
||||
public void undeploy() throws DataException {
|
||||
|
@@ -473,6 +473,9 @@ public class Block {
|
||||
|
||||
/**
|
||||
* Return the next block's version.
|
||||
* <p>
|
||||
* We're starting with version 4 as a nod to being newer than successor Qora,
|
||||
* whose latest block version was 3.
|
||||
*
|
||||
* @return 1, 2, 3 or 4
|
||||
*/
|
||||
@@ -480,14 +483,7 @@ public class Block {
|
||||
if (this.blockData.getHeight() == null)
|
||||
throw new IllegalStateException("Can't determine next block's version as this block has no height set");
|
||||
|
||||
if (this.blockData.getHeight() < BlockChain.getInstance().getATReleaseHeight())
|
||||
return 1;
|
||||
else if (this.blockData.getTimestamp() < BlockChain.getInstance().getPowFixReleaseTimestamp())
|
||||
return 2;
|
||||
else if (this.blockData.getTimestamp() < BlockChain.getInstance().getQortalTimestamp())
|
||||
return 3;
|
||||
else
|
||||
return 4;
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -71,15 +71,6 @@ public class BlockChain {
|
||||
private GenesisBlock.GenesisInfo genesisInfo;
|
||||
|
||||
public enum FeatureTrigger {
|
||||
messageHeight, // block height when MESSAGE transactions are enabled
|
||||
atHeight, // block height when CIYAM automated transactions are enabled
|
||||
assetsTimestamp, // timestamp when assets (issue/transfer/payments) are enabled
|
||||
votingTimestamp, // timestamp when voting is enabled
|
||||
arbitraryTimestamp, // timestamp when arbitrary transactions are enabled
|
||||
powfixTimestamp, // timestamp when various legacy fixes come into effect
|
||||
qortalTimestamp, // timestamp when Qortal changes come into effect
|
||||
newAssetPricingTimestamp, // timestamp when new asset pricing comes into effect
|
||||
groupApprovalTimestamp; // timestamp when transaction approval comes into effect
|
||||
}
|
||||
|
||||
/** Map of which blockchain features are enabled when (height/timestamp) */
|
||||
@@ -357,42 +348,6 @@ public class BlockChain {
|
||||
|
||||
// Convenience methods for specific blockchain feature triggers
|
||||
|
||||
public long getMessageReleaseHeight() {
|
||||
return featureTriggers.get("messageHeight");
|
||||
}
|
||||
|
||||
public long getATReleaseHeight() {
|
||||
return featureTriggers.get("atHeight");
|
||||
}
|
||||
|
||||
public long getPowFixReleaseTimestamp() {
|
||||
return featureTriggers.get("powfixTimestamp");
|
||||
}
|
||||
|
||||
public long getAssetsReleaseTimestamp() {
|
||||
return featureTriggers.get("assetsTimestamp");
|
||||
}
|
||||
|
||||
public long getVotingReleaseTimestamp() {
|
||||
return featureTriggers.get("votingTimestamp");
|
||||
}
|
||||
|
||||
public long getArbitraryReleaseTimestamp() {
|
||||
return featureTriggers.get("arbitraryTimestamp");
|
||||
}
|
||||
|
||||
public long getQortalTimestamp() {
|
||||
return featureTriggers.get("qortalTimestamp");
|
||||
}
|
||||
|
||||
public long getNewAssetPricingTimestamp() {
|
||||
return featureTriggers.get("newAssetPricingTimestamp");
|
||||
}
|
||||
|
||||
public long getGroupApprovalTimestamp() {
|
||||
return featureTriggers.get("groupApprovalTimestamp");
|
||||
}
|
||||
|
||||
// More complex getters for aspects that change by height or timestamp
|
||||
|
||||
public BigDecimal getRewardAtHeight(int ourHeight) {
|
||||
|
@@ -7,7 +7,6 @@ import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.transaction.Transaction.TransactionType;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@@ -54,25 +53,16 @@ public class CreateAssetOrderTransactionData extends TransactionData {
|
||||
|
||||
// Called before converting to JSON for API
|
||||
public void beforeMarshal(Marshaller m) {
|
||||
final boolean isNewPricing = this.timestamp > BlockChain.getInstance().getNewAssetPricingTimestamp();
|
||||
|
||||
this.amountAssetId = (isNewPricing && this.haveAssetId < this.wantAssetId) ? this.wantAssetId : this.haveAssetId;
|
||||
this.amountAssetId = Math.max(this.haveAssetId, this.wantAssetId);
|
||||
|
||||
// If we don't have the extra asset name fields then we can't fill in the others
|
||||
if (this.haveAssetName == null)
|
||||
return;
|
||||
|
||||
if (isNewPricing) {
|
||||
// 'new' pricing scheme
|
||||
if (this.haveAssetId < this.wantAssetId) {
|
||||
this.amountAssetName = this.wantAssetName;
|
||||
this.pricePair = this.haveAssetName + "/" + this.wantAssetName;
|
||||
} else {
|
||||
this.amountAssetName = this.haveAssetName;
|
||||
this.pricePair = this.wantAssetName + "/" + this.haveAssetName;
|
||||
}
|
||||
if (this.haveAssetId < this.wantAssetId) {
|
||||
this.amountAssetName = this.wantAssetName;
|
||||
this.pricePair = this.haveAssetName + "/" + this.wantAssetName;
|
||||
} else {
|
||||
// 'old' pricing scheme is simpler
|
||||
this.amountAssetName = this.haveAssetName;
|
||||
this.pricePair = this.wantAssetName + "/" + this.haveAssetName;
|
||||
}
|
||||
|
@@ -677,12 +677,12 @@ public class HSQLDBDatabaseUpdates {
|
||||
stmt.execute("SET TIME ZONE INTERVAL '0:00' HOUR TO MINUTE");
|
||||
// Normalize amount/fulfilled to asset with highest assetID, BEFORE price correction
|
||||
stmt.execute("UPDATE AssetOrders SET amount = amount * price, fulfilled = fulfilled * price "
|
||||
+ "WHERE ordered < timestamp(" + BlockChain.getInstance().getNewAssetPricingTimestamp() + ") "
|
||||
+ "WHERE ordered < timestamp(" + 0 /* was BlockChain.getInstance().getNewAssetPricingTimestamp() */ + ") "
|
||||
+ "AND have_asset_id < want_asset_id");
|
||||
// Normalize price into lowest-assetID/highest-assetID price-pair, e.g. QORT/asset100
|
||||
// Note: HSQLDB uses BigDecimal's dividend.divide(divisor, RoundingMode.DOWN) too
|
||||
stmt.execute("UPDATE AssetOrders SET price = CAST(1 AS QortalAmount) / price "
|
||||
+ "WHERE ordered < timestamp(" + BlockChain.getInstance().getNewAssetPricingTimestamp() + ") "
|
||||
+ "WHERE ordered < timestamp(" + 0 /* was BlockChain.getInstance().getNewAssetPricingTimestamp() */ + ") "
|
||||
+ "AND have_asset_id < want_asset_id");
|
||||
// Revert time zone change above
|
||||
stmt.execute("SET TIME ZONE LOCAL");
|
||||
|
@@ -7,7 +7,6 @@ import java.util.List;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.account.PublicKeyAccount;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.PaymentData;
|
||||
import org.qortal.data.transaction.ArbitraryTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -91,13 +90,6 @@ public class ArbitraryTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public ValidationResult isValid() throws DataException {
|
||||
// Are arbitrary transactions even allowed at this point?
|
||||
if (arbitraryTransactionData.getVersion() != Transaction.getVersionByTimestamp(arbitraryTransactionData.getTimestamp()))
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
if (this.arbitraryTransactionData.getTimestamp() < BlockChain.getInstance().getArbitraryReleaseTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check data length
|
||||
if (arbitraryTransactionData.getData().length < 1 || arbitraryTransactionData.getData().length > MAX_DATA_SIZE)
|
||||
return ValidationResult.INVALID_DATA_LENGTH;
|
||||
|
@@ -8,7 +8,6 @@ import org.qortal.account.Account;
|
||||
import org.qortal.account.PublicKeyAccount;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.asset.Order;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.asset.AssetData;
|
||||
import org.qortal.data.asset.OrderData;
|
||||
import org.qortal.data.transaction.CreateAssetOrderTransactionData;
|
||||
@@ -106,42 +105,27 @@ public class CreateAssetOrderTransaction extends Transaction {
|
||||
|
||||
Account creator = getCreator();
|
||||
|
||||
boolean isNewPricing = createOrderTransactionData.getTimestamp() >= BlockChain.getInstance().getNewAssetPricingTimestamp();
|
||||
|
||||
BigDecimal committedCost;
|
||||
BigDecimal maxOtherAmount;
|
||||
|
||||
if (isNewPricing) {
|
||||
/*
|
||||
* This is different under "new" pricing scheme as "amount" might be either have-asset or want-asset,
|
||||
* whichever has the highest assetID.
|
||||
*
|
||||
* e.g. with assetID 11 "GOLD":
|
||||
* haveAssetId: 0 (QORT), wantAssetId: 11 (GOLD), amount: 123 (GOLD), price: 400 (QORT/GOLD)
|
||||
* stake 49200 QORT, return 123 GOLD
|
||||
*
|
||||
* haveAssetId: 11 (GOLD), wantAssetId: 0 (QORT), amount: 123 (GOLD), price: 400 (QORT/GOLD)
|
||||
* stake 123 GOLD, return 49200 QORT
|
||||
*/
|
||||
boolean isAmountWantAsset = haveAssetId < wantAssetId;
|
||||
/*
|
||||
* "amount" might be either have-asset or want-asset, whichever has the highest assetID.
|
||||
*
|
||||
* e.g. with assetID 11 "GOLD":
|
||||
* haveAssetId: 0 (QORT), wantAssetId: 11 (GOLD), amount: 123 (GOLD), price: 400 (QORT/GOLD)
|
||||
* stake 49200 QORT, return 123 GOLD
|
||||
*
|
||||
* haveAssetId: 11 (GOLD), wantAssetId: 0 (QORT), amount: 123 (GOLD), price: 400 (QORT/GOLD)
|
||||
* stake 123 GOLD, return 49200 QORT
|
||||
*/
|
||||
boolean isAmountWantAsset = haveAssetId < wantAssetId;
|
||||
|
||||
if (isAmountWantAsset) {
|
||||
// have/commit 49200 QORT, want/return 123 GOLD
|
||||
committedCost = createOrderTransactionData.getAmount().multiply(createOrderTransactionData.getPrice());
|
||||
maxOtherAmount = createOrderTransactionData.getAmount();
|
||||
} else {
|
||||
// have/commit 123 GOLD, want/return 49200 QORT
|
||||
committedCost = createOrderTransactionData.getAmount();
|
||||
maxOtherAmount = createOrderTransactionData.getAmount().multiply(createOrderTransactionData.getPrice());
|
||||
}
|
||||
if (isAmountWantAsset) {
|
||||
// have/commit 49200 QORT, want/return 123 GOLD
|
||||
committedCost = createOrderTransactionData.getAmount().multiply(createOrderTransactionData.getPrice());
|
||||
maxOtherAmount = createOrderTransactionData.getAmount();
|
||||
} else {
|
||||
/*
|
||||
* Under "old" pricing scheme, "amount" is always have-asset and price is always want-per-have.
|
||||
*
|
||||
* e.g. with assetID 11 "GOLD":
|
||||
* haveAssetId: 0 (QORT), wantAssetId: 11 (GOLD), amount: 49200 (QORT), price: 0.00250000 (GOLD/QORT)
|
||||
* haveAssetId: 11 (GOLD), wantAssetId: 0 (QORT), amount: 123 (GOLD), price: 400 (QORT/GOLD)
|
||||
*/
|
||||
// have/commit 123 GOLD, want/return 49200 QORT
|
||||
committedCost = createOrderTransactionData.getAmount();
|
||||
maxOtherAmount = createOrderTransactionData.getAmount().multiply(createOrderTransactionData.getPrice());
|
||||
}
|
||||
@@ -166,9 +150,7 @@ public class CreateAssetOrderTransaction extends Transaction {
|
||||
return ValidationResult.NO_BALANCE;
|
||||
|
||||
// Check creator has enough funds for fee in QORT
|
||||
// NOTE: in Gen1 pre-POWFIX-RELEASE transactions didn't have this check
|
||||
if (createOrderTransactionData.getTimestamp() >= BlockChain.getInstance().getPowFixReleaseTimestamp()
|
||||
&& creator.getConfirmedBalance(Asset.QORT).compareTo(createOrderTransactionData.getFee()) < 0)
|
||||
if (creator.getConfirmedBalance(Asset.QORT).compareTo(createOrderTransactionData.getFee()) < 0)
|
||||
return ValidationResult.NO_BALANCE;
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,6 @@ import java.util.List;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.account.PublicKeyAccount;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.data.transaction.CreatePollTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -78,11 +77,6 @@ public class CreatePollTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public ValidationResult isValid() throws DataException {
|
||||
// Are CreatePollTransactions even allowed at this point?
|
||||
// In gen1 this used NTP.getTime() but surely the transaction's timestamp should be used
|
||||
if (this.createPollTransactionData.getTimestamp() < BlockChain.getInstance().getVotingReleaseTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check owner address is valid
|
||||
if (!Crypto.isValidAddress(createPollTransactionData.getOwner()))
|
||||
return ValidationResult.INVALID_ADDRESS;
|
||||
|
@@ -11,7 +11,6 @@ import org.ciyam.at.MachineState;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.at.AT;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.data.asset.AssetData;
|
||||
import org.qortal.data.transaction.DeployAtTransactionData;
|
||||
@@ -124,9 +123,6 @@ public class DeployAtTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public ValidationResult isValid() throws DataException {
|
||||
if (this.repository.getBlockRepository().getBlockchainHeight() < BlockChain.getInstance().getATReleaseHeight())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check name size bounds
|
||||
int nameLength = Utf8.encodedLength(deployATTransactionData.getName());
|
||||
if (nameLength < 1 || nameLength > MAX_NAME_SIZE)
|
||||
|
@@ -7,7 +7,6 @@ import java.util.List;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.account.PublicKeyAccount;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.data.transaction.IssueAssetTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -76,23 +75,11 @@ public class IssueAssetTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public ValidationResult isValid() throws DataException {
|
||||
// Are IssueAssetTransactions even allowed at this point?
|
||||
// In gen1 this used NTP.getTime() but surely the transaction's timestamp should be used
|
||||
if (this.issueAssetTransactionData.getTimestamp() < BlockChain.getInstance().getAssetsReleaseTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// "data" field is only allowed in v2
|
||||
// Check data field
|
||||
String data = this.issueAssetTransactionData.getData();
|
||||
if (this.issueAssetTransactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp()) {
|
||||
// v2 so check data field properly
|
||||
int dataLength = Utf8.encodedLength(data);
|
||||
if (data == null || dataLength < 1 || dataLength > Asset.MAX_DATA_SIZE)
|
||||
return ValidationResult.INVALID_DATA_LENGTH;
|
||||
} else {
|
||||
// pre-v2 so disallow data field
|
||||
if (data != null && !data.isEmpty())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
}
|
||||
int dataLength = Utf8.encodedLength(data);
|
||||
if (data == null || dataLength < 1 || dataLength > Asset.MAX_DATA_SIZE)
|
||||
return ValidationResult.INVALID_DATA_LENGTH;
|
||||
|
||||
// Check owner address is valid
|
||||
if (!Crypto.isValidAddress(issueAssetTransactionData.getOwner()))
|
||||
@@ -128,10 +115,9 @@ public class IssueAssetTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public ValidationResult isProcessable() throws DataException {
|
||||
// Check the asset name isn't already taken. This check is not present in gen1.
|
||||
if (issueAssetTransactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp())
|
||||
if (this.repository.getAssetRepository().assetExists(issueAssetTransactionData.getAssetName()))
|
||||
return ValidationResult.ASSET_ALREADY_EXISTS;
|
||||
// Check the asset name isn't already taken.
|
||||
if (this.repository.getAssetRepository().assetExists(issueAssetTransactionData.getAssetName()))
|
||||
return ValidationResult.ASSET_ALREADY_EXISTS;
|
||||
|
||||
return ValidationResult.OK;
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ import java.util.List;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.account.PublicKeyAccount;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.PaymentData;
|
||||
import org.qortal.data.transaction.MessageTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -89,13 +88,6 @@ public class MessageTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public ValidationResult isValid() throws DataException {
|
||||
// Are message transactions even allowed at this point?
|
||||
if (messageTransactionData.getVersion() != Transaction.getVersionByTimestamp(messageTransactionData.getTimestamp()))
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
if (this.repository.getBlockRepository().getBlockchainHeight() < BlockChain.getInstance().getMessageReleaseHeight())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check data length
|
||||
if (messageTransactionData.getData().length < 1 || messageTransactionData.getData().length > MAX_DATA_SIZE)
|
||||
return ValidationResult.INVALID_DATA_LENGTH;
|
||||
|
@@ -7,7 +7,6 @@ import java.util.List;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.account.PublicKeyAccount;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.PaymentData;
|
||||
import org.qortal.data.transaction.MultiPaymentTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -90,10 +89,6 @@ public class MultiPaymentTransaction extends Transaction {
|
||||
public ValidationResult isValid() throws DataException {
|
||||
List<PaymentData> payments = multiPaymentTransactionData.getPayments();
|
||||
|
||||
// Are MultiPaymentTransactions even allowed at this point?
|
||||
if (this.multiPaymentTransactionData.getTimestamp() < BlockChain.getInstance().getAssetsReleaseTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check number of payments
|
||||
if (payments.isEmpty() || payments.size() > MAX_PAYMENTS_COUNT)
|
||||
return ValidationResult.INVALID_PAYMENTS_COUNT;
|
||||
@@ -102,9 +97,7 @@ public class MultiPaymentTransaction extends Transaction {
|
||||
Account sender = getSender();
|
||||
|
||||
// Check sender has enough funds for fee
|
||||
// NOTE: in Gen1 pre-POWFIX-RELEASE transactions didn't have this check
|
||||
if (multiPaymentTransactionData.getTimestamp() >= BlockChain.getInstance().getPowFixReleaseTimestamp()
|
||||
&& sender.getConfirmedBalance(Asset.QORT).compareTo(multiPaymentTransactionData.getFee()) < 0)
|
||||
if (sender.getConfirmedBalance(Asset.QORT).compareTo(multiPaymentTransactionData.getFee()) < 0)
|
||||
return ValidationResult.NO_BALANCE;
|
||||
|
||||
return new Payment(this.repository).isValid(multiPaymentTransactionData.getSenderPublicKey(), payments, multiPaymentTransactionData.getFee());
|
||||
|
@@ -354,18 +354,15 @@ public abstract class Transaction {
|
||||
|
||||
/**
|
||||
* Return the transaction version number that should be used, based on passed timestamp.
|
||||
* <p>
|
||||
* We're starting with version 4 as a nod to being newer than successor Qora,
|
||||
* whose latest transaction version was 3.
|
||||
*
|
||||
* @param timestamp
|
||||
* @return transaction version number, likely 1 or 3
|
||||
* @return transaction version number
|
||||
*/
|
||||
public static int getVersionByTimestamp(long timestamp) {
|
||||
if (timestamp < BlockChain.getInstance().getPowFixReleaseTimestamp()) {
|
||||
return 1;
|
||||
} else if (timestamp < BlockChain.getInstance().getQortalTimestamp()) {
|
||||
return 3;
|
||||
} else {
|
||||
return 4;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -803,10 +800,6 @@ public abstract class Transaction {
|
||||
if (!this.transactionData.getType().needsApproval)
|
||||
return false;
|
||||
|
||||
// Is group-approval even in effect yet?
|
||||
if (this.transactionData.getTimestamp() < BlockChain.getInstance().getGroupApprovalTimestamp())
|
||||
return false;
|
||||
|
||||
int txGroupId = this.transactionData.getTxGroupId();
|
||||
|
||||
if (txGroupId == Group.NO_GROUP)
|
||||
|
@@ -7,7 +7,6 @@ import java.util.List;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.account.PublicKeyAccount;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.PaymentData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.data.transaction.TransferAssetTransactionData;
|
||||
@@ -83,11 +82,6 @@ public class TransferAssetTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public ValidationResult isValid() throws DataException {
|
||||
// Are TransferAssetTransactions even allowed at this point?
|
||||
// In gen1 this used NTP.getTime() but surely the transaction's timestamp should be used
|
||||
if (this.transferAssetTransactionData.getTimestamp() < BlockChain.getInstance().getAssetsReleaseTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Wrap asset transfer as a payment and delegate final payment checks to Payment class
|
||||
return new Payment(this.repository).isValid(transferAssetTransactionData.getSenderPublicKey(), getPaymentData(), transferAssetTransactionData.getFee());
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ import java.util.List;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.account.PublicKeyAccount;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.data.asset.AssetData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -75,10 +74,6 @@ public class UpdateAssetTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public ValidationResult isValid() throws DataException {
|
||||
// V2-only transaction
|
||||
if (this.updateAssetTransactionData.getTimestamp() < BlockChain.getInstance().getQortalTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check asset actually exists
|
||||
AssetData assetData = this.repository.getAssetRepository().fromAssetId(updateAssetTransactionData.getAssetId());
|
||||
if (assetData == null)
|
||||
|
@@ -9,7 +9,6 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.account.PublicKeyAccount;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.data.transaction.VoteOnPollTransactionData;
|
||||
import org.qortal.data.voting.PollData;
|
||||
@@ -69,11 +68,6 @@ public class VoteOnPollTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public ValidationResult isValid() throws DataException {
|
||||
// Are VoteOnPollTransactions even allowed at this point?
|
||||
// In gen1 this used NTP.getTime() but surely the transaction's timestamp should be used
|
||||
if (this.voteOnPollTransactionData.getTimestamp() < BlockChain.getInstance().getVotingReleaseTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check name size bounds
|
||||
int pollNameLength = Utf8.encodedLength(voteOnPollTransactionData.getPollName());
|
||||
if (pollNameLength < 1 || pollNameLength > Poll.MAX_NAME_SIZE)
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.AccountFlagsTransactionData;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -45,9 +44,7 @@ public class AccountFlagsTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.AccountLevelTransactionData;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -40,9 +39,7 @@ public class AccountLevelTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.AddGroupAdminTransactionData;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -41,9 +40,7 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,10 +5,8 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.data.PaymentData;
|
||||
import org.qortal.data.transaction.ArbitraryTransactionData;
|
||||
@@ -32,7 +30,7 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
|
||||
private static final int DATA_SIZE_LENGTH = INT_LENGTH;
|
||||
private static final int NUMBER_PAYMENTS_LENGTH = INT_LENGTH;
|
||||
|
||||
private static final int EXTRAS_LENGTH = SERVICE_LENGTH + DATA_SIZE_LENGTH;
|
||||
private static final int EXTRAS_LENGTH = SERVICE_LENGTH + DATA_TYPE_LENGTH + DATA_SIZE_LENGTH;
|
||||
|
||||
protected static final TransactionLayout layout;
|
||||
|
||||
@@ -43,14 +41,14 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
|
||||
layout.add("transaction's groupID", TransformationType.INT);
|
||||
layout.add("reference", TransformationType.SIGNATURE);
|
||||
layout.add("sender's public key", TransformationType.PUBLIC_KEY);
|
||||
layout.add("number of payments (v3+)", TransformationType.INT);
|
||||
layout.add("number of payments", TransformationType.INT);
|
||||
|
||||
layout.add("* recipient", TransformationType.ADDRESS);
|
||||
layout.add("* asset ID of payment", TransformationType.LONG);
|
||||
layout.add("* payment amount", TransformationType.AMOUNT);
|
||||
|
||||
layout.add("service ID", TransformationType.INT);
|
||||
layout.add("is data raw? (v4+)", TransformationType.BOOLEAN);
|
||||
layout.add("is data raw?", TransformationType.BOOLEAN);
|
||||
layout.add("data length", TransformationType.INT);
|
||||
layout.add("data", TransformationType.DATA);
|
||||
layout.add("fee", TransformationType.AMOUNT);
|
||||
@@ -62,9 +60,7 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
int version = Transaction.getVersionByTimestamp(timestamp);
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
@@ -82,14 +78,10 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
int service = byteBuffer.getInt();
|
||||
|
||||
// With V4+ we might be receiving hash of data instead of actual raw data
|
||||
DataType dataType = DataType.RAW_DATA;
|
||||
if (version >= 4) {
|
||||
boolean isRaw = byteBuffer.get() != 0;
|
||||
// We might be receiving hash of data instead of actual raw data
|
||||
boolean isRaw = byteBuffer.get() != 0;
|
||||
|
||||
if (!isRaw)
|
||||
dataType = DataType.DATA_HASH;
|
||||
}
|
||||
DataType dataType = isRaw ? DataType.RAW_DATA : DataType.DATA_HASH;
|
||||
|
||||
int dataSize = byteBuffer.getInt();
|
||||
// Don't allow invalid dataSize here to avoid run-time issues
|
||||
@@ -114,13 +106,8 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
int length = getBaseLength(transactionData) + EXTRAS_LENGTH + arbitraryTransactionData.getData().length;
|
||||
|
||||
// V4+ transactions have data type
|
||||
if (arbitraryTransactionData.getVersion() >= 4)
|
||||
length += DATA_TYPE_LENGTH;
|
||||
|
||||
// V3+ transactions have optional payments
|
||||
if (arbitraryTransactionData.getVersion() >= 3)
|
||||
length += NUMBER_PAYMENTS_LENGTH + arbitraryTransactionData.getPayments().size() * PaymentTransformer.getDataLength();
|
||||
// Optional payments
|
||||
length += NUMBER_PAYMENTS_LENGTH + arbitraryTransactionData.getPayments().size() * PaymentTransformer.getDataLength();
|
||||
|
||||
return length;
|
||||
}
|
||||
@@ -133,19 +120,15 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
transformCommonBytes(transactionData, bytes);
|
||||
|
||||
if (arbitraryTransactionData.getVersion() != 1) {
|
||||
List<PaymentData> payments = arbitraryTransactionData.getPayments();
|
||||
bytes.write(Ints.toByteArray(payments.size()));
|
||||
List<PaymentData> payments = arbitraryTransactionData.getPayments();
|
||||
bytes.write(Ints.toByteArray(payments.size()));
|
||||
|
||||
for (PaymentData paymentData : payments)
|
||||
bytes.write(PaymentTransformer.toBytes(paymentData));
|
||||
}
|
||||
for (PaymentData paymentData : payments)
|
||||
bytes.write(PaymentTransformer.toBytes(paymentData));
|
||||
|
||||
bytes.write(Ints.toByteArray(arbitraryTransactionData.getService()));
|
||||
|
||||
// V4+ also has data type
|
||||
if (arbitraryTransactionData.getVersion() >= 4)
|
||||
bytes.write((byte) (arbitraryTransactionData.getDataType() == DataType.RAW_DATA ? 1 : 0));
|
||||
bytes.write((byte) (arbitraryTransactionData.getDataType() == DataType.RAW_DATA ? 1 : 0));
|
||||
|
||||
bytes.write(Ints.toByteArray(arbitraryTransactionData.getData().length));
|
||||
bytes.write(arbitraryTransactionData.getData());
|
||||
@@ -162,38 +145,15 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
|
||||
}
|
||||
|
||||
/**
|
||||
* In Qora v1, the bytes used for verification are really mangled so we need to test for v1-ness and adjust the bytes accordingly.
|
||||
* Signature for ArbitraryTransactions always uses hash of data, not raw data itself.
|
||||
*
|
||||
* @param transactionData
|
||||
* @return byte[]
|
||||
* @throws TransformationException
|
||||
*/
|
||||
public static byte[] toBytesForSigningImpl(TransactionData transactionData) throws TransformationException {
|
||||
protected static byte[] toBytesForSigningImpl(TransactionData transactionData) throws TransformationException {
|
||||
ArbitraryTransactionData arbitraryTransactionData = (ArbitraryTransactionData) transactionData;
|
||||
|
||||
// For v4, signature uses hash of data, not raw data itself
|
||||
if (arbitraryTransactionData.getVersion() == 4)
|
||||
return toBytesForSigningImplV4(arbitraryTransactionData);
|
||||
|
||||
byte[] bytes = TransactionTransformer.toBytesForSigningImpl(transactionData);
|
||||
if (arbitraryTransactionData.getVersion() == 1 || transactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp())
|
||||
return bytes;
|
||||
|
||||
// Special v1 version
|
||||
|
||||
// In v1, a coding error means that all bytes prior to final payment entry are lost!
|
||||
// If there are no payments then we can skip mangling
|
||||
if (arbitraryTransactionData.getPayments().isEmpty())
|
||||
return bytes;
|
||||
|
||||
// So we're left with: final payment entry, service, data size, data, fee
|
||||
int v1Length = PaymentTransformer.getDataLength() + SERVICE_LENGTH + DATA_SIZE_LENGTH + arbitraryTransactionData.getData().length + FEE_LENGTH;
|
||||
int v1Start = bytes.length - v1Length;
|
||||
|
||||
return Arrays.copyOfRange(bytes, v1Start, bytes.length);
|
||||
}
|
||||
|
||||
private static byte[] toBytesForSigningImplV4(ArbitraryTransactionData arbitraryTransactionData) throws TransformationException {
|
||||
try {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
|
||||
@@ -210,6 +170,8 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
|
||||
bytes.write(Ints.toByteArray(arbitraryTransactionData.getService()));
|
||||
|
||||
bytes.write(Ints.toByteArray(arbitraryTransactionData.getData().length));
|
||||
|
||||
// Signature uses hash of data, not raw data itself
|
||||
switch (arbitraryTransactionData.getDataType()) {
|
||||
case DATA_HASH:
|
||||
bytes.write(arbitraryTransactionData.getData());
|
||||
@@ -228,7 +190,6 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
|
||||
} catch (IOException | ClassCastException e) {
|
||||
throw new TransformationException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.BuyNameTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -45,9 +44,7 @@ public class BuyNameTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.CancelAssetOrderTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -37,9 +36,7 @@ public class CancelAssetOrderTransactionTransformer extends TransactionTransform
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.CancelGroupBanTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -41,9 +40,7 @@ public class CancelGroupBanTransactionTransformer extends TransactionTransformer
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.CancelGroupInviteTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -41,9 +40,7 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.CancelSellNameTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -41,9 +40,7 @@ public class CancelSellNameTransactionTransformer extends TransactionTransformer
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.CreateAssetOrderTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -13,7 +12,6 @@ import org.qortal.transaction.Transaction.TransactionType;
|
||||
import org.qortal.transform.TransformationException;
|
||||
import org.qortal.utils.Serialization;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.google.common.primitives.Longs;
|
||||
|
||||
public class CreateAssetOrderTransactionTransformer extends TransactionTransformer {
|
||||
@@ -44,9 +42,7 @@ public class CreateAssetOrderTransactionTransformer extends TransactionTransform
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
@@ -102,41 +98,4 @@ public class CreateAssetOrderTransactionTransformer extends TransactionTransform
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In Qora v1, the bytes used for verification have mangled price so we need to test for v1-ness and adjust the bytes accordingly.
|
||||
*
|
||||
* @param transactionData
|
||||
* @return byte[]
|
||||
* @throws TransformationException
|
||||
*/
|
||||
public static byte[] toBytesForSigningImpl(TransactionData transactionData) throws TransformationException {
|
||||
if (transactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp())
|
||||
return TransactionTransformer.toBytesForSigningImpl(transactionData);
|
||||
|
||||
// Special v1 version
|
||||
try {
|
||||
CreateAssetOrderTransactionData createOrderTransactionData = (CreateAssetOrderTransactionData) transactionData;
|
||||
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
|
||||
bytes.write(Ints.toByteArray(createOrderTransactionData.getType().value));
|
||||
bytes.write(Longs.toByteArray(createOrderTransactionData.getTimestamp()));
|
||||
bytes.write(createOrderTransactionData.getReference());
|
||||
|
||||
bytes.write(createOrderTransactionData.getCreatorPublicKey());
|
||||
bytes.write(Longs.toByteArray(createOrderTransactionData.getHaveAssetId()));
|
||||
bytes.write(Longs.toByteArray(createOrderTransactionData.getWantAssetId()));
|
||||
Serialization.serializeBigDecimal(bytes, createOrderTransactionData.getAmount(), AMOUNT_LENGTH);
|
||||
|
||||
// This is the crucial difference
|
||||
Serialization.serializeBigDecimal(bytes, createOrderTransactionData.getPrice(), FEE_LENGTH);
|
||||
|
||||
Serialization.serializeBigDecimal(bytes, createOrderTransactionData.getFee());
|
||||
|
||||
return bytes.toByteArray();
|
||||
} catch (IOException | ClassCastException e) {
|
||||
throw new TransformationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.CreateGroupTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -56,9 +55,7 @@ public class CreateGroupTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -7,7 +7,6 @@ import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.CreatePollTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -54,9 +53,7 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
@@ -78,13 +75,6 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
|
||||
String optionName = Serialization.deserializeSizedString(byteBuffer, Poll.MAX_NAME_SIZE);
|
||||
|
||||
pollOptions.add(new PollOptionData(optionName));
|
||||
|
||||
// V1 only: voter count also present
|
||||
if (timestamp < BlockChain.getInstance().getQortalTimestamp()) {
|
||||
int voterCount = byteBuffer.getInt();
|
||||
if (voterCount != 0)
|
||||
throw new TransformationException("Unexpected voter count in byte data for CreatePollTransaction");
|
||||
}
|
||||
}
|
||||
|
||||
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
|
||||
@@ -104,15 +94,10 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
|
||||
+ Utf8.encodedLength(createPollTransactionData.getDescription());
|
||||
|
||||
// Add lengths for each poll options
|
||||
for (PollOptionData pollOptionData : createPollTransactionData.getPollOptions()) {
|
||||
for (PollOptionData pollOptionData : createPollTransactionData.getPollOptions())
|
||||
// option-string-length, option-string
|
||||
dataLength += INT_LENGTH + Utf8.encodedLength(pollOptionData.getOptionName());
|
||||
|
||||
if (transactionData.getTimestamp() < BlockChain.getInstance().getQortalTimestamp())
|
||||
// v1 only: voter-count (should always be zero)
|
||||
dataLength += INT_LENGTH;
|
||||
}
|
||||
|
||||
return dataLength;
|
||||
}
|
||||
|
||||
@@ -133,16 +118,9 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
|
||||
List<PollOptionData> pollOptions = createPollTransactionData.getPollOptions();
|
||||
bytes.write(Ints.toByteArray(pollOptions.size()));
|
||||
|
||||
for (PollOptionData pollOptionData : pollOptions) {
|
||||
for (PollOptionData pollOptionData : pollOptions)
|
||||
Serialization.serializeSizedString(bytes, pollOptionData.getOptionName());
|
||||
|
||||
if (transactionData.getTimestamp() < BlockChain.getInstance().getQortalTimestamp()) {
|
||||
// In v1, CreatePollTransaction uses Poll.toBytes which serializes voters too.
|
||||
// Zero voters as this is a new poll.
|
||||
bytes.write(Ints.toByteArray(0));
|
||||
}
|
||||
}
|
||||
|
||||
Serialization.serializeBigDecimal(bytes, createPollTransactionData.getFee());
|
||||
|
||||
if (createPollTransactionData.getSignature() != null)
|
||||
@@ -154,26 +132,4 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In Qora v1, the bytes used for verification have transaction type set to REGISTER_NAME_TRANSACTION so we need to test for v1-ness and adjust the bytes
|
||||
* accordingly.
|
||||
*
|
||||
* @param transactionData
|
||||
* @return byte[]
|
||||
* @throws TransformationException
|
||||
*/
|
||||
public static byte[] toBytesForSigningImpl(TransactionData transactionData) throws TransformationException {
|
||||
byte[] bytes = TransactionTransformer.toBytesForSigningImpl(transactionData);
|
||||
|
||||
if (transactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp())
|
||||
return bytes;
|
||||
|
||||
// Special v1 version
|
||||
|
||||
// Replace transaction type with incorrect Register Name value
|
||||
System.arraycopy(Ints.toByteArray(TransactionType.REGISTER_NAME.value), 0, bytes, 0, INT_LENGTH);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,13 +5,10 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.DeployAtTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.transaction.DeployAtTransaction;
|
||||
import org.qortal.transaction.Transaction;
|
||||
import org.qortal.transaction.Transaction.TransactionType;
|
||||
import org.qortal.transform.TransformationException;
|
||||
import org.qortal.utils.Serialization;
|
||||
@@ -32,7 +29,7 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
|
||||
private static final int ASSET_ID_LENGTH = LONG_LENGTH;
|
||||
|
||||
private static final int EXTRAS_LENGTH = NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + AT_TYPE_SIZE_LENGTH + TAGS_SIZE_LENGTH + CREATION_BYTES_SIZE_LENGTH
|
||||
+ AMOUNT_LENGTH;
|
||||
+ AMOUNT_LENGTH + ASSET_ID_LENGTH;
|
||||
|
||||
protected static final TransactionLayout layout;
|
||||
|
||||
@@ -60,11 +57,7 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int version = Transaction.getVersionByTimestamp(timestamp);
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
@@ -88,9 +81,7 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
BigDecimal amount = Serialization.deserializeBigDecimal(byteBuffer);
|
||||
|
||||
long assetId = Asset.QORT;
|
||||
if (version >= 4)
|
||||
assetId = byteBuffer.getLong();
|
||||
long assetId = byteBuffer.getLong();
|
||||
|
||||
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
|
||||
|
||||
@@ -107,12 +98,6 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
int dataLength = getBaseLength(transactionData) + EXTRAS_LENGTH;
|
||||
|
||||
int version = Transaction.getVersionByTimestamp(transactionData.getTimestamp());
|
||||
|
||||
// V4+ have assetId too
|
||||
if (version >= 4)
|
||||
dataLength += ASSET_ID_LENGTH;
|
||||
|
||||
dataLength += Utf8.encodedLength(deployATTransactionData.getName()) + Utf8.encodedLength(deployATTransactionData.getDescription())
|
||||
+ Utf8.encodedLength(deployATTransactionData.getAtType()) + Utf8.encodedLength(deployATTransactionData.getTags())
|
||||
+ deployATTransactionData.getCreationBytes().length;
|
||||
@@ -124,8 +109,6 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
|
||||
try {
|
||||
DeployAtTransactionData deployATTransactionData = (DeployAtTransactionData) transactionData;
|
||||
|
||||
int version = Transaction.getVersionByTimestamp(transactionData.getTimestamp());
|
||||
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
|
||||
transformCommonBytes(transactionData, bytes);
|
||||
@@ -144,8 +127,7 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
Serialization.serializeBigDecimal(bytes, deployATTransactionData.getAmount());
|
||||
|
||||
if (version >= 4)
|
||||
bytes.write(Longs.toByteArray(deployATTransactionData.getAssetId()));
|
||||
bytes.write(Longs.toByteArray(deployATTransactionData.getAssetId()));
|
||||
|
||||
Serialization.serializeBigDecimal(bytes, deployATTransactionData.getFee());
|
||||
|
||||
@@ -158,51 +140,4 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In Qora v1, the bytes used for verification omit AT-type and tags so we need to test for v1-ness and adjust the bytes accordingly.
|
||||
*
|
||||
* @param transactionData
|
||||
* @return byte[]
|
||||
* @throws TransformationException
|
||||
*/
|
||||
public static byte[] toBytesForSigningImpl(TransactionData transactionData) throws TransformationException {
|
||||
if (transactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp())
|
||||
return TransactionTransformer.toBytesForSigningImpl(transactionData);
|
||||
|
||||
// Special v1 version
|
||||
|
||||
// Easier to start from scratch
|
||||
try {
|
||||
DeployAtTransactionData deployATTransactionData = (DeployAtTransactionData) transactionData;
|
||||
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
|
||||
bytes.write(Ints.toByteArray(deployATTransactionData.getType().value));
|
||||
bytes.write(Longs.toByteArray(deployATTransactionData.getTimestamp()));
|
||||
bytes.write(deployATTransactionData.getReference());
|
||||
|
||||
bytes.write(deployATTransactionData.getCreatorPublicKey());
|
||||
|
||||
Serialization.serializeSizedString(bytes, deployATTransactionData.getName());
|
||||
|
||||
Serialization.serializeSizedString(bytes, deployATTransactionData.getDescription());
|
||||
|
||||
// Omitted: Serialization.serializeSizedString(bytes, deployATTransactionData.getATType());
|
||||
|
||||
// Omitted: Serialization.serializeSizedString(bytes, deployATTransactionData.getTags());
|
||||
|
||||
byte[] creationBytes = deployATTransactionData.getCreationBytes();
|
||||
bytes.write(Ints.toByteArray(creationBytes.length));
|
||||
bytes.write(creationBytes);
|
||||
|
||||
Serialization.serializeBigDecimal(bytes, deployATTransactionData.getAmount());
|
||||
|
||||
Serialization.serializeBigDecimal(bytes, deployATTransactionData.getFee());
|
||||
|
||||
return bytes.toByteArray();
|
||||
} catch (IOException | ClassCastException e) {
|
||||
throw new TransformationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -6,8 +6,6 @@ import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.account.GenesisAccount;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.GenesisTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -28,6 +26,8 @@ public class GenesisTransactionTransformer extends TransactionTransformer {
|
||||
private static final int AMOUNT_LENGTH = LONG_LENGTH;
|
||||
private static final int ASSET_ID_LENGTH = LONG_LENGTH;
|
||||
|
||||
private static final int TOTAL_LENGTH = TYPE_LENGTH + TIMESTAMP_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH + ASSET_ID_LENGTH;
|
||||
|
||||
protected static final TransactionLayout layout;
|
||||
|
||||
static {
|
||||
@@ -47,9 +47,7 @@ public class GenesisTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
BigDecimal amount = Serialization.deserializeBigDecimal(byteBuffer);
|
||||
|
||||
long assetId = Asset.QORT;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
assetId = byteBuffer.getLong();
|
||||
long assetId = byteBuffer.getLong();
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, null, GenesisAccount.PUBLIC_KEY, BigDecimal.ZERO, null);
|
||||
|
||||
@@ -57,11 +55,7 @@ public class GenesisTransactionTransformer extends TransactionTransformer {
|
||||
}
|
||||
|
||||
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||
if (transactionData.getTimestamp() < BlockChain.getInstance().getQortalTimestamp())
|
||||
return TYPE_LENGTH + TIMESTAMP_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH;
|
||||
|
||||
// Qortal
|
||||
return TYPE_LENGTH + TIMESTAMP_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH + ASSET_ID_LENGTH;
|
||||
return TOTAL_LENGTH;
|
||||
}
|
||||
|
||||
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
|
||||
@@ -78,8 +72,7 @@ public class GenesisTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
Serialization.serializeBigDecimal(bytes, genesisTransactionData.getAmount());
|
||||
|
||||
if (genesisTransactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp())
|
||||
bytes.write(Longs.toByteArray(genesisTransactionData.getAssetId()));
|
||||
bytes.write(Longs.toByteArray(genesisTransactionData.getAssetId()));
|
||||
|
||||
return bytes.toByteArray();
|
||||
} catch (IOException | ClassCastException e) {
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.GroupApprovalTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -39,9 +38,7 @@ public class GroupApprovalTransactionTransformer extends TransactionTransformer
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.GroupBanTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -48,9 +47,7 @@ public class GroupBanTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.GroupInviteTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -43,9 +42,7 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.GroupKickTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -46,9 +45,7 @@ public class GroupKickTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -4,10 +4,8 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.IssueAssetTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -26,12 +24,11 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
||||
private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH;
|
||||
private static final int QUANTITY_LENGTH = LONG_LENGTH;
|
||||
private static final int IS_DIVISIBLE_LENGTH = BOOLEAN_LENGTH;
|
||||
private static final int ASSET_REFERENCE_LENGTH = REFERENCE_LENGTH;
|
||||
private static final int DATA_SIZE_LENGTH = INT_LENGTH;
|
||||
private static final int IS_UNSPENDABLE_LENGTH = BOOLEAN_LENGTH;
|
||||
|
||||
private static final int EXTRAS_LENGTH = OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + QUANTITY_LENGTH
|
||||
+ IS_DIVISIBLE_LENGTH;
|
||||
+ IS_DIVISIBLE_LENGTH + DATA_SIZE_LENGTH + IS_UNSPENDABLE_LENGTH;
|
||||
|
||||
protected static final TransactionLayout layout;
|
||||
|
||||
@@ -59,9 +56,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
@@ -78,18 +73,9 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
boolean isDivisible = byteBuffer.get() != 0;
|
||||
|
||||
byte[] assetReference = new byte[ASSET_REFERENCE_LENGTH];
|
||||
String data = "";
|
||||
boolean isUnspendable = false;
|
||||
String data = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_DATA_SIZE);
|
||||
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp()) {
|
||||
// in v2, assets have additional fields
|
||||
data = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_DATA_SIZE);
|
||||
isUnspendable = byteBuffer.get() != 0;
|
||||
} else {
|
||||
// In v1, IssueAssetTransaction uses Asset.parse which also deserializes reference.
|
||||
byteBuffer.get(assetReference);
|
||||
}
|
||||
boolean isUnspendable = byteBuffer.get() != 0;
|
||||
|
||||
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
|
||||
|
||||
@@ -104,19 +90,10 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
||||
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||
IssueAssetTransactionData issueAssetTransactionData = (IssueAssetTransactionData) transactionData;
|
||||
|
||||
int dataLength = getBaseLength(transactionData) + EXTRAS_LENGTH
|
||||
return getBaseLength(transactionData) + EXTRAS_LENGTH
|
||||
+ Utf8.encodedLength(issueAssetTransactionData.getAssetName())
|
||||
+ Utf8.encodedLength(issueAssetTransactionData.getDescription());
|
||||
|
||||
if (transactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp()) {
|
||||
// In v2, assets have additional fields.
|
||||
dataLength += DATA_SIZE_LENGTH + Utf8.encodedLength(issueAssetTransactionData.getData()) + IS_UNSPENDABLE_LENGTH;
|
||||
} else {
|
||||
// In v1, IssueAssetTransaction uses Asset.toBytes which also serializes reference.
|
||||
dataLength += ASSET_REFERENCE_LENGTH;
|
||||
}
|
||||
|
||||
return dataLength;
|
||||
+ Utf8.encodedLength(issueAssetTransactionData.getDescription())
|
||||
+ Utf8.encodedLength(issueAssetTransactionData.getData());
|
||||
}
|
||||
|
||||
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
|
||||
@@ -136,20 +113,9 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
||||
bytes.write(Longs.toByteArray(issueAssetTransactionData.getQuantity()));
|
||||
bytes.write((byte) (issueAssetTransactionData.getIsDivisible() ? 1 : 0));
|
||||
|
||||
// In v2, assets have additional fields.
|
||||
if (transactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp()) {
|
||||
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getData());
|
||||
bytes.write((byte) (issueAssetTransactionData.getIsUnspendable() ? 1 : 0));
|
||||
} else {
|
||||
// In v1, IssueAssetTransaction uses Asset.toBytes which also
|
||||
// serializes Asset's reference which is the IssueAssetTransaction's
|
||||
// signature
|
||||
byte[] assetReference = issueAssetTransactionData.getSignature();
|
||||
if (assetReference != null)
|
||||
bytes.write(assetReference);
|
||||
else
|
||||
bytes.write(new byte[ASSET_REFERENCE_LENGTH]);
|
||||
}
|
||||
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getData());
|
||||
|
||||
bytes.write((byte) (issueAssetTransactionData.getIsUnspendable() ? 1 : 0));
|
||||
|
||||
Serialization.serializeBigDecimal(bytes, issueAssetTransactionData.getFee());
|
||||
|
||||
@@ -162,32 +128,4 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In Qora v1, the bytes used for verification have asset's reference zeroed
|
||||
* so we need to test for v1-ness and adjust the bytes accordingly.
|
||||
*
|
||||
* @param transactionData
|
||||
* @return byte[]
|
||||
* @throws TransformationException
|
||||
*/
|
||||
public static byte[] toBytesForSigningImpl(TransactionData transactionData) throws TransformationException {
|
||||
byte[] bytes = TransactionTransformer.toBytesForSigningImpl(transactionData);
|
||||
|
||||
if (transactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp())
|
||||
return bytes;
|
||||
|
||||
// Special v1 version
|
||||
|
||||
// Zero duplicate signature/reference
|
||||
int start = bytes.length - ASSET_REFERENCE_LENGTH - FEE_LENGTH; // before
|
||||
// asset
|
||||
// reference
|
||||
// (and
|
||||
// fee)
|
||||
int end = start + ASSET_REFERENCE_LENGTH;
|
||||
Arrays.fill(bytes, start, end, (byte) 0);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.JoinGroupTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -39,9 +38,7 @@ public class JoinGroupTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.LeaveGroupTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -39,9 +38,7 @@ public class LeaveGroupTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,8 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.MessageTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -29,7 +27,7 @@ public class MessageTransactionTransformer extends TransactionTransformer {
|
||||
private static final int IS_TEXT_LENGTH = BOOLEAN_LENGTH;
|
||||
private static final int IS_ENCRYPTED_LENGTH = BOOLEAN_LENGTH;
|
||||
|
||||
private static final int EXTRAS_LENGTH = RECIPIENT_LENGTH + AMOUNT_LENGTH + DATA_SIZE_LENGTH + IS_ENCRYPTED_LENGTH + IS_TEXT_LENGTH;
|
||||
private static final int EXTRAS_LENGTH = RECIPIENT_LENGTH + ASSET_ID_LENGTH + AMOUNT_LENGTH + DATA_SIZE_LENGTH + IS_ENCRYPTED_LENGTH + IS_TEXT_LENGTH;
|
||||
|
||||
protected static final TransactionLayout layout;
|
||||
|
||||
@@ -41,7 +39,7 @@ public class MessageTransactionTransformer extends TransactionTransformer {
|
||||
layout.add("reference", TransformationType.SIGNATURE);
|
||||
layout.add("sender's public key", TransformationType.PUBLIC_KEY);
|
||||
layout.add("recipient", TransformationType.ADDRESS);
|
||||
layout.add("asset ID of payment (v2+)", TransformationType.LONG);
|
||||
layout.add("asset ID of payment", TransformationType.LONG);
|
||||
layout.add("payment (can be zero)", TransformationType.AMOUNT);
|
||||
layout.add("message length", TransformationType.INT);
|
||||
layout.add("message", TransformationType.DATA);
|
||||
@@ -56,9 +54,7 @@ public class MessageTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
int version = Transaction.getVersionByTimestamp(timestamp);
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
@@ -67,11 +63,7 @@ public class MessageTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
String recipient = Serialization.deserializeAddress(byteBuffer);
|
||||
|
||||
long assetId;
|
||||
if (version == 1)
|
||||
assetId = Asset.QORT;
|
||||
else
|
||||
assetId = byteBuffer.getLong();
|
||||
long assetId = byteBuffer.getLong();
|
||||
|
||||
BigDecimal amount = Serialization.deserializeBigDecimal(byteBuffer);
|
||||
|
||||
@@ -100,13 +92,7 @@ public class MessageTransactionTransformer extends TransactionTransformer {
|
||||
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||
MessageTransactionData messageTransactionData = (MessageTransactionData) transactionData;
|
||||
|
||||
int dataLength = getBaseLength(transactionData) + EXTRAS_LENGTH + messageTransactionData.getData().length;
|
||||
|
||||
// V3+ has assetID for amount
|
||||
if (messageTransactionData.getVersion() != 1)
|
||||
dataLength += ASSET_ID_LENGTH;
|
||||
|
||||
return dataLength;
|
||||
return getBaseLength(transactionData) + EXTRAS_LENGTH + messageTransactionData.getData().length;
|
||||
}
|
||||
|
||||
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
|
||||
@@ -119,8 +105,7 @@ public class MessageTransactionTransformer extends TransactionTransformer {
|
||||
|
||||
Serialization.serializeAddress(bytes, messageTransactionData.getRecipient());
|
||||
|
||||
if (messageTransactionData.getVersion() != 1)
|
||||
bytes.write(Longs.toByteArray(messageTransactionData.getAssetId()));
|
||||
bytes.write(Longs.toByteArray(messageTransactionData.getAssetId()));
|
||||
|
||||
Serialization.serializeBigDecimal(bytes, messageTransactionData.getAmount());
|
||||
|
||||
|
@@ -5,10 +5,8 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.PaymentData;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.MultiPaymentTransactionData;
|
||||
@@ -47,9 +45,7 @@ public class MultiPaymentTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
@@ -103,27 +99,4 @@ public class MultiPaymentTransactionTransformer extends TransactionTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In Qora v1, the bytes used for verification are really mangled so we need to test for v1-ness and adjust the bytes accordingly.
|
||||
*
|
||||
* @param transactionData
|
||||
* @return byte[]
|
||||
* @throws TransformationException
|
||||
*/
|
||||
public static byte[] toBytesForSigningImpl(TransactionData transactionData) throws TransformationException {
|
||||
byte[] bytes = TransactionTransformer.toBytesForSigningImpl(transactionData);
|
||||
|
||||
if (transactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp())
|
||||
return bytes;
|
||||
|
||||
// Special v1 version
|
||||
|
||||
// In v1, a coding error means that all bytes prior to final payment entry are lost!
|
||||
// So we're left with: final payment entry and fee. Signature has already been stripped
|
||||
int v1Length = PaymentTransformer.getDataLength() + FEE_LENGTH;
|
||||
int v1Start = bytes.length - v1Length;
|
||||
|
||||
return Arrays.copyOfRange(bytes, v1Start, bytes.length);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.PaymentTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -39,9 +38,7 @@ public class PaymentTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.RegisterNameTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -46,9 +45,7 @@ public class RegisterNameTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.RemoveGroupAdminTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -41,9 +40,7 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.RewardShareTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -40,9 +39,7 @@ public class RewardShareTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.SellNameTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -43,9 +42,7 @@ public class SellNameTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.SetGroupTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@@ -39,9 +38,7 @@ public class SetGroupTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -18,7 +18,6 @@ import javax.xml.bind.annotation.XmlElement;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.qortal.account.PrivateKeyAccount;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.transaction.Transaction;
|
||||
import org.qortal.transaction.Transaction.TransactionType;
|
||||
@@ -222,13 +221,8 @@ public abstract class TransactionTransformer extends Transformer {
|
||||
}
|
||||
|
||||
protected static int getBaseLength(TransactionData transactionData) {
|
||||
// All transactions have at least txType, timestamp, reference, tx creator's public key and also fee and signature (on the end)
|
||||
int baseLength = TYPE_LENGTH + TIMESTAMP_LENGTH + REFERENCE_LENGTH + PUBLIC_KEY_LENGTH + FEE_LENGTH + SIGNATURE_LENGTH;
|
||||
|
||||
if (transactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp())
|
||||
baseLength += GROUPID_LENGTH;
|
||||
|
||||
return baseLength;
|
||||
// All transactions have at least txType, timestamp, txGroupId, reference, tx creator's public key and also fee and signature (on the end)
|
||||
return TYPE_LENGTH + TIMESTAMP_LENGTH + GROUPID_LENGTH + REFERENCE_LENGTH + PUBLIC_KEY_LENGTH + FEE_LENGTH + SIGNATURE_LENGTH;
|
||||
}
|
||||
|
||||
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||
@@ -309,17 +303,14 @@ public abstract class TransactionTransformer extends Transformer {
|
||||
}
|
||||
|
||||
protected static void transformCommonBytes(TransactionData transactionData, ByteArrayOutputStream bytes) throws IOException {
|
||||
boolean v2 = transactionData.getTimestamp() >= BlockChain.getInstance().getQortalTimestamp();
|
||||
|
||||
// Transaction type
|
||||
bytes.write(Ints.toByteArray(transactionData.getType().value));
|
||||
|
||||
// Timestamp
|
||||
bytes.write(Longs.toByteArray(transactionData.getTimestamp()));
|
||||
|
||||
if (v2)
|
||||
// Transaction's groupID
|
||||
bytes.write(Ints.toByteArray(transactionData.getTxGroupId()));
|
||||
// Transaction's groupID
|
||||
bytes.write(Ints.toByteArray(transactionData.getTxGroupId()));
|
||||
|
||||
// Reference
|
||||
bytes.write(transactionData.getReference());
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.data.transaction.TransferAssetTransactionData;
|
||||
@@ -43,9 +42,7 @@ public class TransferAssetTransactionTransformer extends TransactionTransformer
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.data.transaction.TransferPrivsTransactionData;
|
||||
@@ -37,9 +36,7 @@ public class TransferPrivsTransactionTransformer extends TransactionTransformer
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -6,7 +6,6 @@ import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.data.transaction.UpdateAssetTransactionData;
|
||||
@@ -50,9 +49,7 @@ public class UpdateAssetTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.data.transaction.UpdateGroupTransactionData;
|
||||
@@ -56,9 +55,7 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.data.transaction.UpdateNameTransactionData;
|
||||
@@ -46,9 +45,7 @@ public class UpdateNameTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.data.transaction.VoteOnPollTransactionData;
|
||||
@@ -44,9 +43,7 @@ public class VoteOnPollTransactionTransformer extends TransactionTransformer {
|
||||
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
int txGroupId = 0;
|
||||
if (timestamp >= BlockChain.getInstance().getQortalTimestamp())
|
||||
txGroupId = byteBuffer.getInt();
|
||||
int txGroupId = byteBuffer.getInt();
|
||||
|
||||
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||
byteBuffer.get(reference);
|
||||
|
Reference in New Issue
Block a user