Fixed old Qora v1 "GenesisAccount" by replacing with NullAccount

NullAccount has 'empty' public key (32 bytes of zeros) compared
with GenesisAccount's vague sometimes 8 bytes, sometimes 32 bytes
public key.

NullAccount has static public key and address, plus overridden
methods to speed up pointless calls like verify().

Genesis Block also tidied up, dropping old Qora v1 compatibility
and using proper block signature and public key to generate
minter's block signature.

Genesis Block transaction processing also simplified, with no need
to access repository to handle fake references, due to new
last-reference code (which will need to be merged).

Dropped support for old, broken RMD160 code.
This commit is contained in:
catbref 2020-04-27 14:57:27 +01:00
parent 2602bb01e1
commit 9e2663b11b
14 changed files with 80 additions and 106 deletions

View File

@ -3,6 +3,9 @@ package org.qortal.account;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.qortal.block.BlockChain; import org.qortal.block.BlockChain;
@ -15,6 +18,7 @@ import org.qortal.repository.Repository;
import org.qortal.transaction.Transaction; import org.qortal.transaction.Transaction;
import org.qortal.utils.Base58; import org.qortal.utils.Base58;
@XmlAccessorType(XmlAccessType.NONE) // Stops JAX-RS errors when unmarshalling blockchain config
public class Account { public class Account {
private static final Logger LOGGER = LogManager.getLogger(Account.class); private static final Logger LOGGER = LogManager.getLogger(Account.class);

View File

@ -1,13 +0,0 @@
package org.qortal.account;
import org.qortal.repository.Repository;
public final class GenesisAccount extends PublicKeyAccount {
public static final byte[] PUBLIC_KEY = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
public GenesisAccount(Repository repository) {
super(repository, PUBLIC_KEY);
}
}

View File

@ -0,0 +1,24 @@
package org.qortal.account;
import org.qortal.crypto.Crypto;
import org.qortal.repository.Repository;
public final class NullAccount extends PublicKeyAccount {
public static final byte[] PUBLIC_KEY = new byte[32];
public static final String ADDRESS = Crypto.toAddress(PUBLIC_KEY);
public NullAccount(Repository repository) {
super(repository, PUBLIC_KEY, ADDRESS);
}
protected NullAccount() {
}
@Override
public boolean verify(byte[] signature, byte[] message) {
// Can't sign, hence can't verify.
return false;
}
}

View File

@ -22,6 +22,18 @@ public class PublicKeyAccount extends Account {
this.publicKey = edPublicKeyParams.getEncoded(); this.publicKey = edPublicKeyParams.getEncoded();
} }
protected PublicKeyAccount(Repository repository, byte[] publicKey, String address) {
super(repository, address);
this.publicKey = publicKey;
this.edPublicKeyParams = null;
}
protected PublicKeyAccount() {
this.publicKey = null;
this.edPublicKeyParams = null;
}
public byte[] getPublicKey() { public byte[] getPublicKey() {
return this.publicKey; return this.publicKey;
} }

View File

@ -14,7 +14,7 @@ import org.ciyam.at.MachineState;
import org.ciyam.at.OpCode; import org.ciyam.at.OpCode;
import org.ciyam.at.Timestamp; import org.ciyam.at.Timestamp;
import org.qortal.account.Account; import org.qortal.account.Account;
import org.qortal.account.GenesisAccount; import org.qortal.account.NullAccount;
import org.qortal.account.PublicKeyAccount; import org.qortal.account.PublicKeyAccount;
import org.qortal.asset.Asset; import org.qortal.asset.Asset;
import org.qortal.crypto.Crypto; import org.qortal.crypto.Crypto;
@ -270,7 +270,7 @@ public class QortalATAPI extends API {
byte[] reference = this.getLastReference(); byte[] reference = this.getLastReference();
BigDecimal amount = BigDecimal.valueOf(unscaledAmount, 8); BigDecimal amount = BigDecimal.valueOf(unscaledAmount, 8);
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, GenesisAccount.PUBLIC_KEY, BigDecimal.ZERO, null); BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, NullAccount.PUBLIC_KEY, BigDecimal.ZERO, null);
ATTransactionData atTransactionData = new ATTransactionData(baseTransactionData, this.atData.getATAddress(), ATTransactionData atTransactionData = new ATTransactionData(baseTransactionData, this.atData.getATAddress(),
recipient.getAddress(), amount, this.atData.getAssetId(), new byte[0]); recipient.getAddress(), amount, this.atData.getAssetId(), new byte[0]);
AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData); AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData);
@ -289,7 +289,7 @@ public class QortalATAPI extends API {
long timestamp = this.getNextTransactionTimestamp(); long timestamp = this.getNextTransactionTimestamp();
byte[] reference = this.getLastReference(); byte[] reference = this.getLastReference();
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, GenesisAccount.PUBLIC_KEY, BigDecimal.ZERO, null); BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, NullAccount.PUBLIC_KEY, BigDecimal.ZERO, null);
ATTransactionData atTransactionData = new ATTransactionData(baseTransactionData, this.atData.getATAddress(), ATTransactionData atTransactionData = new ATTransactionData(baseTransactionData, this.atData.getATAddress(),
recipient.getAddress(), BigDecimal.ZERO, this.atData.getAssetId(), message); recipient.getAddress(), BigDecimal.ZERO, this.atData.getAssetId(), message);
AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData); AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData);
@ -316,7 +316,7 @@ public class QortalATAPI extends API {
byte[] reference = this.getLastReference(); byte[] reference = this.getLastReference();
BigDecimal amount = BigDecimal.valueOf(finalBalance, 8); BigDecimal amount = BigDecimal.valueOf(finalBalance, 8);
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, GenesisAccount.PUBLIC_KEY, BigDecimal.ZERO, null); BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, NullAccount.PUBLIC_KEY, BigDecimal.ZERO, null);
ATTransactionData atTransactionData = new ATTransactionData(baseTransactionData, this.atData.getATAddress(), ATTransactionData atTransactionData = new ATTransactionData(baseTransactionData, this.atData.getATAddress(),
creator.getAddress(), amount, this.atData.getAssetId(), new byte[0]); creator.getAddress(), amount, this.atData.getAssetId(), new byte[0]);
AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData); AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData);

View File

@ -7,27 +7,21 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.qortal.account.Account; import org.qortal.account.NullAccount;
import org.qortal.account.GenesisAccount;
import org.qortal.account.PublicKeyAccount;
import org.qortal.crypto.Crypto; import org.qortal.crypto.Crypto;
import org.qortal.data.asset.AssetData; import org.qortal.data.asset.AssetData;
import org.qortal.data.block.BlockData; import org.qortal.data.block.BlockData;
import org.qortal.data.transaction.IssueAssetTransactionData;
import org.qortal.data.transaction.TransactionData; import org.qortal.data.transaction.TransactionData;
import org.qortal.group.Group;
import org.qortal.repository.DataException; import org.qortal.repository.DataException;
import org.qortal.repository.Repository; import org.qortal.repository.Repository;
import org.qortal.transaction.Transaction; import org.qortal.transaction.Transaction;
import org.qortal.transaction.Transaction.ApprovalStatus; import org.qortal.transaction.Transaction.ApprovalStatus;
import org.qortal.transaction.Transaction.TransactionType;
import org.qortal.transform.TransformationException; import org.qortal.transform.TransformationException;
import org.qortal.transform.transaction.TransactionTransformer; import org.qortal.transform.transaction.TransactionTransformer;
@ -39,9 +33,8 @@ public class GenesisBlock extends Block {
private static final Logger LOGGER = LogManager.getLogger(GenesisBlock.class); private static final Logger LOGGER = LogManager.getLogger(GenesisBlock.class);
private static final byte[] GENESIS_REFERENCE = new byte[] { private static final byte[] GENESIS_BLOCK_REFERENCE = new byte[128];
1, 1, 1, 1, 1, 1, 1, 1 private static final byte[] GENESIS_TRANSACTION_REFERENCE = new byte[64];
}; // NOTE: Neither 64 nor 128 bytes!
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
public static class GenesisInfo { public static class GenesisInfo {
@ -96,37 +89,16 @@ public class GenesisBlock extends Block {
transactionData.setFee(BigDecimal.ZERO.setScale(8)); transactionData.setFee(BigDecimal.ZERO.setScale(8));
if (transactionData.getCreatorPublicKey() == null) if (transactionData.getCreatorPublicKey() == null)
transactionData.setCreatorPublicKey(GenesisAccount.PUBLIC_KEY); transactionData.setCreatorPublicKey(NullAccount.PUBLIC_KEY);
if (transactionData.getTimestamp() == 0) if (transactionData.getTimestamp() == 0)
transactionData.setTimestamp(info.timestamp); transactionData.setTimestamp(info.timestamp);
}); });
// For version 1, extract any ISSUE_ASSET transactions into initialAssets and only allow GENESIS transactions byte[] reference = GENESIS_BLOCK_REFERENCE;
if (info.version == 1) {
List<TransactionData> issueAssetTransactions = transactionsData.stream()
.filter(transactionData -> transactionData.getType() == TransactionType.ISSUE_ASSET).collect(Collectors.toList());
transactionsData.removeAll(issueAssetTransactions);
// There should be only GENESIS transactions left;
if (transactionsData.stream().anyMatch(transactionData -> transactionData.getType() != TransactionType.GENESIS)) {
LOGGER.error("Version 1 genesis block only allowed to contain GENESIS transctions (after issue-asset processing)");
throw new RuntimeException("Version 1 genesis block only allowed to contain GENESIS transctions (after issue-asset processing)");
}
// Convert ISSUE_ASSET transactions into initial assets
initialAssets = issueAssetTransactions.stream().map(transactionData -> {
IssueAssetTransactionData issueAssetTransactionData = (IssueAssetTransactionData) transactionData;
return new AssetData(issueAssetTransactionData.getOwner(), issueAssetTransactionData.getAssetName(), issueAssetTransactionData.getDescription(),
issueAssetTransactionData.getQuantity(), issueAssetTransactionData.getIsDivisible(), "", false, Group.NO_GROUP, issueAssetTransactionData.getReference());
}).collect(Collectors.toList());
}
byte[] reference = GENESIS_REFERENCE;
int transactionCount = transactionsData.size(); int transactionCount = transactionsData.size();
BigDecimal totalFees = BigDecimal.ZERO.setScale(8); BigDecimal totalFees = BigDecimal.ZERO.setScale(8);
byte[] minterPublicKey = GenesisAccount.PUBLIC_KEY; byte[] minterPublicKey = NullAccount.PUBLIC_KEY;
byte[] bytesForSignature = getBytesForMinterSignature(info.timestamp, reference, minterPublicKey); byte[] bytesForSignature = getBytesForMinterSignature(info.timestamp, reference, minterPublicKey);
byte[] minterSignature = calcGenesisMinterSignature(bytesForSignature); byte[] minterSignature = calcGenesisMinterSignature(bytesForSignature);
byte[] transactionsSignature = calcGenesisTransactionsSignature(); byte[] transactionsSignature = calcGenesisTransactionsSignature();
@ -212,24 +184,16 @@ public class GenesisBlock extends Block {
try { try {
// Passing expected size to ByteArrayOutputStream avoids reallocation when adding more bytes than default 32. // Passing expected size to ByteArrayOutputStream avoids reallocation when adding more bytes than default 32.
// See below for explanation of some of the values used to calculated expected size. // See below for explanation of some of the values used to calculated expected size.
ByteArrayOutputStream bytes = new ByteArrayOutputStream(8 + 64 + 8 + 32); ByteArrayOutputStream bytes = new ByteArrayOutputStream(8 + 128 + 32);
/* // Genesis block timestamp
* NOTE: Historic code had genesis block using Longs.toByteArray(version) compared to standard block's Ints.toByteArray. The subsequent
* Bytes.ensureCapacity(versionBytes, 0, 4) did not truncate versionBytes back to 4 bytes either. This means 8 bytes were used even though
* VERSION_LENGTH is set to 4. Correcting this historic bug will break genesis block signatures!
*/
// For Qortal, we use genesis timestamp instead
bytes.write(Longs.toByteArray(timestamp)); bytes.write(Longs.toByteArray(timestamp));
/* // Block's reference
* NOTE: Historic code had the reference expanded to only 64 bytes whereas standard block references are 128 bytes. Correcting this historic bug bytes.write(reference);
* will break genesis block signatures!
*/
bytes.write(Bytes.ensureCapacity(reference, 64, 0));
// NOTE: Genesis account's public key is only 8 bytes, not the usual 32, so we have to pad. // Minting account's public key (typically NullAccount)
bytes.write(Bytes.ensureCapacity(minterPublicKey, 32, 0)); bytes.write(minterPublicKey);
return bytes.toByteArray(); return bytes.toByteArray();
} catch (IOException e) { } catch (IOException e) {
@ -295,26 +259,18 @@ public class GenesisBlock extends Block {
public void process() throws DataException { public void process() throws DataException {
LOGGER.info(String.format("Using genesis block timestamp of %d", this.blockData.getTimestamp())); LOGGER.info(String.format("Using genesis block timestamp of %d", this.blockData.getTimestamp()));
// If we're a version 1 genesis block, create assets now
if (this.blockData.getVersion() == 1)
for (AssetData assetData : initialAssets)
repository.getAssetRepository().save(assetData);
/* /*
* Some transactions will be missing references and signatures, * Some transactions will be missing references and signatures,
* so we generate them by trial-processing transactions and using * so we generate them by using <tt>GENESIS_TRANSACTION_REFERENCE</tt>
* account's last-reference to fill in the gaps for reference,
* and a duplicated SHA256 digest for signature * and a duplicated SHA256 digest for signature
*/ */
this.repository.setSavepoint();
try { try {
for (Transaction transaction : this.getTransactions()) { for (Transaction transaction : this.getTransactions()) {
TransactionData transactionData = transaction.getTransactionData(); TransactionData transactionData = transaction.getTransactionData();
Account creator = new PublicKeyAccount(this.repository, transactionData.getCreatorPublicKey());
// Missing reference? // Missing reference?
if (transactionData.getReference() == null) if (transactionData.getReference() == null)
transactionData.setReference(creator.getLastReference()); transactionData.setReference(GENESIS_TRANSACTION_REFERENCE);
// Missing signature? // Missing signature?
if (transactionData.getSignature() == null) { if (transactionData.getSignature() == null) {
@ -324,18 +280,11 @@ public class GenesisBlock extends Block {
transactionData.setSignature(signature); transactionData.setSignature(signature);
} }
// Missing approval status (not used in V1) // Approval status
transactionData.setApprovalStatus(ApprovalStatus.NOT_REQUIRED); transactionData.setApprovalStatus(ApprovalStatus.NOT_REQUIRED);
// Ask transaction to update references, etc.
transaction.processReferencesAndFees();
creator.setLastReference(transactionData.getSignature());
} }
} catch (TransformationException e) { } catch (TransformationException e) {
throw new RuntimeException("Can't process genesis block transaction", e); throw new RuntimeException("Can't process genesis block transaction", e);
} finally {
this.repository.rollbackToSavepoint();
} }
// Save transactions into repository ready for processing // Save transactions into repository ready for processing

View File

@ -6,7 +6,7 @@ import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import org.qortal.account.GenesisAccount; import org.qortal.account.NullAccount;
import org.qortal.transaction.Transaction.TransactionType; import org.qortal.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@ -31,14 +31,14 @@ public class ATTransactionData extends TransactionData {
} }
public void afterUnmarshal(Unmarshaller u, Object parent) { public void afterUnmarshal(Unmarshaller u, Object parent) {
this.creatorPublicKey = GenesisAccount.PUBLIC_KEY; this.creatorPublicKey = NullAccount.PUBLIC_KEY;
} }
/** From repository */ /** From repository */
public ATTransactionData(BaseTransactionData baseTransactionData, String atAddress, String recipient, BigDecimal amount, Long assetId, byte[] message) { public ATTransactionData(BaseTransactionData baseTransactionData, String atAddress, String recipient, BigDecimal amount, Long assetId, byte[] message) {
super(TransactionType.AT, baseTransactionData); super(TransactionType.AT, baseTransactionData);
this.creatorPublicKey = GenesisAccount.PUBLIC_KEY; this.creatorPublicKey = NullAccount.PUBLIC_KEY;
this.atAddress = atAddress; this.atAddress = atAddress;
this.recipient = recipient; this.recipient = recipient;
this.amount = amount; this.amount = amount;

View File

@ -6,7 +6,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue; import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;
import org.qortal.account.GenesisAccount; import org.qortal.account.NullAccount;
import org.qortal.block.GenesisBlock; import org.qortal.block.GenesisBlock;
import org.qortal.transaction.Transaction.TransactionType; import org.qortal.transaction.Transaction.TransactionType;
@ -36,10 +36,10 @@ public class AccountFlagsTransactionData extends TransactionData {
/* /*
* If we're being constructed as part of the genesis block info inside blockchain config * If we're being constructed as part of the genesis block info inside blockchain config
* and no specific creator's public key is supplied * and no specific creator's public key is supplied
* then use genesis account's public key. * then use null account's public key.
*/ */
if (parent instanceof GenesisBlock.GenesisInfo && this.creatorPublicKey == null) if (parent instanceof GenesisBlock.GenesisInfo && this.creatorPublicKey == null)
this.creatorPublicKey = GenesisAccount.PUBLIC_KEY; this.creatorPublicKey = NullAccount.PUBLIC_KEY;
} }
/** From repository */ /** From repository */

View File

@ -6,7 +6,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue; import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;
import org.qortal.account.GenesisAccount; import org.qortal.account.NullAccount;
import org.qortal.block.GenesisBlock; import org.qortal.block.GenesisBlock;
import org.qortal.transaction.Transaction.TransactionType; import org.qortal.transaction.Transaction.TransactionType;
@ -33,10 +33,10 @@ public class AccountLevelTransactionData extends TransactionData {
/* /*
* If we're being constructed as part of the genesis block info inside blockchain config * If we're being constructed as part of the genesis block info inside blockchain config
* and no specific creator's public key is supplied * and no specific creator's public key is supplied
* then use genesis account's public key. * then use null account's public key.
*/ */
if (parent instanceof GenesisBlock.GenesisInfo && this.creatorPublicKey == null) if (parent instanceof GenesisBlock.GenesisInfo && this.creatorPublicKey == null)
this.creatorPublicKey = GenesisAccount.PUBLIC_KEY; this.creatorPublicKey = NullAccount.PUBLIC_KEY;
} }
/** From repository, network/API */ /** From repository, network/API */

View File

@ -34,10 +34,8 @@ public class GenesisTransactionData extends TransactionData {
super(TransactionType.GENESIS); super(TransactionType.GENESIS);
} }
/** From repository (V2) */ /** From repository */
public GenesisTransactionData(BaseTransactionData baseTransactionData, String recipient, BigDecimal amount, long assetId) { public GenesisTransactionData(BaseTransactionData baseTransactionData, String recipient, BigDecimal amount, long assetId) {
// No groupID, null reference, zero fee, no approval required, height always 1
// super(TransactionType.GENESIS, timestamp, Group.NO_GROUP, null, GenesisAccount.PUBLIC_KEY, BigDecimal.ZERO, ApprovalStatus.NOT_REQUIRED, 1, signature);
super(TransactionType.GENESIS, baseTransactionData); super(TransactionType.GENESIS, baseTransactionData);
this.recipient = recipient; this.recipient = recipient;
@ -45,7 +43,7 @@ public class GenesisTransactionData extends TransactionData {
this.assetId = assetId; this.assetId = assetId;
} }
/** From repository (V1, where asset locked to QORT) */ /** From repository (where asset locked to QORT) */
public GenesisTransactionData(BaseTransactionData baseTransactionData, String recipient, BigDecimal amount) { public GenesisTransactionData(BaseTransactionData baseTransactionData, String recipient, BigDecimal amount) {
this(baseTransactionData, recipient, amount, Asset.QORT); this(baseTransactionData, recipient, amount, Asset.QORT);
} }

View File

@ -5,7 +5,7 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue; import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;
import org.qortal.account.GenesisAccount; import org.qortal.account.NullAccount;
import org.qortal.block.GenesisBlock; import org.qortal.block.GenesisBlock;
import org.qortal.transaction.Transaction.TransactionType; import org.qortal.transaction.Transaction.TransactionType;
@ -51,10 +51,10 @@ public class IssueAssetTransactionData extends TransactionData {
/* /*
* If we're being constructed as part of the genesis block info inside blockchain config * If we're being constructed as part of the genesis block info inside blockchain config
* and no specific issuer's public key is supplied * and no specific issuer's public key is supplied
* then use genesis account's public key. * then use null account's public key.
*/ */
if (parent instanceof GenesisBlock.GenesisInfo && this.issuerPublicKey == null) if (parent instanceof GenesisBlock.GenesisInfo && this.issuerPublicKey == null)
this.issuerPublicKey = GenesisAccount.PUBLIC_KEY; this.issuerPublicKey = NullAccount.PUBLIC_KEY;
this.creatorPublicKey = this.issuerPublicKey; this.creatorPublicKey = this.issuerPublicKey;
} }

View File

@ -5,7 +5,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import org.qortal.account.Account; import org.qortal.account.Account;
import org.qortal.account.GenesisAccount; import org.qortal.account.NullAccount;
import org.qortal.asset.Asset; import org.qortal.asset.Asset;
import org.qortal.data.transaction.AccountFlagsTransactionData; import org.qortal.data.transaction.AccountFlagsTransactionData;
import org.qortal.data.transaction.TransactionData; import org.qortal.data.transaction.TransactionData;
@ -68,8 +68,8 @@ public class AccountFlagsTransaction extends Transaction {
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
Account creator = getCreator(); Account creator = getCreator();
// Only genesis account can modify flags // Only null account can modify flags
if (!creator.getAddress().equals(new GenesisAccount(repository).getAddress())) if (!creator.getAddress().equals(NullAccount.ADDRESS))
return ValidationResult.NO_FLAG_PERMISSION; return ValidationResult.NO_FLAG_PERMISSION;
// Check fee is zero or positive // Check fee is zero or positive

View File

@ -5,7 +5,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import org.qortal.account.Account; import org.qortal.account.Account;
import org.qortal.account.GenesisAccount; import org.qortal.account.NullAccount;
import org.qortal.asset.Asset; import org.qortal.asset.Asset;
import org.qortal.block.BlockChain; import org.qortal.block.BlockChain;
import org.qortal.data.transaction.AccountLevelTransactionData; import org.qortal.data.transaction.AccountLevelTransactionData;
@ -70,7 +70,7 @@ public class AccountLevelTransaction extends Transaction {
Account creator = getCreator(); Account creator = getCreator();
// Only genesis account can modify level // Only genesis account can modify level
if (!creator.getAddress().equals(new GenesisAccount(repository).getAddress())) if (!creator.getAddress().equals(new NullAccount(repository).getAddress()))
return ValidationResult.NO_FLAG_PERMISSION; return ValidationResult.NO_FLAG_PERMISSION;
// Check fee is zero or positive // Check fee is zero or positive

View File

@ -5,7 +5,7 @@ import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.qortal.account.GenesisAccount; import org.qortal.account.NullAccount;
import org.qortal.data.transaction.BaseTransactionData; import org.qortal.data.transaction.BaseTransactionData;
import org.qortal.data.transaction.GenesisTransactionData; import org.qortal.data.transaction.GenesisTransactionData;
import org.qortal.data.transaction.TransactionData; import org.qortal.data.transaction.TransactionData;
@ -49,7 +49,7 @@ public class GenesisTransactionTransformer extends TransactionTransformer {
long assetId = byteBuffer.getLong(); long assetId = byteBuffer.getLong();
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, null, GenesisAccount.PUBLIC_KEY, BigDecimal.ZERO, null); BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, null, NullAccount.PUBLIC_KEY, BigDecimal.ZERO, null);
return new GenesisTransactionData(baseTransactionData, recipient, amount, assetId); return new GenesisTransactionData(baseTransactionData, recipient, amount, assetId);
} }