forked from Qortal/qortal
Committed stashed code that is functional but probably too messy for production use.
Online account nonces are appended to the onlineAccountsSignatures to avoid the need for a new field, but it probably makes more sense to separate them.
This commit is contained in:
parent
fbcc870d36
commit
46c40ca9ca
@ -10,7 +10,6 @@ import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
@ -90,7 +89,8 @@ public class Block {
|
||||
ONLINE_ACCOUNT_UNKNOWN(71),
|
||||
ONLINE_ACCOUNT_SIGNATURES_MISSING(72),
|
||||
ONLINE_ACCOUNT_SIGNATURES_MALFORMED(73),
|
||||
ONLINE_ACCOUNT_SIGNATURE_INCORRECT(74);
|
||||
ONLINE_ACCOUNT_SIGNATURE_INCORRECT(74),
|
||||
ONLINE_ACCOUNT_NONCE_INCORRECT(75);
|
||||
|
||||
public final int value;
|
||||
|
||||
@ -409,6 +409,31 @@ public class Block {
|
||||
}
|
||||
}
|
||||
|
||||
// Add nonces to the end of the online accounts signatures if mempow is active
|
||||
if (timestamp >= BlockChain.getInstance().getOnlineAccountsMemoryPoWTimestamp()) {
|
||||
try {
|
||||
// Create ordered list of nonce values
|
||||
List<Integer> nonces = new ArrayList<>();
|
||||
for (int i = 0; i < onlineAccountsCount; ++i) {
|
||||
Integer accountIndex = accountIndexes.get(i);
|
||||
OnlineAccountData onlineAccountData = indexedOnlineAccounts.get(accountIndex);
|
||||
nonces.add(onlineAccountData.getNonce());
|
||||
}
|
||||
|
||||
// Encode the nonces to a byte array
|
||||
byte[] encodedNonces = BlockTransformer.encodeOnlineAccountNonces(nonces);
|
||||
|
||||
// Append the encoded nonces to the encoded online account signatures
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
outputStream.write(onlineAccountsSignatures);
|
||||
outputStream.write(encodedNonces);
|
||||
onlineAccountsSignatures = outputStream.toByteArray();
|
||||
}
|
||||
catch (TransformationException | IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] minterSignature = minter.sign(BlockTransformer.getBytesForMinterSignature(parentBlockData,
|
||||
minter.getPublicKey(), encodedOnlineAccounts));
|
||||
|
||||
@ -1016,12 +1041,15 @@ public class Block {
|
||||
if (this.blockData.getOnlineAccountsSignatures() == null || this.blockData.getOnlineAccountsSignatures().length == 0)
|
||||
return ValidationResult.ONLINE_ACCOUNT_SIGNATURES_MISSING;
|
||||
|
||||
if (this.blockData.getTimestamp() >= BlockChain.getInstance().getAggregateSignatureTimestamp()) {
|
||||
// We expect just the one, aggregated signature
|
||||
if (this.blockData.getOnlineAccountsSignatures().length != Transformer.SIGNATURE_LENGTH)
|
||||
final int signaturesLength = (this.blockData.getTimestamp() >= BlockChain.getInstance().getAggregateSignatureTimestamp()) ? Transformer.SIGNATURE_LENGTH : onlineRewardShares.size() * Transformer.SIGNATURE_LENGTH;
|
||||
final int noncesLength = onlineRewardShares.size() * Transformer.INT_LENGTH;
|
||||
|
||||
if (this.blockData.getTimestamp() >= BlockChain.getInstance().getOnlineAccountsMemoryPoWTimestamp()) {
|
||||
// We expect nonces to be appended to the online accounts signatures
|
||||
if (this.blockData.getOnlineAccountsSignatures().length != signaturesLength + noncesLength)
|
||||
return ValidationResult.ONLINE_ACCOUNT_SIGNATURES_MALFORMED;
|
||||
} else {
|
||||
if (this.blockData.getOnlineAccountsSignatures().length != onlineRewardShares.size() * Transformer.SIGNATURE_LENGTH)
|
||||
if (this.blockData.getOnlineAccountsSignatures().length != signaturesLength)
|
||||
return ValidationResult.ONLINE_ACCOUNT_SIGNATURES_MALFORMED;
|
||||
}
|
||||
|
||||
@ -1029,8 +1057,37 @@ public class Block {
|
||||
long onlineTimestamp = this.blockData.getOnlineAccountsTimestamp();
|
||||
byte[] onlineTimestampBytes = Longs.toByteArray(onlineTimestamp);
|
||||
|
||||
byte[] encodedOnlineAccountSignatures = this.blockData.getOnlineAccountsSignatures();
|
||||
|
||||
// Split online account signatures into signature(s) + nonces, then validate the nonces
|
||||
if (this.blockData.getTimestamp() >= BlockChain.getInstance().getOnlineAccountsMemoryPoWTimestamp()) {
|
||||
byte[] extractedSignatures = BlockTransformer.extract(encodedOnlineAccountSignatures, 0, signaturesLength);
|
||||
byte[] extractedNonces = BlockTransformer.extract(encodedOnlineAccountSignatures, signaturesLength, onlineRewardShares.size() * Transformer.INT_LENGTH);
|
||||
encodedOnlineAccountSignatures = extractedSignatures;
|
||||
|
||||
List<Integer> nonces = BlockTransformer.decodeOnlineAccountNonces(extractedNonces);
|
||||
|
||||
// Build block's view of online accounts (without signatures, as we don't need them here)
|
||||
Set<OnlineAccountData> onlineAccounts = new HashSet<>();
|
||||
for (int i = 0; i < onlineRewardShares.size(); ++i) {
|
||||
Integer nonce = nonces.get(i);
|
||||
byte[] publicKey = onlineRewardShares.get(i).getRewardSharePublicKey();
|
||||
|
||||
OnlineAccountData onlineAccountData = new OnlineAccountData(onlineTimestamp, null, publicKey, nonce);
|
||||
onlineAccounts.add(onlineAccountData);
|
||||
}
|
||||
|
||||
// Remove those already validated & cached by online accounts manager - no need to re-validate them
|
||||
OnlineAccountsManager.getInstance().removeKnown(onlineAccounts, onlineTimestamp);
|
||||
|
||||
// Validate the rest
|
||||
for (OnlineAccountData onlineAccount : onlineAccounts)
|
||||
if (!OnlineAccountsManager.getInstance().verifyMemoryPoW(onlineAccount, this.blockData.getTimestamp()))
|
||||
return ValidationResult.ONLINE_ACCOUNT_NONCE_INCORRECT;
|
||||
}
|
||||
|
||||
// Extract online accounts' timestamp signatures from block data. Only one signature if aggregated.
|
||||
List<byte[]> onlineAccountsSignatures = BlockTransformer.decodeTimestampSignatures(this.blockData.getOnlineAccountsSignatures());
|
||||
List<byte[]> onlineAccountsSignatures = BlockTransformer.decodeTimestampSignatures(encodedOnlineAccountSignatures);
|
||||
|
||||
if (this.blockData.getTimestamp() >= BlockChain.getInstance().getAggregateSignatureTimestamp()) {
|
||||
// Aggregate all public keys
|
||||
|
@ -478,4 +478,44 @@ public class BlockTransformer extends Transformer {
|
||||
return signatures;
|
||||
}
|
||||
|
||||
public static byte[] encodeOnlineAccountNonces(List<Integer> nonces) throws TransformationException {
|
||||
try {
|
||||
final int length = nonces.size() * Transformer.INT_LENGTH;
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream(length);
|
||||
|
||||
for (int i = 0; i < nonces.size(); ++i) {
|
||||
Integer nonce = nonces.get(i);
|
||||
if (nonce == null || nonce < 0) {
|
||||
throw new TransformationException("Unable to serialize online account nonces due to invalid value");
|
||||
}
|
||||
bytes.write(Ints.toByteArray(nonce));
|
||||
}
|
||||
|
||||
return bytes.toByteArray();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new TransformationException("Unable to serialize online account nonces", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Integer> decodeOnlineAccountNonces(byte[] encodedNonces) {
|
||||
List<Integer> nonces = new ArrayList<>();
|
||||
|
||||
ByteBuffer bytes = ByteBuffer.wrap(encodedNonces);
|
||||
final int count = encodedNonces.length / Transformer.INT_LENGTH;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
Integer nonce = bytes.getInt();
|
||||
nonces.add(nonce);
|
||||
}
|
||||
|
||||
return nonces;
|
||||
}
|
||||
|
||||
public static byte[] extract(byte[] input, int pos, int length) {
|
||||
byte[] output = new byte[length];
|
||||
System.arraycopy(input, pos, output, 0, length);
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -72,7 +72,7 @@
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
"timestamp": "1593450000000",
|
||||
"timestamp": "1656777099000",
|
||||
"transactions": [
|
||||
{ "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORTAL coin", "quantity": 0, "isDivisible": true, "data": "{}" },
|
||||
{ "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||
|
@ -361,7 +361,7 @@ public class BlockArchiveTests extends Common {
|
||||
assertEquals(0, repository.getBlockArchiveRepository().getBlockArchiveHeight());
|
||||
|
||||
// Write blocks 2-900 to the archive (using bulk method)
|
||||
int fileSizeTarget = 425000; // Pre-calculated size of 900 blocks
|
||||
int fileSizeTarget = 428600; // Pre-calculated size of 900 blocks
|
||||
assertTrue(HSQLDBDatabaseArchiving.buildBlockArchive(repository, fileSizeTarget));
|
||||
|
||||
// Ensure the block archive height has increased
|
||||
@ -455,7 +455,7 @@ public class BlockArchiveTests extends Common {
|
||||
assertEquals(0, repository.getBlockArchiveRepository().getBlockArchiveHeight());
|
||||
|
||||
// Write blocks 2-900 to the archive (using bulk method)
|
||||
int fileSizeTarget = 42000; // Pre-calculated size of approx 90 blocks
|
||||
int fileSizeTarget = 42360; // Pre-calculated size of approx 90 blocks
|
||||
assertTrue(HSQLDBDatabaseArchiving.buildBlockArchive(repository, fileSizeTarget));
|
||||
|
||||
// Ensure 10 archive files have been created
|
||||
|
Loading…
Reference in New Issue
Block a user