Tidy up Assets by removing 'owner' from ISSUE_ASSET.

Owner now derived from issuer's public key.
Maximum asset name length reduced to 40 characters.

Repository table changes.

"owner" removed from test blockchain configs and "issuerPublicKey" used instead
where applicable.

Some getters in the form of "getIs___()" renamed to simply "is____()".
This commit is contained in:
catbref 2020-05-15 16:22:13 +01:00
parent f6ed3388a4
commit 38a2af8cd5
21 changed files with 85 additions and 112 deletions

View File

@ -1,5 +1,6 @@
package org.qortal.asset; package org.qortal.asset;
import org.qortal.crypto.Crypto;
import org.qortal.data.asset.AssetData; import org.qortal.data.asset.AssetData;
import org.qortal.data.transaction.IssueAssetTransactionData; import org.qortal.data.transaction.IssueAssetTransactionData;
import org.qortal.data.transaction.TransactionData; import org.qortal.data.transaction.TransactionData;
@ -22,7 +23,7 @@ public class Asset {
// Other useful constants // Other useful constants
public static final int MAX_NAME_SIZE = 400; public static final int MAX_NAME_SIZE = 40;
public static final int MAX_DESCRIPTION_SIZE = 4000; public static final int MAX_DESCRIPTION_SIZE = 4000;
public static final int MAX_DATA_SIZE = 400000; public static final int MAX_DATA_SIZE = 400000;
@ -42,11 +43,13 @@ public class Asset {
public Asset(Repository repository, IssueAssetTransactionData issueAssetTransactionData) { public Asset(Repository repository, IssueAssetTransactionData issueAssetTransactionData) {
this.repository = repository; this.repository = repository;
String ownerAddress = Crypto.toAddress(issueAssetTransactionData.getCreatorPublicKey());
// NOTE: transaction's reference is used to look up newly assigned assetID on creation! // NOTE: transaction's reference is used to look up newly assigned assetID on creation!
this.assetData = new AssetData(issueAssetTransactionData.getOwner(), issueAssetTransactionData.getAssetName(), this.assetData = new AssetData(ownerAddress, issueAssetTransactionData.getAssetName(),
issueAssetTransactionData.getDescription(), issueAssetTransactionData.getQuantity(), issueAssetTransactionData.getDescription(), issueAssetTransactionData.getQuantity(),
issueAssetTransactionData.getIsDivisible(), issueAssetTransactionData.getData(), issueAssetTransactionData.isDivisible(), issueAssetTransactionData.getData(),
issueAssetTransactionData.getIsUnspendable(), issueAssetTransactionData.isUnspendable(),
issueAssetTransactionData.getTxGroupId(), issueAssetTransactionData.getSignature()); issueAssetTransactionData.getTxGroupId(), issueAssetTransactionData.getSignature());
} }
@ -118,10 +121,11 @@ public class Asset {
throw new IllegalStateException("Missing referenced transaction when orphaning UPDATE_ASSET"); throw new IllegalStateException("Missing referenced transaction when orphaning UPDATE_ASSET");
switch (previousTransactionData.getType()) { switch (previousTransactionData.getType()) {
case ISSUE_ASSET: case ISSUE_ASSET: {
IssueAssetTransactionData previousIssueAssetTransactionData = (IssueAssetTransactionData) previousTransactionData; IssueAssetTransactionData previousIssueAssetTransactionData = (IssueAssetTransactionData) previousTransactionData;
this.assetData.setOwner(previousIssueAssetTransactionData.getOwner()); String ownerAddress = Crypto.toAddress(previousIssueAssetTransactionData.getCreatorPublicKey());
this.assetData.setOwner(ownerAddress);
if (needDescription) { if (needDescription) {
this.assetData.setDescription(previousIssueAssetTransactionData.getDescription()); this.assetData.setDescription(previousIssueAssetTransactionData.getDescription());
@ -133,8 +137,9 @@ public class Asset {
needData = false; needData = false;
} }
break; break;
}
case UPDATE_ASSET: case UPDATE_ASSET: {
UpdateAssetTransactionData previousUpdateAssetTransactionData = (UpdateAssetTransactionData) previousTransactionData; UpdateAssetTransactionData previousUpdateAssetTransactionData = (UpdateAssetTransactionData) previousTransactionData;
this.assetData.setOwner(previousUpdateAssetTransactionData.getNewOwner()); this.assetData.setOwner(previousUpdateAssetTransactionData.getNewOwner());
@ -152,7 +157,9 @@ public class Asset {
// Get signature for previous transaction in chain, just in case we need it // Get signature for previous transaction in chain, just in case we need it
if (needDescription || needData) if (needDescription || needData)
previousTransactionSignature = previousUpdateAssetTransactionData.getOrphanReference(); previousTransactionSignature = previousUpdateAssetTransactionData.getOrphanReference();
break; break;
}
default: default:
throw new IllegalStateException("Invalid referenced transaction when orphaning UPDATE_ASSET"); throw new IllegalStateException("Invalid referenced transaction when orphaning UPDATE_ASSET");

View File

@ -335,7 +335,7 @@ public class Order {
continue; continue;
// Calculate amount granularity, based on price and both assets' divisibility, so that return-amount traded is a valid value (integer or to 8 d.p.) // Calculate amount granularity, based on price and both assets' divisibility, so that return-amount traded is a valid value (integer or to 8 d.p.)
long granularity = calculateAmountGranularity(matchingAssetData.getIsDivisible(), returnAssetData.getIsDivisible(), theirOrderData.getPrice()); long granularity = calculateAmountGranularity(matchingAssetData.isDivisible(), returnAssetData.isDivisible(), theirOrderData.getPrice());
LOGGER.trace(() -> String.format("granularity (amount granularity): %s %s", prettyAmount(granularity), matchingAssetData.getName())); LOGGER.trace(() -> String.format("granularity (amount granularity): %s %s", prettyAmount(granularity), matchingAssetData.getName()));
// Reduce matched amount (if need be) to fit granularity // Reduce matched amount (if need be) to fit granularity
@ -395,7 +395,7 @@ public class Order {
* @throws DataException if divisibility check fails * @throws DataException if divisibility check fails
*/ */
private void checkDivisibility(AssetData assetData, long amount, OrderData orderData) throws DataException { private void checkDivisibility(AssetData assetData, long amount, OrderData orderData) throws DataException {
if (assetData.getIsDivisible() || amount % Amounts.MULTIPLIER == 0) if (assetData.isDivisible() || amount % Amounts.MULTIPLIER == 0)
// Asset is divisible or amount has no fractional part // Asset is divisible or amount has no fractional part
return; return;

View File

@ -84,7 +84,7 @@ public class AssetData {
return this.quantity; return this.quantity;
} }
public boolean getIsDivisible() { public boolean isDivisible() {
return this.isDivisible; return this.isDivisible;
} }
@ -96,7 +96,7 @@ public class AssetData {
this.data = data; this.data = data;
} }
public boolean getIsUnspendable() { public boolean isUnspendable() {
return this.isUnspendable; return this.isUnspendable;
} }

View File

@ -29,9 +29,6 @@ public class IssueAssetTransactionData extends TransactionData {
@Schema(description = "asset issuer's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") @Schema(description = "asset issuer's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
private byte[] issuerPublicKey; private byte[] issuerPublicKey;
@Schema(description = "asset owner's address", example = "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v")
private String owner;
@Schema(description = "asset name", example = "GOLD") @Schema(description = "asset name", example = "GOLD")
private String assetName; private String assetName;
@ -72,12 +69,11 @@ public class IssueAssetTransactionData extends TransactionData {
/** From repository */ /** From repository */
public IssueAssetTransactionData(BaseTransactionData baseTransactionData, public IssueAssetTransactionData(BaseTransactionData baseTransactionData,
Long assetId, String owner, String assetName, String description, long quantity, boolean isDivisible, String data, boolean isUnspendable) { Long assetId, String assetName, String description, long quantity, boolean isDivisible, String data, boolean isUnspendable) {
super(TransactionType.ISSUE_ASSET, baseTransactionData); super(TransactionType.ISSUE_ASSET, baseTransactionData);
this.assetId = assetId; this.assetId = assetId;
this.issuerPublicKey = baseTransactionData.creatorPublicKey; this.issuerPublicKey = baseTransactionData.creatorPublicKey;
this.owner = owner;
this.assetName = assetName; this.assetName = assetName;
this.description = description; this.description = description;
this.quantity = quantity; this.quantity = quantity;
@ -87,9 +83,9 @@ public class IssueAssetTransactionData extends TransactionData {
} }
/** From network/API */ /** From network/API */
public IssueAssetTransactionData(BaseTransactionData baseTransactionData, String owner, String assetName, String description, public IssueAssetTransactionData(BaseTransactionData baseTransactionData, String assetName, String description,
long quantity, boolean isDivisible, String data, boolean isUnspendable) { long quantity, boolean isDivisible, String data, boolean isUnspendable) {
this(baseTransactionData, null, owner, assetName, description, quantity, isDivisible, data, isUnspendable); this(baseTransactionData, null, assetName, description, quantity, isDivisible, data, isUnspendable);
} }
// Getters/Setters // Getters/Setters
@ -106,14 +102,6 @@ public class IssueAssetTransactionData extends TransactionData {
return this.issuerPublicKey; return this.issuerPublicKey;
} }
public String getOwner() {
return this.owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getAssetName() { public String getAssetName() {
return this.assetName; return this.assetName;
} }
@ -126,7 +114,7 @@ public class IssueAssetTransactionData extends TransactionData {
return this.quantity; return this.quantity;
} }
public boolean getIsDivisible() { public boolean isDivisible() {
return this.isDivisible; return this.isDivisible;
} }
@ -134,7 +122,7 @@ public class IssueAssetTransactionData extends TransactionData {
return this.data; return this.data;
} }
public boolean getIsUnspendable() { public boolean isUnspendable() {
return this.isUnspendable; return this.isUnspendable;
} }

View File

@ -86,7 +86,7 @@ public class Payment {
return ValidationResult.ASSET_DOES_NOT_EXIST; return ValidationResult.ASSET_DOES_NOT_EXIST;
// Do not allow non-owner asset holders to use asset // Do not allow non-owner asset holders to use asset
if (assetData.getIsUnspendable() && !assetData.getOwner().equals(sender.getAddress())) if (assetData.isUnspendable() && !assetData.getOwner().equals(sender.getAddress()))
return ValidationResult.ASSET_NOT_SPENDABLE; return ValidationResult.ASSET_NOT_SPENDABLE;
// If we're sending to an AT then assetId must match AT's assetId // If we're sending to an AT then assetId must match AT's assetId
@ -94,7 +94,7 @@ public class Payment {
return ValidationResult.ASSET_DOES_NOT_MATCH_AT; return ValidationResult.ASSET_DOES_NOT_MATCH_AT;
// Check asset amount is integer if asset is not divisible // Check asset amount is integer if asset is not divisible
if (!assetData.getIsDivisible() && paymentData.getAmount() % Amounts.MULTIPLIER != 0) if (!assetData.isDivisible() && paymentData.getAmount() % Amounts.MULTIPLIER != 0)
return ValidationResult.INVALID_AMOUNT; return ValidationResult.INVALID_AMOUNT;
// Set or add amount into amounts-by-asset map // Set or add amount into amounts-by-asset map

View File

@ -159,8 +159,8 @@ public class HSQLDBAssetRepository implements AssetRepository {
saveHelper.bind("asset_id", assetData.getAssetId()).bind("owner", assetData.getOwner()) saveHelper.bind("asset_id", assetData.getAssetId()).bind("owner", assetData.getOwner())
.bind("asset_name", assetData.getName()).bind("description", assetData.getDescription()) .bind("asset_name", assetData.getName()).bind("description", assetData.getDescription())
.bind("quantity", assetData.getQuantity()).bind("is_divisible", assetData.getIsDivisible()) .bind("quantity", assetData.getQuantity()).bind("is_divisible", assetData.isDivisible())
.bind("data", assetData.getData()).bind("is_unspendable", assetData.getIsUnspendable()) .bind("data", assetData.getData()).bind("is_unspendable", assetData.isUnspendable())
.bind("creation_group_id", assetData.getCreationGroupId()).bind("reference", assetData.getReference()); .bind("creation_group_id", assetData.getCreationGroupId()).bind("reference", assetData.getReference());
try { try {

View File

@ -380,8 +380,7 @@ public class HSQLDBDatabaseUpdates {
stmt.execute("CREATE INDEX AssetTradeSellOrderIndex on AssetTrades (target_order_id, traded_when)"); stmt.execute("CREATE INDEX AssetTradeSellOrderIndex on AssetTrades (target_order_id, traded_when)");
// Issue Asset Transactions // Issue Asset Transactions
stmt.execute("CREATE TABLE IssueAssetTransactions (signature Signature, issuer QortalPublicKey NOT NULL, owner QortalAddress NOT NULL, " stmt.execute("CREATE TABLE IssueAssetTransactions (signature Signature, issuer QortalPublicKey NOT NULL, asset_name AssetName NOT NULL, "
+ "asset_name AssetName NOT NULL, "
+ "description GenericDescription NOT NULL, quantity BIGINT NOT NULL, is_divisible BOOLEAN NOT NULL, asset_id AssetID, " + "description GenericDescription NOT NULL, quantity BIGINT NOT NULL, is_divisible BOOLEAN NOT NULL, asset_id AssetID, "
+ "is_unspendable BOOLEAN NOT NULL, data AssetData NOT NULL DEFAULT '', " + TRANSACTION_KEYS + ")"); + "is_unspendable BOOLEAN NOT NULL, data AssetData NOT NULL DEFAULT '', " + TRANSACTION_KEYS + ")");

View File

@ -17,26 +17,25 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo
} }
TransactionData fromBase(BaseTransactionData baseTransactionData) throws DataException { TransactionData fromBase(BaseTransactionData baseTransactionData) throws DataException {
String sql = "SELECT owner, asset_name, description, quantity, is_divisible, data, is_unspendable, asset_id FROM IssueAssetTransactions WHERE signature = ?"; String sql = "SELECT asset_name, description, quantity, is_divisible, data, is_unspendable, asset_id FROM IssueAssetTransactions WHERE signature = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, baseTransactionData.getSignature())) { try (ResultSet resultSet = this.repository.checkedExecute(sql, baseTransactionData.getSignature())) {
if (resultSet == null) if (resultSet == null)
return null; return null;
String owner = resultSet.getString(1); String assetName = resultSet.getString(1);
String assetName = resultSet.getString(2); String description = resultSet.getString(2);
String description = resultSet.getString(3); long quantity = resultSet.getLong(3);
long quantity = resultSet.getLong(4); boolean isDivisible = resultSet.getBoolean(4);
boolean isDivisible = resultSet.getBoolean(5); String data = resultSet.getString(5);
String data = resultSet.getString(6); boolean isUnspendable = resultSet.getBoolean(6);
boolean isUnspendable = resultSet.getBoolean(7);
// Special null-checking for asset ID // Special null-checking for asset ID
Long assetId = resultSet.getLong(8); Long assetId = resultSet.getLong(7);
if (assetId == 0 && resultSet.wasNull()) if (assetId == 0 && resultSet.wasNull())
assetId = null; assetId = null;
return new IssueAssetTransactionData(baseTransactionData, assetId, owner, assetName, description, quantity, isDivisible, return new IssueAssetTransactionData(baseTransactionData, assetId, assetName, description, quantity, isDivisible,
data, isUnspendable); data, isUnspendable);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch issue asset transaction from repository", e); throw new DataException("Unable to fetch issue asset transaction from repository", e);
@ -50,10 +49,10 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo
HSQLDBSaver saveHelper = new HSQLDBSaver("IssueAssetTransactions"); HSQLDBSaver saveHelper = new HSQLDBSaver("IssueAssetTransactions");
saveHelper.bind("signature", issueAssetTransactionData.getSignature()).bind("issuer", issueAssetTransactionData.getIssuerPublicKey()) saveHelper.bind("signature", issueAssetTransactionData.getSignature()).bind("issuer", issueAssetTransactionData.getIssuerPublicKey())
.bind("owner", issueAssetTransactionData.getOwner()).bind("asset_name", issueAssetTransactionData.getAssetName()) .bind("asset_name", issueAssetTransactionData.getAssetName())
.bind("description", issueAssetTransactionData.getDescription()).bind("quantity", issueAssetTransactionData.getQuantity()) .bind("description", issueAssetTransactionData.getDescription()).bind("quantity", issueAssetTransactionData.getQuantity())
.bind("is_divisible", issueAssetTransactionData.getIsDivisible()).bind("data", issueAssetTransactionData.getData()) .bind("is_divisible", issueAssetTransactionData.isDivisible()).bind("data", issueAssetTransactionData.getData())
.bind("is_unspendable", issueAssetTransactionData.getIsUnspendable()).bind("asset_id", issueAssetTransactionData.getAssetId()); .bind("is_unspendable", issueAssetTransactionData.isUnspendable()).bind("asset_id", issueAssetTransactionData.getAssetId());
try { try {
saveHelper.execute(this.repository); saveHelper.execute(this.repository);

View File

@ -114,7 +114,7 @@ public class AtTransaction extends Transaction {
return ValidationResult.ASSET_DOES_NOT_EXIST; return ValidationResult.ASSET_DOES_NOT_EXIST;
// Check asset amount is integer if asset is not divisible // Check asset amount is integer if asset is not divisible
if (!assetData.getIsDivisible() && amount % Amounts.MULTIPLIER != 0) if (!assetData.isDivisible() && amount % Amounts.MULTIPLIER != 0)
return ValidationResult.INVALID_AMOUNT; return ValidationResult.INVALID_AMOUNT;
Account sender = getATAccount(); Account sender = getATAccount();

View File

@ -76,7 +76,7 @@ public class CreateAssetOrderTransaction extends Transaction {
return ValidationResult.ASSET_DOES_NOT_EXIST; return ValidationResult.ASSET_DOES_NOT_EXIST;
// Unspendable assets are not tradable // Unspendable assets are not tradable
if (haveAssetData.getIsUnspendable() || wantAssetData.getIsUnspendable()) if (haveAssetData.isUnspendable() || wantAssetData.isUnspendable())
return ValidationResult.ASSET_NOT_SPENDABLE; return ValidationResult.ASSET_NOT_SPENDABLE;
Account creator = getCreator(); Account creator = getCreator();
@ -109,11 +109,11 @@ public class CreateAssetOrderTransaction extends Transaction {
} }
// Check amount is integer if amount's asset is not divisible // Check amount is integer if amount's asset is not divisible
if (!haveAssetData.getIsDivisible() && committedCost.mod(Amounts.MULTIPLIER_BI).signum() != 0) if (!haveAssetData.isDivisible() && committedCost.mod(Amounts.MULTIPLIER_BI).signum() != 0)
return ValidationResult.INVALID_AMOUNT; return ValidationResult.INVALID_AMOUNT;
// Check total return from fulfilled order would be integer if return's asset is not divisible // Check total return from fulfilled order would be integer if return's asset is not divisible
if (!wantAssetData.getIsDivisible() && maxOtherAmount.mod(Amounts.MULTIPLIER_BI).signum() != 0) if (!wantAssetData.isDivisible() && maxOtherAmount.mod(Amounts.MULTIPLIER_BI).signum() != 0)
return ValidationResult.INVALID_RETURN; return ValidationResult.INVALID_RETURN;
// Check order creator has enough asset balance AFTER removing fee, in case asset is QORT // Check order creator has enough asset balance AFTER removing fee, in case asset is QORT

View File

@ -113,11 +113,11 @@ public class DeployAtTransaction extends Transaction {
return ValidationResult.ASSET_DOES_NOT_EXIST; return ValidationResult.ASSET_DOES_NOT_EXIST;
// Unspendable assets are not valid // Unspendable assets are not valid
if (assetData.getIsUnspendable()) if (assetData.isUnspendable())
return ValidationResult.ASSET_NOT_SPENDABLE; return ValidationResult.ASSET_NOT_SPENDABLE;
// Check asset amount is integer if asset is not divisible // Check asset amount is integer if asset is not divisible
if (!assetData.getIsDivisible() && this.deployATTransactionData.getAmount() % Amounts.MULTIPLIER != 0) if (!assetData.isDivisible() && this.deployATTransactionData.getAmount() % Amounts.MULTIPLIER != 0)
return ValidationResult.INVALID_AMOUNT; return ValidationResult.INVALID_AMOUNT;
Account creator = this.getCreator(); Account creator = this.getCreator();

View File

@ -5,7 +5,6 @@ import java.util.List;
import org.qortal.account.Account; import org.qortal.account.Account;
import org.qortal.asset.Asset; import org.qortal.asset.Asset;
import org.qortal.crypto.Crypto;
import org.qortal.data.transaction.IssueAssetTransactionData; import org.qortal.data.transaction.IssueAssetTransactionData;
import org.qortal.data.transaction.TransactionData; import org.qortal.data.transaction.TransactionData;
import org.qortal.repository.DataException; import org.qortal.repository.DataException;
@ -19,7 +18,6 @@ public class IssueAssetTransaction extends Transaction {
// Properties // Properties
private IssueAssetTransactionData issueAssetTransactionData; private IssueAssetTransactionData issueAssetTransactionData;
private Account ownerAccount = null;
// Constructors // Constructors
@ -33,7 +31,7 @@ public class IssueAssetTransaction extends Transaction {
@Override @Override
public List<String> getRecipientAddresses() throws DataException { public List<String> getRecipientAddresses() throws DataException {
return Collections.singletonList(this.issueAssetTransactionData.getOwner()); return Collections.emptyList();
} }
// Navigation // Navigation
@ -42,21 +40,10 @@ public class IssueAssetTransaction extends Transaction {
return this.getCreator(); return this.getCreator();
} }
public Account getOwner() {
if (this.ownerAccount == null)
this.ownerAccount = new Account(this.repository, this.issueAssetTransactionData.getOwner());
return this.ownerAccount;
}
// Processing // Processing
@Override @Override
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
// Check owner address is valid
if (!Crypto.isValidAddress(this.issueAssetTransactionData.getOwner()))
return ValidationResult.INVALID_ADDRESS;
// Check name size bounds // Check name size bounds
int assetNameLength = Utf8.encodedLength(this.issueAssetTransactionData.getAssetName()); int assetNameLength = Utf8.encodedLength(this.issueAssetTransactionData.getAssetName());
if (assetNameLength < 1 || assetNameLength > Asset.MAX_NAME_SIZE) if (assetNameLength < 1 || assetNameLength > Asset.MAX_NAME_SIZE)
@ -78,7 +65,7 @@ public class IssueAssetTransaction extends Transaction {
return ValidationResult.INVALID_QUANTITY; return ValidationResult.INVALID_QUANTITY;
// Check quantity versus indivisibility // Check quantity versus indivisibility
if (!this.issueAssetTransactionData.getIsDivisible() && this.issueAssetTransactionData.getQuantity() % Amounts.MULTIPLIER != 0) if (!this.issueAssetTransactionData.isDivisible() && this.issueAssetTransactionData.getQuantity() % Amounts.MULTIPLIER != 0)
return ValidationResult.INVALID_QUANTITY; return ValidationResult.INVALID_QUANTITY;
Account issuer = getIssuer(); Account issuer = getIssuer();
@ -105,9 +92,9 @@ public class IssueAssetTransaction extends Transaction {
Asset asset = new Asset(this.repository, this.issueAssetTransactionData); Asset asset = new Asset(this.repository, this.issueAssetTransactionData);
asset.issue(); asset.issue();
// Add asset to owner // Add asset to issuer
Account owner = getOwner(); Account issuer = this.getIssuer();
owner.setConfirmedBalance(asset.getAssetData().getAssetId(), this.issueAssetTransactionData.getQuantity()); issuer.setConfirmedBalance(asset.getAssetData().getAssetId(), this.issueAssetTransactionData.getQuantity());
// Note newly assigned asset ID in our transaction record // Note newly assigned asset ID in our transaction record
this.issueAssetTransactionData.setAssetId(asset.getAssetData().getAssetId()); this.issueAssetTransactionData.setAssetId(asset.getAssetData().getAssetId());
@ -118,9 +105,9 @@ public class IssueAssetTransaction extends Transaction {
@Override @Override
public void orphan() throws DataException { public void orphan() throws DataException {
// Remove asset from owner // Remove asset from issuer
Account owner = getOwner(); Account issuer = this.getIssuer();
owner.deleteBalance(this.issueAssetTransactionData.getAssetId()); issuer.deleteBalance(this.issueAssetTransactionData.getAssetId());
// Deissue asset // Deissue asset
Asset asset = new Asset(this.repository, this.issueAssetTransactionData.getAssetId()); Asset asset = new Asset(this.repository, this.issueAssetTransactionData.getAssetId());

View File

@ -18,7 +18,6 @@ import com.google.common.primitives.Longs;
public class IssueAssetTransactionTransformer extends TransactionTransformer { public class IssueAssetTransactionTransformer extends TransactionTransformer {
// Property lengths // Property lengths
private static final int OWNER_LENGTH = ADDRESS_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH; private static final int NAME_SIZE_LENGTH = INT_LENGTH;
private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH; private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH;
private static final int QUANTITY_LENGTH = AMOUNT_LENGTH; private static final int QUANTITY_LENGTH = AMOUNT_LENGTH;
@ -26,7 +25,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
private static final int DATA_SIZE_LENGTH = INT_LENGTH; private static final int DATA_SIZE_LENGTH = INT_LENGTH;
private static final int IS_UNSPENDABLE_LENGTH = BOOLEAN_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 private static final int EXTRAS_LENGTH = NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + QUANTITY_LENGTH
+ IS_DIVISIBLE_LENGTH + DATA_SIZE_LENGTH + IS_UNSPENDABLE_LENGTH; + IS_DIVISIBLE_LENGTH + DATA_SIZE_LENGTH + IS_UNSPENDABLE_LENGTH;
protected static final TransactionLayout layout; protected static final TransactionLayout layout;
@ -38,7 +37,6 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
layout.add("transaction's groupID", TransformationType.INT); layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE); layout.add("reference", TransformationType.SIGNATURE);
layout.add("asset issuer's public key", TransformationType.PUBLIC_KEY); layout.add("asset issuer's public key", TransformationType.PUBLIC_KEY);
layout.add("asset owner", TransformationType.ADDRESS);
layout.add("asset name length", TransformationType.INT); layout.add("asset name length", TransformationType.INT);
layout.add("asset name", TransformationType.STRING); layout.add("asset name", TransformationType.STRING);
layout.add("asset description length", TransformationType.INT); layout.add("asset description length", TransformationType.INT);
@ -62,8 +60,6 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
byte[] issuerPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] issuerPublicKey = Serialization.deserializePublicKey(byteBuffer);
String owner = Serialization.deserializeAddress(byteBuffer);
String assetName = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_NAME_SIZE); String assetName = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_NAME_SIZE);
String description = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_DESCRIPTION_SIZE); String description = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_DESCRIPTION_SIZE);
@ -83,7 +79,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, issuerPublicKey, fee, signature); BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, issuerPublicKey, fee, signature);
return new IssueAssetTransactionData(baseTransactionData, owner, assetName, description, quantity, isDivisible, data, isUnspendable); return new IssueAssetTransactionData(baseTransactionData, assetName, description, quantity, isDivisible, data, isUnspendable);
} }
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
@ -103,18 +99,16 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
transformCommonBytes(transactionData, bytes); transformCommonBytes(transactionData, bytes);
Serialization.serializeAddress(bytes, issueAssetTransactionData.getOwner());
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getAssetName()); Serialization.serializeSizedString(bytes, issueAssetTransactionData.getAssetName());
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getDescription()); Serialization.serializeSizedString(bytes, issueAssetTransactionData.getDescription());
bytes.write(Longs.toByteArray(issueAssetTransactionData.getQuantity())); bytes.write(Longs.toByteArray(issueAssetTransactionData.getQuantity()));
bytes.write((byte) (issueAssetTransactionData.getIsDivisible() ? 1 : 0)); bytes.write((byte) (issueAssetTransactionData.isDivisible() ? 1 : 0));
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getData()); Serialization.serializeSizedString(bytes, issueAssetTransactionData.getData());
bytes.write((byte) (issueAssetTransactionData.getIsUnspendable() ? 1 : 0)); bytes.write((byte) (issueAssetTransactionData.isUnspendable() ? 1 : 0));
bytes.write(Longs.toByteArray(issueAssetTransactionData.getFee())); bytes.write(Longs.toByteArray(issueAssetTransactionData.getFee()));

View File

@ -41,7 +41,7 @@ public class AssetUtils {
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1; long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, AssetUtils.txGroupId, reference, account.getPublicKey(), AssetUtils.fee, null); BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, AssetUtils.txGroupId, reference, account.getPublicKey(), AssetUtils.fee, null);
TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, account.getAddress(), assetName, "desc", quantity, isDivisible, "{}", false); TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, assetName, "desc", quantity, isDivisible, "{}", false);
TransactionUtils.signAndMint(repository, transactionData, account); TransactionUtils.signAndMint(repository, transactionData, account);

View File

@ -14,7 +14,6 @@ public class IssueAssetTestTransaction extends TestTransaction {
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException { public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
Random random = new Random(); Random random = new Random();
String owner = account.getAddress();
String assetName = "test-asset-" + random.nextInt(1_000_000); String assetName = "test-asset-" + random.nextInt(1_000_000);
String description = "random test asset"; String description = "random test asset";
final long quantity = 1_000_000L; final long quantity = 1_000_000L;
@ -22,7 +21,7 @@ public class IssueAssetTestTransaction extends TestTransaction {
String data = AssetUtils.randomData(); String data = AssetUtils.randomData();
final boolean isUnspendable = false; final boolean isUnspendable = false;
return new IssueAssetTransactionData(generateBase(account), owner, assetName, description, quantity, isDivisible, data, isUnspendable); return new IssueAssetTransactionData(generateBase(account), assetName, description, quantity, isDivisible, data, isUnspendable);
} }
} }

View File

@ -434,7 +434,7 @@ public class GroupApprovalTests extends Common {
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1; long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, account.getPublicKey(), fee, null); BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, account.getPublicKey(), fee, null);
TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, account.getAddress(), "test asset", "test asset desc", 1000L, true, "{}", false); TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, "test asset", "test asset desc", 1000L, true, "{}", false);
return Transaction.fromData(repository, transactionData); return Transaction.fromData(repository, transactionData);
} }

View File

@ -50,9 +50,9 @@
"version": 4, "version": 4,
"timestamp": 0, "timestamp": 0,
"transactions": [ "transactions": [
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, { "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, { "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 }, { "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 }, { "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },

View File

@ -50,9 +50,9 @@
"version": 4, "version": 4,
"timestamp": 0, "timestamp": 0,
"transactions": [ "transactions": [
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, { "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, { "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" }, { "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" }, { "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },

View File

@ -50,9 +50,9 @@
"version": 4, "version": 4,
"timestamp": 0, "timestamp": 0,
"transactions": [ "transactions": [
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, { "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, { "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" }, { "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" }, { "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
@ -64,9 +64,9 @@
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 }, { "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
{ "type": "ISSUE_ASSET", "owner": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "issuerPublicKey": "C6wuddsBV3HzRrXUtezE7P5MoRXp5m3mEDokRDGZB6ry", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 }, { "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 }, { "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },

View File

@ -50,9 +50,9 @@
"version": 4, "version": 4,
"timestamp": 0, "timestamp": 0,
"transactions": [ "transactions": [
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, { "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, { "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" }, { "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" }, { "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
@ -64,9 +64,9 @@
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 }, { "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
{ "type": "ISSUE_ASSET", "owner": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "issuerPublicKey": "C6wuddsBV3HzRrXUtezE7P5MoRXp5m3mEDokRDGZB6ry", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 }, { "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 }, { "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },

View File

@ -50,9 +50,9 @@
"version": 4, "version": 4,
"timestamp": 0, "timestamp": 0,
"transactions": [ "transactions": [
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, { "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, { "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" }, { "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" }, { "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
@ -61,9 +61,9 @@
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 }, { "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "TEST", "description": "test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "TEST", "description": "test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 },
{ "type": "ISSUE_ASSET", "owner": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "issuerPublicKey": "C6wuddsBV3HzRrXUtezE7P5MoRXp5m3mEDokRDGZB6ry", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 },
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 }, { "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 },
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 }, { "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": "100" }, { "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": "100" },