From 674e4b5c4ceb6d031605c0b0f96a12e7e5f49168 Mon Sep 17 00:00:00 2001 From: Alexandra Roatis Date: Mon, 4 Nov 2019 16:46:11 -0500 Subject: [PATCH] AKI-509: Bugfix for block encoding/decoding inconsistency: - The bug: the seal method in StakingBlock was not updating the encoding with the sealer signature. - The fix: removed the lazy initialization of the encoding to avoid similar issues caused by other updates. --- .../aion/zero/impl/types/AbstractBlock.java | 3 - .../org/aion/zero/impl/types/AionBlock.java | 87 ++++------------- .../aion/zero/impl/types/StakingBlock.java | 94 ++++--------------- 3 files changed, 34 insertions(+), 150 deletions(-) diff --git a/modAionImpl/src/org/aion/zero/impl/types/AbstractBlock.java b/modAionImpl/src/org/aion/zero/impl/types/AbstractBlock.java index e6dc06b56f..9bff8a8c2b 100644 --- a/modAionImpl/src/org/aion/zero/impl/types/AbstractBlock.java +++ b/modAionImpl/src/org/aion/zero/impl/types/AbstractBlock.java @@ -35,8 +35,6 @@ public boolean isEqual(Block block) { public abstract String getShortDescr(); - abstract void parseRLP(); - /** * check if param block is son of this block * @@ -59,7 +57,6 @@ public byte[] getEncodedBody() { } List getBodyElements() { - parseRLP(); byte[] transactions = getTransactionsEncoded(); List body = new ArrayList<>(); body.add(transactions); diff --git a/modAionImpl/src/org/aion/zero/impl/types/AionBlock.java b/modAionImpl/src/org/aion/zero/impl/types/AionBlock.java index 866e4f0a93..03d2f7587b 100644 --- a/modAionImpl/src/org/aion/zero/impl/types/AionBlock.java +++ b/modAionImpl/src/org/aion/zero/impl/types/AionBlock.java @@ -21,8 +21,6 @@ public class AionBlock extends AbstractBlock { /* Private */ - private byte[] rlpEncoded; - private volatile boolean parsed = false; private A0BlockHeader header; /* Constructors */ @@ -35,15 +33,13 @@ public AionBlock(AionBlock block) { } this.header = A0BlockHeader.Builder.newInstance().withHeader(block.getHeader()).build(); this.transactionsList.addAll(block.getTransactionsList()); - this.parsed = true; } public AionBlock(byte[] rawData) { if (rawData == null) { throw new NullPointerException("RlpEncoded data is null"); } - - this.rlpEncoded = rawData; + parseRLP(rawData); } /** @@ -86,7 +82,6 @@ public AionBlock(A0BlockHeader header, List transactionsList) { this.header = header; this.transactionsList.clear(); this.transactionsList.addAll(transactionsList); - this.parsed = true; } @VisibleForTesting @@ -131,7 +126,6 @@ public AionBlock( this.header = builder.build(); this.transactionsList.clear(); this.transactionsList.addAll(transactionsList); - this.parsed = true; } /** @@ -191,30 +185,19 @@ protected AionBlock( .withDefaultSolution(); this.header = builder.build(); - this.parsed = true; } - void parseRLP() { - if (this.parsed) { - return; - } - - synchronized (this) { - if (this.parsed) return; + private void parseRLP(byte[] rawData) { + RLPList params = RLP.decode2(rawData); + RLPList block = (RLPList) params.get(0); - RLPList params = RLP.decode2(rlpEncoded); - RLPList block = (RLPList) params.get(0); - - // Parse Header - RLPList header = (RLPList) block.get(0); - this.header = A0BlockHeader.Builder.newInstance().withRlpList(header).build(); - - // Parse Transactions - RLPList txTransactions = (RLPList) block.get(1); - this.parseTxs(this.header.getTxTrieRoot(), txTransactions); + // Parse Header + RLPList header = (RLPList) block.get(0); + this.header = A0BlockHeader.Builder.newInstance().withRlpList(header).build(); - this.parsed = true; - } + // Parse Transactions + RLPList txTransactions = (RLPList) block.get(1); + this.parseTxs(this.header.getTxTrieRoot(), txTransactions); } @Override @@ -223,61 +206,51 @@ public int size() { } public A0BlockHeader getHeader() { - parseRLP(); return this.header; } @Override public byte[] getHash() { - parseRLP(); return this.header.getHash(); } @Override public byte[] getParentHash() { - parseRLP(); return this.header.getParentHash(); } @Override public AionAddress getCoinbase() { - parseRLP(); return this.header.getCoinbase(); } @Override public byte[] getStateRoot() { - parseRLP(); return this.header.getStateRoot(); } @Override public byte[] getTxTrieRoot() { - parseRLP(); return this.header.getTxTrieRoot(); } @Override public byte[] getReceiptsRoot() { - parseRLP(); return this.header.getReceiptsRoot(); } @Override public byte[] getLogBloom() { - parseRLP(); return this.header.getLogsBloom(); } @Override public byte[] getDifficulty() { - parseRLP(); return this.header.getDifficulty(); } @Override public BigInteger getDifficultyBI() { - parseRLP(); return this.header.getDifficultyBI(); } @@ -289,46 +262,29 @@ public void updateHeader(BlockHeader _header) { } header = (A0BlockHeader) _header; - - if (rlpEncoded == null) { - getEncoded(); - } - - byte[] headerEncoded = header.getEncoded(); - - List block = getBodyElements(); - block.add(0, headerEncoded); - byte[][] elements = block.toArray(new byte[block.size()][]); - - rlpEncoded = RLP.encodeList(elements); } @Override public long getTimestamp() { - parseRLP(); return this.header.getTimestamp(); } @Override public long getNumber() { - parseRLP(); return this.header.getNumber(); } @Override public byte[] getExtraData() { - parseRLP(); return this.header.getExtraData(); } public byte[] getNonce() { - parseRLP(); return this.header.getNonce(); } @Override public List getTransactionsList() { - parseRLP(); return transactionsList; } @@ -398,8 +354,6 @@ public void updateTransactionAndState( @Override public String toString() { StringBuilder toStringBuff = new StringBuilder(); - parseRLP(); - toStringBuff.setLength(0); toStringBuff.append("BlockData [ "); toStringBuff.append("hash=").append(ByteUtil.toHexString(this.getHash())).append("\n"); @@ -477,26 +431,22 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Arrays.hashCode(rlpEncoded); + return Arrays.hashCode(getEncoded()); } @Override public byte[] getEncoded() { - if (rlpEncoded == null) { - byte[] header = this.header.getEncoded(); + byte[] header = this.header.getEncoded(); - List block = getBodyElements(); - block.add(0, header); - byte[][] elements = block.toArray(new byte[block.size()][]); + List block = getBodyElements(); + block.add(0, header); + byte[][] elements = block.toArray(new byte[block.size()][]); - this.rlpEncoded = RLP.encodeList(elements); - } - return rlpEncoded; + return RLP.encodeList(elements); } @Override public String getShortHash() { - parseRLP(); return Hex.toHexString(getHash()).substring(0, 6); } @@ -514,13 +464,11 @@ public String getShortDescr() { @Override public long getNrgConsumed() { - parseRLP(); return this.header.getEnergyConsumed(); } @Override public long getNrgLimit() { - parseRLP(); return this.header.getEnergyLimit(); } @@ -529,7 +477,6 @@ public static AionBlock createBlockFromNetwork(A0BlockHeader header, byte[] body AionBlock block = new AionBlock(); block.header = header; - block.parsed = true; RLPList items = (RLPList) RLP.decode2(body).get(0); RLPList transactions = (RLPList) items.get(0); @@ -568,7 +515,6 @@ public static AionBlock fromRLP(byte[] rlpEncoded, boolean isUnsafe) { AionBlock block = new AionBlock(); block.header = header; - block.parsed = true; // Parse Transactions RLPList transactions = (RLPList) blockRLP.get(1); @@ -616,7 +562,6 @@ public static AionBlock fromRLPList(RLPList rlpEncoded) { AionBlock block = new AionBlock(); block.header = header; - block.parsed = true; // Parse Transactions RLPList transactions = (RLPList) rlpEncoded.get(1); diff --git a/modAionImpl/src/org/aion/zero/impl/types/StakingBlock.java b/modAionImpl/src/org/aion/zero/impl/types/StakingBlock.java index e9c5ea6404..c53412a321 100644 --- a/modAionImpl/src/org/aion/zero/impl/types/StakingBlock.java +++ b/modAionImpl/src/org/aion/zero/impl/types/StakingBlock.java @@ -20,8 +20,6 @@ public class StakingBlock extends AbstractBlock { /* Private */ - private byte[] rlpEncoded; - private volatile boolean parsed = false; private StakingBlockHeader header; /* Constructors */ @@ -35,15 +33,13 @@ public StakingBlock(StakingBlock block) { this.header = StakingBlockHeader.Builder.newInstance().withHeader(block.getHeader()).build(); this.transactionsList.addAll(block.getTransactionsList()); - this.parsed = true; } public StakingBlock(byte[] rawData) { if (rawData == null) { throw new NullPointerException("RlpEncoded data is null"); } - - this.rlpEncoded = rawData; + parseRLP(rawData); } /** @@ -63,7 +59,6 @@ public StakingBlock(StakingBlockHeader header, List transaction this.header = header; this.transactionsList.clear(); this.transactionsList.addAll(transactionsList); - this.parsed = true; } @VisibleForTesting @@ -125,7 +120,6 @@ public StakingBlock( this.header = builder.build(); this.transactionsList.clear(); this.transactionsList.addAll(transactionsList); - this.parsed = true; } /** @@ -186,40 +180,19 @@ protected StakingBlock( .withDefaultTxTrieRoot(); this.header = builder.build(); - this.parsed = true; - } - - void parseRLP() { - if (this.parsed) { - return; - } - - synchronized (this) { - if (this.parsed) return; - - RLPList params = RLP.decode2(rlpEncoded); - RLPList block = (RLPList) params.get(0); - - // Parse Header - RLPList header = (RLPList) block.get(0); - this.header = StakingBlockHeader.Builder.newInstance().withRlpList(header).build(); - - // Parse Transactions - RLPList txTransactions = (RLPList) block.get(1); - this.parseTxs(this.header.getTxTrieRoot(), txTransactions); - - this.parsed = true; - } } - private void updateRlpEncoded() { - byte[] headerRlpEncoded = header.getEncoded(); + private void parseRLP(byte[] rawData) { + RLPList params = RLP.decode2(rawData); + RLPList block = (RLPList) params.get(0); - List block = getBodyElements(); - block.add(0, headerRlpEncoded); - byte[][] elements = block.toArray(new byte[block.size()][]); + // Parse Header + RLPList header = (RLPList) block.get(0); + this.header = StakingBlockHeader.Builder.newInstance().withRlpList(header).build(); - rlpEncoded = RLP.encodeList(elements); + // Parse Transactions + RLPList txTransactions = (RLPList) block.get(1); + this.parseTxs(this.header.getTxTrieRoot(), txTransactions); } @Override @@ -228,90 +201,75 @@ public int size() { } public StakingBlockHeader getHeader() { - parseRLP(); return this.header; } @Override public byte[] getHash() { - parseRLP(); return this.header.getHash(); } @Override public byte[] getParentHash() { - parseRLP(); return this.header.getParentHash(); } @Override public AionAddress getCoinbase() { - parseRLP(); return this.header.getCoinbase(); } @Override public byte[] getStateRoot() { - parseRLP(); return this.header.getStateRoot(); } @Override public byte[] getTxTrieRoot() { - parseRLP(); return this.header.getTxTrieRoot(); } @Override public byte[] getReceiptsRoot() { - parseRLP(); return this.header.getReceiptsRoot(); } @Override public byte[] getLogBloom() { - parseRLP(); return this.header.getLogsBloom(); } @Override public byte[] getDifficulty() { - parseRLP(); return this.header.getDifficulty(); } @Override public BigInteger getDifficultyBI() { - parseRLP(); return this.header.getDifficultyBI(); } @Override public long getTimestamp() { - parseRLP(); return this.header.getTimestamp(); } @Override public long getNumber() { - parseRLP(); return this.header.getNumber(); } @Override public byte[] getExtraData() { - parseRLP(); return this.header.getExtraData(); } public byte[] getSeed() { - parseRLP(); return this.header.getSeed(); } @Override public List getTransactionsList() { - parseRLP(); return transactionsList; } @@ -382,7 +340,6 @@ public void updateTransactionAndState( @Override public String toString() { StringBuilder toStringBuff = new StringBuilder(); - parseRLP(); toStringBuff.setLength(0); toStringBuff.append(Hex.toHexString(this.getEncoded())).append("\n"); @@ -451,19 +408,21 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Arrays.hashCode(rlpEncoded); + return Arrays.hashCode(getEncoded()); } public byte[] getEncoded() { - if (rlpEncoded == null) { - updateRlpEncoded(); - } - return rlpEncoded; + byte[] headerRlpEncoded = header.getEncoded(); + + List block = getBodyElements(); + block.add(0, headerRlpEncoded); + byte[][] elements = block.toArray(new byte[block.size()][]); + + return RLP.encodeList(elements); } @Override public String getShortHash() { - parseRLP(); return Hex.toHexString(getHash()).substring(0, 6); } @@ -481,13 +440,11 @@ public String getShortDescr() { @Override public long getNrgConsumed() { - parseRLP(); return this.header.getEnergyConsumed(); } @Override public long getNrgLimit() { - parseRLP(); return this.header.getEnergyLimit(); } @@ -496,7 +453,6 @@ public static StakingBlock createBlockFromNetwork(StakingBlockHeader header, byt StakingBlock block = new StakingBlock(); block.header = header; - block.parsed = true; RLPList items = (RLPList) RLP.decode2(body).get(0); RLPList transactions = (RLPList) items.get(0); @@ -535,7 +491,6 @@ public static StakingBlock fromRLP(byte[] rlpEncoded, boolean isUnsafe) { StakingBlock block = new StakingBlock(); block.header = header; - block.parsed = true; // Parse Transactions RLPList transactions = (RLPList) blockRLP.get(1); @@ -575,18 +530,6 @@ public void updateHeader(BlockHeader _header) { } header = (StakingBlockHeader) _header; - - if (rlpEncoded == null) { - getEncoded(); - } - - byte[] headerEncoded = header.getEncoded(); - - List block = getBodyElements(); - block.add(0, headerEncoded); - byte[][] elements = block.toArray(new byte[block.size()][]); - - rlpEncoded = RLP.encodeList(elements); } public static StakingBlock fromRLPList(RLPList rlpEncoded) { @@ -605,7 +548,6 @@ public static StakingBlock fromRLPList(RLPList rlpEncoded) { StakingBlock block = new StakingBlock(); block.header = header; - block.parsed = true; // Parse Transactions RLPList transactions = (RLPList) rlpEncoded.get(1);