Skip to content
Permalink
Browse files

Version 518. Corrected transaction-validation issue.

  • Loading branch information...
n-y-z-o committed May 14, 2019
1 parent c1d1c77 commit 53509ee81c00b0ac22e0d18334cff3dc66c8853e
@@ -458,7 +458,7 @@ public static Block fromByteBuffer(ByteBuffer buffer, boolean validateTransactio
int numberOfTransactions = buffer.getInt();
List<Transaction> transactions = new ArrayList<>();
for (int i = 0; i < numberOfTransactions; i++) {
transactions.add(Transaction.fromByteBuffer(buffer));
transactions.add(Transaction.fromByteBuffer(buffer, blockHeight, previousBlockHash));
}

byte[] balanceListHash = new byte[FieldByteSize.hash];
@@ -249,22 +249,10 @@ public static synchronized void requestMissingFrozenBlocks() {
frozenBlockRequestHeight = maximumHeightToRequest + 1L;
}

// Send the request for all heights from the minimum to maximum.
for (long height = minimumHeightToRequest; height <= maximumHeightToRequest; height++) {
Message message = new Message(MessageType.BlockRequest11, new BlockRequest(height, height, false));
Message.fetchFromRandomNode(message, new MessageCallback() {
@Override
public void responseReceived(Message message) {

if (message != null && message.getContent() instanceof BlockResponse) {
BlockResponse response = (BlockResponse) message.getContent();
for (Block block : response.getBlocks()) {
UnfrozenBlockManager.registerBlock(block);
}
}
}
});
}
// Send the request.
Message message = new Message(MessageType.BlockRequest11, new BlockRequest(minimumHeightToRequest,
maximumHeightToRequest, false));
Message.fetchFromRandomNode(message, null);
}
}
}
@@ -269,6 +269,11 @@ public int getByteSize(boolean forSigning) {

public static Transaction fromByteBuffer(ByteBuffer buffer) {

return fromByteBuffer(buffer, 0, new byte[FieldByteSize.hash]);
}

public static Transaction fromByteBuffer(ByteBuffer buffer, long transactionHeight, byte[] previousHashInChain) {

// These are the fields contained in all transactions.
byte type = buffer.get();
long timestamp = buffer.getLong();
@@ -282,7 +287,8 @@ public static Transaction fromByteBuffer(ByteBuffer buffer) {
transaction = coinGenerationTransaction(timestamp, amount, recipientIdentifier);
} else if (type == typeSeed || type == typeStandard) {
long previousHashHeight = buffer.getLong();
Block previousHashBlock = BlockManager.frozenBlockForHeight(previousHashHeight);
Block previousHashBlock = previousHashBlockForHeight(previousHashHeight, transactionHeight,
previousHashInChain);
byte[] previousBlockHash = previousHashBlock == null ? new byte[FieldByteSize.hash] :
previousHashBlock.getHash();
byte[] senderIdentifier = new byte[FieldByteSize.identifier];
@@ -308,6 +314,28 @@ public static Transaction fromByteBuffer(ByteBuffer buffer) {
return transaction;
}

private static Block previousHashBlockForHeight(long hashHeight, long transactionHeight,
byte[] previousHashInChain) {

// First, try to get a frozen block. If one is not available, and the height referenced is past the frozen edge,
// try to get a block on the branch leading to this transaction.
Block block = BlockManager.frozenBlockForHeight(hashHeight);
if (block == null && hashHeight > BlockManager.getFrozenEdgeHeight()) {
Block previousBlock = UnfrozenBlockManager.unverifiedBlockAtHeight(transactionHeight - 1,
previousHashInChain);
while (previousBlock != null && previousBlock.getBlockHeight() > hashHeight) {
previousBlock = UnfrozenBlockManager.unverifiedBlockAtHeight(previousBlock.getBlockHeight() - 1,
previousBlock.getPreviousBlockHash());
}

if (previousBlock != null && previousBlock.getBlockHeight() == hashHeight) {
block = previousBlock;
}
}

return block;
}

public boolean performInitialValidation(StringBuilder validationError, StringBuilder validationWarning) {

// As its name indicates, this method performs initial validation of transactions so users know when a
@@ -33,13 +33,6 @@ public static void attemptToRegisterDisconnectedBlocks() {
registerBlock(block);
}
}

// Remove lower heights that may have been skipped.
for (long height : new HashSet<>(disconnectedBlocks.keySet())) {
if (height <= frozenEdgeHeight) {
disconnectedBlocks.remove(height);
}
}
}

public static boolean registerBlock(Block block) {
@@ -390,6 +383,13 @@ public static void performMaintenance() {
}
}

// Remove disconnected blocks at or below the new frozen edge.
for (long height : new HashSet<>(disconnectedBlocks.keySet())) {
if (height <= frozenEdgeHeight) {
disconnectedBlocks.remove(height);
}
}

// Remove threshold overrides at or below the new frozen edge.
for (Long height : new HashSet<>(thresholdOverrides.keySet())) {
if (height <= frozenEdgeHeight) {
@@ -462,7 +462,7 @@ public static Block unfrozenBlockAtHeight(long height, byte[] hash) {
return blockAtHeight(height, hash, unfrozenBlocks);
}

private static Block unverifiedBlockAtHeight(long height, byte[] hash) {
public static Block unverifiedBlockAtHeight(long height, byte[] hash) {

// If the unfrozen block is not available, look to the disconnected block map. These blocks, importantly, have
// not passed the same level of local vetting at the unfrozen blocks, as we have not yet been able to
@@ -2,7 +2,7 @@

public class Version {

private static final int version = 517;
private static final int version = 518;

public static int getVersion() {

@@ -141,15 +141,15 @@ public static BlockResponse fromByteBuffer(ByteBuffer buffer) {
}

List<Block> blocks = new ArrayList<>();
int numberOfBlocks = buffer.getShort() & 0xffff;
int numberOfBlocks = Math.min(buffer.getShort() & 0xffff, 10);
for (int i = 0; i < numberOfBlocks; i++) {
blocks.add(Block.fromByteBuffer(buffer));
Block block = Block.fromByteBuffer(buffer);
blocks.add(block);
UnfrozenBlockManager.registerBlock(block);
}

result = new BlockResponse(initialBalanceList, blocks);
} catch (Exception ignored) {
ignored.printStackTrace();
}
} catch (Exception ignored) { }

return result;
}
@@ -7,10 +7,7 @@
import co.nyzo.verifier.util.ThreadUtil;
import co.nyzo.verifier.util.UpdateUtil;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
@@ -352,7 +349,7 @@ public void responseReceived(Message message) {
BlockResponse blockResponse = (BlockResponse) message.getContent();
List<Block> blocks = blockResponse.getBlocks();
if (blocks.size() > 0 && blocks.get(0).getBlockHeight() == startHeightToFetch &&
blocks.get(blocks.size() - 1).getBlockHeight() == endHeightToFetch) {
blocks.get(blocks.size() - 1).getBlockHeight() == endHeightToFetch) {
blockList.addAll(blocks);
}
} catch (Exception ignored) { }
@@ -373,6 +370,10 @@ public void responseReceived(Message message) {
}
lastBlockReceivedTimestamp.set(System.currentTimeMillis());

// Perform maintenance on the unfrozen block manager. Blocks are automatically registered with the manager
// in block requests, so they must be periodically removed to prevent problems.
UnfrozenBlockManager.performMaintenance();

// Four consecutive successes activate fast-fetch mode unless we are very close to the open edge. The
// interval between fetches is less than the block duration, so multiple consecutive successful fetches
// typically indicate that we need to catch up.

0 comments on commit 53509ee

Please sign in to comment.
You can’t perform that action at this time.