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:
catbref
2020-04-27 12:27:18 +01:00
parent 136188339d
commit bd521baade
63 changed files with 169 additions and 1259 deletions

View File

@@ -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());

View File

@@ -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());

View File

@@ -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 {

View File

@@ -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;
}
/**

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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");

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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());

View File

@@ -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)

View File

@@ -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());
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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());

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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());

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);