From bb1a43d533c2a50d1fc3244fc711da2a7b3ec056 Mon Sep 17 00:00:00 2001 From: EunKi Yu Date: Mon, 10 Jul 2023 15:19:04 +0900 Subject: [PATCH] Fix bsc plato bmv bugs --- .../icon/btp/bmv/bsc/ChainConfig.java | 2 +- .../icon/btp/bmv/bsc/EthAddresses.java | 1 - bmv/bsc2/build.gradle | 2 - .../icon/btp/bmv/bsc2/BLSPublicKey.java | 2 +- .../icon/btp/bmv/bsc2/BLSSignature.java | 17 ------- .../icon/btp/bmv/bsc2/BTPMessageVerifier.java | 24 +++++----- .../icon/btp/bmv/bsc2/BlockProof.java | 6 +-- .../icon/btp/bmv/bsc2/BlockTree.java | 2 +- .../icon/btp/bmv/bsc2/BlockUpdate.java | 2 +- .../icon/btp/bmv/bsc2/ChainConfig.java | 7 --- .../icon/btp/bmv/bsc2/EthAddresses.java | 41 +---------------- .../icon/btp/bmv/bsc2/EventLog.java | 6 +-- .../foundation/icon/btp/bmv/bsc2/Hash.java | 2 +- .../foundation/icon/btp/bmv/bsc2/Header.java | 45 ++++++++++++------- .../icon/btp/bmv/bsc2/MessageEvent.java | 6 +-- .../icon/btp/bmv/bsc2/MessageProof.java | 4 +- .../foundation/icon/btp/bmv/bsc2/Receipt.java | 18 +++----- .../icon/btp/bmv/bsc2/ReceiptProof.java | 4 +- .../icon/btp/bmv/bsc2/RelayMessage.java | 8 +--- .../icon/btp/bmv/bsc2/Snapshot.java | 20 ++++----- .../icon/btp/bmv/bsc2/Validator.java | 4 +- .../icon/btp/bmv/bsc2/Validators.java | 20 ++++++++- .../icon/btp/bmv/bsc2/VoteAttestation.java | 25 ++--------- .../foundation/icon/btp/bmv/bsc2/Voters.java | 8 ++-- .../foundation/icon/btp/bmv/bsc2/BMVTest.java | 8 ---- 25 files changed, 104 insertions(+), 180 deletions(-) delete mode 100644 bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BLSSignature.java diff --git a/bmv/bsc/src/main/java/foundation/icon/btp/bmv/bsc/ChainConfig.java b/bmv/bsc/src/main/java/foundation/icon/btp/bmv/bsc/ChainConfig.java index 6092e011..c6d75aff 100644 --- a/bmv/bsc/src/main/java/foundation/icon/btp/bmv/bsc/ChainConfig.java +++ b/bmv/bsc/src/main/java/foundation/icon/btp/bmv/bsc/ChainConfig.java @@ -48,7 +48,7 @@ public static ChainConfig fromChainID(BigInteger cid) { return new ChainConfig(97L, 200L, 3L, 1010000L, 28196022L, 29295050L); } else if (cid.longValue() == 99L) { // Private BSC Testnet - return new ChainConfig(99L, 200L, 3L, 0L, 0L, 0L); + return new ChainConfig(99L, 200L, 3L, 0L, 0L, 6L); } Context.require(false, "No Chain Config - ChainID(" + cid.intValue() + ")"); diff --git a/bmv/bsc/src/main/java/foundation/icon/btp/bmv/bsc/EthAddresses.java b/bmv/bsc/src/main/java/foundation/icon/btp/bmv/bsc/EthAddresses.java index a1c8cade..981f6a66 100644 --- a/bmv/bsc/src/main/java/foundation/icon/btp/bmv/bsc/EthAddresses.java +++ b/bmv/bsc/src/main/java/foundation/icon/btp/bmv/bsc/EthAddresses.java @@ -16,7 +16,6 @@ package foundation.icon.btp.bmv.bsc; import foundation.icon.score.util.StringUtil; -import score.Context; import score.ObjectReader; import score.ObjectWriter; import scorex.util.ArrayList; diff --git a/bmv/bsc2/build.gradle b/bmv/bsc2/build.gradle index b5f5f7b1..403e0cac 100644 --- a/bmv/bsc2/build.gradle +++ b/bmv/bsc2/build.gradle @@ -3,7 +3,6 @@ version = '0.1.0' dependencies { compileOnly("foundation.icon:javaee-api:$javaeeVersion") implementation("foundation.icon:javaee-scorex:$scorexVersion") - implementation project(':score-util') implementation project(':lib') testImplementation("org.junit.jupiter:junit-jupiter-api:$jupiterVersion") @@ -20,7 +19,6 @@ dependencies { optimizedJar { dependsOn(project(':lib').jar) - dependsOn(project(':score-util').jar) mainClassName = 'foundation.icon.btp.bmv.bsc2.BTPMessageVerifier' archivesBaseName = 'bmv-bsc2' from { diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BLSPublicKey.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BLSPublicKey.java index 05e28d43..a9a65245 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BLSPublicKey.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BLSPublicKey.java @@ -7,7 +7,7 @@ public class BLSPublicKey { public static final int LENGTH = 48; - private byte[] data; + private final byte[] data; public BLSPublicKey(byte[] data) { Context.require(data.length == LENGTH, "Invalid bls public key"); diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BLSSignature.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BLSSignature.java deleted file mode 100644 index 139f596f..00000000 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BLSSignature.java +++ /dev/null @@ -1,17 +0,0 @@ -package foundation.icon.btp.bmv.bsc2; - -import score.Context; - -public class BLSSignature { - private byte[] sig; - - public BLSSignature(byte[] sig) { - Context.require(sig.length == 96, "Invalid bls signature length"); - this.sig = new byte[96]; - System.arraycopy(sig, 0, this.sig, 0, 96); - } - - public void verify(byte[] msg, byte[] aggr) { - Context.verifySignature("bls12-381-g2", msg, sig, aggr); - } -} diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BTPMessageVerifier.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BTPMessageVerifier.java index 4148abcf..6c5bdb27 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BTPMessageVerifier.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BTPMessageVerifier.java @@ -46,7 +46,6 @@ public BTPMessageVerifier(Address _bmc, BigInteger _chainId, byte[] _header, ChainConfig config = ChainConfig.fromChainID(_chainId); Header head = Header.fromBytes(_header); - // Context.require(config.isEpoch(head.getNumber()), "No epoch block"); verify(config, head); MerkleTreeAccumulator mta = new MerkleTreeAccumulator(); @@ -68,8 +67,8 @@ public BTPMessageVerifier(Address _bmc, BigInteger _chainId, byte[] _header, this.tree.set(new BlockTree(head.getHash())); this.mta.set(mta); this.heads.set(head.getHash().toBytes(), head); - // TODO attestation shouldn't be null VoteAttestation attestation = head.getVoteAttestation(config); + Context.require(attestation != null, "No vote attestation"); this.snap.set(new Snapshot( head.getHash(), head.getNumber(), @@ -131,7 +130,6 @@ private List
handleBlockUpdate(ChainConfig config, BlockUpdate bu, Block if (newHeads.isEmpty()) { return new ArrayList<>(); } - List ancestors = tree.getStem(newHeads.get(0).getParentHash()); Context.require(ancestors.size() > 0, "Inconsistent block"); @@ -169,6 +167,13 @@ private List
handleBlockUpdate(ChainConfig config, BlockUpdate bu, Block } this.snap.set(snaps.get(finality)); + + // ascending ordered finalized heads + List
finalities = collect(heads, tree.getRoot(), finality); + for (Header head : finalities) { + mta.add(head.getHash().toBytes()); + } + tree.prune(finality, new BlockTree.OnRemoveListener() { @Override public void onRemove(Hash node) { @@ -191,12 +196,6 @@ public void onRemove(Hash node) { for (Header newHead : newHeads) { this.heads.set(newHead.getHash().toBytes(), newHead); } - - // ascending ordered finalized heads - List
finalities = collect(heads, tree.getRoot(), finality); - for (Header head : finalities) { - mta.add(head.getHash().toBytes()); - } return finalities; } @@ -363,7 +362,6 @@ private Hash getFinalizedBlockHash(ChainConfig config, Map heads, Context.require(snaps.get(range.getSourceHash()) != null, "Unknown justified block hash"); return range.getSourceHash(); } - //snap = snaps.get(range.getSourceHash()); snap = snaps.get(head.getParentHash()); head = heads.get(head.getParentHash()); } @@ -407,10 +405,10 @@ private List toSortedList(byte[][] addrs) { private static List
collect(Map heads, Hash from, Hash to) { List
cols = new ArrayList<>(); - Header head = heads.get(from); - while (!head.getHash().equals(to)) { + Header head = heads.get(to); + while (!head.getHash().equals(from)) { cols.add(head); - head = heads.get(head.getHash()); + head = heads.get(head.getParentHash()); Context.require(head != null, "Inconsistent chain"); } reverse(cols); diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockProof.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockProof.java index 1ac0e6e7..5576069e 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockProof.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockProof.java @@ -23,9 +23,9 @@ import java.util.List; public class BlockProof { - private Header header; - private BigInteger height; - private byte[][] witness; + private final Header header; + private final BigInteger height; + private final byte[][] witness; public BlockProof(Header header, BigInteger height, byte[][] witness) { this.header = header; diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockTree.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockTree.java index 89af6c2f..5b7f9ef6 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockTree.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockTree.java @@ -29,7 +29,7 @@ public class BlockTree { private Hash root; - private Map> nodes; + private final Map> nodes; public BlockTree(Hash root) { this.root = root; diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockUpdate.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockUpdate.java index 52d6d5db..9dcb73bf 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockUpdate.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/BlockUpdate.java @@ -23,7 +23,7 @@ import java.util.List; public class BlockUpdate { - private List
headers; + private final List
headers; public BlockUpdate(List
headers) { this.headers = Collections.unmodifiableList(headers); diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/ChainConfig.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/ChainConfig.java index 020b59fd..e724c270 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/ChainConfig.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/ChainConfig.java @@ -54,11 +54,4 @@ public boolean isEpoch(BigInteger number) { return number.longValue() % this.Epoch == 0; } - public boolean isRamanujan(BigInteger number) { - return number.longValue() >= this.RamanujanBlock; - } - - public boolean isPlanck(BigInteger number) { - return this.PlanckBlock <= number.longValue(); - } } diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/EthAddresses.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/EthAddresses.java index 5dd03e0d..33a28325 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/EthAddresses.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/EthAddresses.java @@ -15,7 +15,6 @@ */ package foundation.icon.btp.bmv.bsc2; -import foundation.icon.score.util.StringUtil; import score.Context; import score.ObjectReader; import score.ObjectWriter; @@ -24,22 +23,12 @@ import java.util.List; public class EthAddresses { - private List addresses; + private final List addresses; - public EthAddresses(EthAddress[] addresses) { - this.addresses = new ArrayList<>(List.of(addresses)); - } public EthAddresses(List addresses) { this.addresses = addresses; } - public EthAddresses(byte[][] addresses) { - this.addresses = new ArrayList<>(); - for (int i = 0; i < addresses.length; i++) { - this.addresses.add(new EthAddress(StringUtil.bytesToHex(addresses[i]))); - } - } - public EthAddresses(EthAddresses o) { this.addresses = new ArrayList<>(o.addresses); } @@ -52,15 +41,6 @@ public EthAddress[] toArray() { return addresses; } - public static EthAddresses fromString(String o) { - List tokens = StringUtil.tokenize(o, ','); - List addresses = new ArrayList<>(); - for (String token : tokens) { - addresses.add(EthAddress.of(token)); - } - return new EthAddresses(addresses); - } - public EthAddress get(int i) { return addresses.get(i); } @@ -77,10 +57,6 @@ public EthAddress remove(int i) { return addresses.remove(i); } - public EthAddresses subList(int from, int to) { - return new EthAddresses(addresses.subList(from, to)); - } - public int size() { return addresses.size(); } @@ -114,21 +90,6 @@ public static void writeObject(ObjectWriter w, EthAddresses o) { w.end(); } - public static void sort(EthAddress[] a) { - int len = a.length; - for (int i = 0; i < len; i++) { - EthAddress v = a[i]; - for (int j = i+1; j < len; j++) { - if (v.compareTo(a[j]) > 0) { - EthAddress t = v; - v = a[j]; - a[j] = t; - } - } - a[i] = v; - } - } - public static void sort(List a) { int len = a.size(); for (int i = 0; i < len; i++) { diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/EventLog.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/EventLog.java index d4b6e126..d316833f 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/EventLog.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/EventLog.java @@ -22,9 +22,9 @@ import java.util.List; public class EventLog { - private EthAddress address; - private List topics; - private byte[] data; + private final EthAddress address; + private final List topics; + private final byte[] data; public EventLog(EthAddress address, List topics, byte[] data) { this.address = address; diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Hash.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Hash.java index c3d811e2..bf7b7982 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Hash.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Hash.java @@ -24,7 +24,7 @@ public class Hash { public static final Hash EMPTY = new Hash(new byte[32]); - private byte[] data; + private final byte[] data; public Hash(byte[] data) { this.data = data; diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Header.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Header.java index 62537220..893cadaf 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Header.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Header.java @@ -19,9 +19,11 @@ import score.Context; import score.ObjectReader; import score.ObjectWriter; +import scorex.util.ArrayList; import java.math.BigInteger; import java.util.Arrays; +import java.util.List; public class Header { public static final int EXTRA_VANITY = 32; @@ -36,21 +38,21 @@ public class Header { public static final BigInteger MAX_GAS_LIMIT = BigInteger.valueOf(0x7FFFFFFFFFFFFFFFL); // (2^63-1) public static final BigInteger MIN_GAS_LIMIT = BigInteger.valueOf(5000L); - private Hash parentHash; - private Hash uncleHash; - private EthAddress coinbase; - private Hash root; - private Hash txHash; - private Hash receiptHash; - private byte[] bloom; - private BigInteger difficulty; - private BigInteger number; - private BigInteger gasLimit; - private BigInteger gasUsed; - private long time; - private byte[] extra; - private Hash mixDigest; - private byte[] nonce; + private final Hash parentHash; + private final Hash uncleHash; + private final EthAddress coinbase; + private final Hash root; + private final Hash txHash; + private final Hash receiptHash; + private final byte[] bloom; + private final BigInteger difficulty; + private final BigInteger number; + private final BigInteger gasLimit; + private final BigInteger gasUsed; + private final long time; + private final byte[] extra; + private final Hash mixDigest; + private final byte[] nonce; // caches private Hash hashCache; @@ -141,7 +143,17 @@ public Hash getHash() { public Validators getValidators(ChainConfig config) { if (valsCache == null) { - valsCache = Validators.fromBytes(getValidatorBytes(config)); + List validators = new ArrayList<>(); + byte[] b = getValidatorBytes(config); + int n = b.length / VALIDATOR_BYTES_LENGTH; + for (int i = 0; i < n; i++) { + byte[] consensus = Arrays.copyOfRange(b, i * VALIDATOR_BYTES_LENGTH, + i * VALIDATOR_BYTES_LENGTH + EthAddress.LENGTH); + byte[] vote = Arrays.copyOfRange(b, i * VALIDATOR_BYTES_LENGTH + EthAddress.LENGTH, + (i + 1) * VALIDATOR_BYTES_LENGTH); + validators.add(new Validator(new EthAddress(consensus), new BLSPublicKey(vote))); + } + valsCache = new Validators(validators); } return valsCache; } @@ -166,7 +178,6 @@ public byte[] getValidatorBytes(ChainConfig config) { public VoteAttestation getVoteAttestation(ChainConfig config) { if (extra.length <= EXTRA_VANITY + EXTRA_SEAL) { - Context.println("No vote attestation - height(" + number.intValue() + ")"); return null; } diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/MessageEvent.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/MessageEvent.java index a0456ad7..63ef273e 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/MessageEvent.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/MessageEvent.java @@ -26,9 +26,9 @@ public class MessageEvent { // keccak256("Message(string,uint256,bytes)") public static final Hash SIGNATURE = Hash.of("37be353f216cf7e33639101fd610c542e6a0c0109173fa1c1d8b04d34edb7c1b"); - private BTPAddress next; - private BigInteger sequence; - private byte[] message; + private final BTPAddress next; + private final BigInteger sequence; + private final byte[] message; public MessageEvent(BTPAddress next, BigInteger sequence, byte[] message) { this.next = next; diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/MessageProof.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/MessageProof.java index 5eda0e94..e39ee373 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/MessageProof.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/MessageProof.java @@ -24,8 +24,8 @@ public class MessageProof { // block hash - private Hash id; - private List proofs; + private final Hash id; + private final List proofs; public MessageProof(Hash id, List proofs) { this.id = id; diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Receipt.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Receipt.java index 789e81a3..e86f0396 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Receipt.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Receipt.java @@ -25,24 +25,20 @@ public class Receipt { public static final int StatusFailed = 0; - private byte[] postStatusOrState; - private BigInteger cumulativeGasUsed; - private byte[] bloom; - private List logs; + private final byte[] postStatusOrState; + private final List logs; - public Receipt(byte[] postStatusOrState, BigInteger cumulativeGasUsed, - byte[] bloom, List logs) { + public Receipt(byte[] postStatusOrState, + List logs) { this.postStatusOrState = postStatusOrState; - this.cumulativeGasUsed = cumulativeGasUsed; - this.bloom = bloom; this.logs = Collections.unmodifiableList(logs); } public static Receipt readObject(ObjectReader r) { r.beginList(); byte[] postStatusOrState = r.readByteArray(); - BigInteger cumulativeGasUsed = r.readBigInteger(); - byte[] bloom = r.readByteArray(); + r.readBigInteger(); + r.readByteArray(); r.beginList(); List logs = new ArrayList<>(); while(r.hasNext()) { @@ -50,7 +46,7 @@ public static Receipt readObject(ObjectReader r) { } r.end(); r.end(); - return new Receipt(postStatusOrState, cumulativeGasUsed, bloom, logs); + return new Receipt(postStatusOrState, logs); } public static Receipt fromBytes(byte[] bytes) { diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/ReceiptProof.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/ReceiptProof.java index 4da01586..2135ddd1 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/ReceiptProof.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/ReceiptProof.java @@ -22,8 +22,8 @@ import java.util.List; public class ReceiptProof { - private byte[] key; // transaction index encoded with rlp - private byte[][] proof; // merkle proof + private final byte[] key; // transaction index encoded with rlp + private final byte[][] proof; // merkle proof private ReceiptProof(byte[] key, byte[][] proof) { this.key = key; diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/RelayMessage.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/RelayMessage.java index 78f5a202..1be08db3 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/RelayMessage.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/RelayMessage.java @@ -27,7 +27,7 @@ import java.util.List; public class RelayMessage { - private List tpms; + private final List tpms; public RelayMessage(List tpms) { this.tpms = Collections.unmodifiableList(tpms); @@ -127,12 +127,6 @@ public static void writeObject(ObjectWriter w, TypePrefixedMessage o) { w.end(); } - public byte[] toBytes() { - ByteArrayObjectWriter w = Context.newByteArrayObjectWriter("RLP"); - writeObject(w, this); - return w.toByteArray(); - } - @Override public String toString() { return "TypePrefixedMessage{" + diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Snapshot.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Snapshot.java index cbb5c208..17cc1385 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Snapshot.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Snapshot.java @@ -22,12 +22,12 @@ import java.math.BigInteger; public class Snapshot { - private Hash hash; - private BigInteger number; - private Validators validators; - private Validators candidates; - private EthAddresses recents; - private VoteAttestation attestation; + private final Hash hash; + private final BigInteger number; + private final Validators validators; + private final Validators candidates; + private final EthAddresses recents; + private final VoteAttestation attestation; public Snapshot(Hash hash, BigInteger number, Validators validators, Validators candidates, EthAddresses recents, VoteAttestation attestation) { @@ -74,12 +74,13 @@ public Snapshot apply(ChainConfig config, Header head) { Hash newHash = head.getHash(); BigInteger newNumber = head.getNumber(); Context.require(number.longValue() + 1L == newNumber.longValue() - && hash.equals(head.getParentHash()), "Inconsistent header"); + && hash.equals(head.getParentHash()), "Inconsistent block number"); + Context.require(hash.equals(head.getParentHash()), "Inconsistent block hash"); // ensure the coinbase is sealer EthAddress sealer = head.getCoinbase(); - // TODO Check authority - // TODO Check recently sealer + Context.require(validators.contains(sealer), "UnauthorizedValidator"); + Context.require(!recents.contains(sealer), "RecentlySigned"); Validators newValidators = newNumber.longValue() % config.Epoch == validators.size() / 2 ? candidates : validators; @@ -99,7 +100,6 @@ public Snapshot apply(ChainConfig config, Header head) { } else { newAttestation = attestation; } - // TODO recent fork hashes...? return new Snapshot(head.getHash(), newNumber, newValidators, newCandidates, newRecents, newAttestation); } diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Validator.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Validator.java index f0ee71f5..414e8f27 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Validator.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Validator.java @@ -4,8 +4,8 @@ import score.ObjectWriter; public class Validator { - private EthAddress address; - private BLSPublicKey pubkey; + private final EthAddress address; + private final BLSPublicKey pubkey; public Validator(EthAddress address, BLSPublicKey pubkey) { this.address = address; diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Validators.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Validators.java index b151f6df..0127d156 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Validators.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Validators.java @@ -8,7 +8,7 @@ import java.util.List; public class Validators { - private List validators; + private final List validators; public Validators(List validators) { this.validators = validators; @@ -60,6 +60,24 @@ public boolean contains(Validator validator) { return validators.contains(validator); } + public boolean contains(EthAddress address) { + for (Validator validator : validators) { + if (validator.getAddress().equals(address)) { + return true; + } + } + return false; + } + + public boolean contains(BLSPublicKey pubkey) { + for (Validator validator : validators) { + if (validator.getPublicKey().equals(pubkey)) { + return true; + } + } + return false; + } + public int size() { return validators.size(); } diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/VoteAttestation.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/VoteAttestation.java index 67ed3925..5e3e5a40 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/VoteAttestation.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/VoteAttestation.java @@ -8,14 +8,7 @@ import java.math.BigInteger; import java.util.List; -import static foundation.icon.btp.bmv.bsc2.BLSPublicKey.LENGTH; - public class VoteAttestation { - - private final String ERR_INVALID_VOTER_COUNT = "Invalid attestation, vote number larger than validators number"; - private final String ERR_SHORT_QUORUM = "Invalid attestation, not enough votes"; - - public static final int MAX_EXTRA_LENGTH = 256; public static final int BLS_SIG_LENGTH = 96; private final Voters voters; private final byte[] signature; @@ -39,9 +32,6 @@ public static VoteAttestation readObject(ObjectReader r) { byte[] bitset = new byte[1]; bitset[0] = r.readByte(); Voters voters = new Voters(bitset); - // TODO - //r.read(Voters.class); - //new Voters(r.readByteArray()); byte[] signature = r.readByteArray(); Context.require(signature.length == BLS_SIG_LENGTH, "Invalid signature"); VoteRange range = r.read(VoteRange.class); @@ -52,8 +42,6 @@ public static VoteAttestation readObject(ObjectReader r) { public static void writeObject(ObjectWriter w, VoteAttestation o) { w.beginList(4); - // TODO - //o.voters. w.write(o.voters.bitset[0]); w.write(o.signature); w.write(o.range); @@ -65,11 +53,6 @@ public VoteRange getVoteRange() { return range; } - // TODO - // public byte[] getExtra() { - // return Utils.copy(this.extra); - // } - public boolean isSourceOf(BigInteger number, Hash hash) { return range.getSourceNumber().compareTo(number) == 0 && range.getSourceHash().equals(hash); } @@ -84,7 +67,7 @@ public void verify(Validators validators) { } public byte[] aggregate(Validators validators) { - Context.require(voters.count() <= validators.size(), ERR_INVALID_VOTER_COUNT); + Context.require(voters.count() <= validators.size(), "Invalid vote - larger than validators"); List keys = new ArrayList<>(); for (int i = 0; i < validators.size(); i++) { @@ -93,11 +76,11 @@ public byte[] aggregate(Validators validators) { } keys.add(validators.get(i).getPublicKey()); } - Context.require(keys.size() >= Utils.ceilDiv(validators.size() * 2, 3), ERR_SHORT_QUORUM); + Context.require(keys.size() >= Utils.ceilDiv(validators.size() * 2, 3), "Short quorum"); byte[] aggregation = null; - for (int i = 0; i < keys.size(); i++) { - aggregation = Context.aggregate("bls12-381-g1", aggregation, keys.get(i).toBytes()); + for (BLSPublicKey key : keys) { + aggregation = Context.aggregate("bls12-381-g1", aggregation, key.toBytes()); } return aggregation; } diff --git a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Voters.java b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Voters.java index 8374b135..68d4dd52 100644 --- a/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Voters.java +++ b/bmv/bsc2/src/main/java/foundation/icon/btp/bmv/bsc2/Voters.java @@ -12,16 +12,14 @@ public class Voters { public Voters(byte[] bitset) { Context.require(bitset.length <= BITSET_BYTES_LENGTH, "Invalid bitset size"); this.bitset = new byte[8]; - for (int i = 0; i < bitset.length; i++) { - this.bitset[i] = bitset[i]; - } + System.arraycopy(bitset, 0, this.bitset, 0, bitset.length); } public int count() { int cnt = 0; - for (int i = 0; i < bitset.length; i++) { + for (byte b : bitset) { for (int j = 0; j < 8; j++) { - if ((bitset[i] >> j & 1) == 1) { + if ((b >> j & 1) == 1) { cnt++; } } diff --git a/bmv/bsc2/src/test/java/foundation/icon/btp/bmv/bsc2/BMVTest.java b/bmv/bsc2/src/test/java/foundation/icon/btp/bmv/bsc2/BMVTest.java index 4c0bb319..00cbea13 100644 --- a/bmv/bsc2/src/test/java/foundation/icon/btp/bmv/bsc2/BMVTest.java +++ b/bmv/bsc2/src/test/java/foundation/icon/btp/bmv/bsc2/BMVTest.java @@ -6,7 +6,6 @@ import com.iconloop.score.test.TestBase; import foundation.icon.btp.lib.BMVStatus; import foundation.icon.btp.lib.BTPAddress; -import foundation.icon.score.util.StringUtil; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; @@ -22,13 +21,6 @@ public class BMVTest extends TestBase { static final Account BMC = sm.createAccount(Integer.MAX_VALUE); static final BTPAddress BMC_BTP_ADDR = BTPAddress.parse("btp://0x1.icon/cx123"); - // public static Score deployBmv(DataSource.Case.Deployment params) throws Exception { - // return sm.deploy(sm.createAccount(), BTPMessageVerifier.class, - // BMC.getAddress(), params.getChainId(), StringUtil.hexToBytes(params.getHeader()), - // DataSource.Case.Deployment.toBytesArray(params.getRecents()), - // DataSource.Case.Deployment.toBytesArray(params.getValidators())); - // } - public static Score deployBmv(DataSource.Case.Deployment deployment) throws Exception { return sm.deploy(sm.createAccount(), BTPMessageVerifier.class, BMC.getAddress(), deployment.getChainId(), deployment.getHeader(),