From 14b54e205e98d7f4acef5b748ffa39e75fcfc2be Mon Sep 17 00:00:00 2001 From: mikera Date: Mon, 2 Dec 2024 13:43:06 +0000 Subject: [PATCH] Make Block work as generic record --- .../src/main/java/convex/core/cpos/Block.java | 88 +++++++------------ .../main/java/convex/core/data/Format.java | 75 ++++++++-------- .../java/convex/core/data/BlocksTest.java | 2 +- .../test/java/convex/store/EtchStoreTest.java | 2 +- 4 files changed, 71 insertions(+), 96 deletions(-) diff --git a/convex-core/src/main/java/convex/core/cpos/Block.java b/convex-core/src/main/java/convex/core/cpos/Block.java index b752743a4..e1eed53fd 100644 --- a/convex-core/src/main/java/convex/core/cpos/Block.java +++ b/convex-core/src/main/java/convex/core/cpos/Block.java @@ -3,26 +3,24 @@ import java.util.Comparator; import java.util.List; -import convex.core.cvm.ACVMRecord; +import convex.core.cvm.ARecordGeneric; import convex.core.cvm.CVMTag; import convex.core.cvm.Keywords; import convex.core.cvm.RecordFormat; import convex.core.cvm.transactions.ATransaction; import convex.core.data.ACell; import convex.core.data.AVector; -import convex.core.data.AccountKey; import convex.core.data.Blob; import convex.core.data.Cells; -import convex.core.data.Format; import convex.core.data.Hash; -import convex.core.data.IRefFunction; import convex.core.data.Keyword; -import convex.core.data.Ref; import convex.core.data.SignedData; import convex.core.data.Vectors; import convex.core.data.prim.CVMLong; import convex.core.exceptions.BadFormatException; import convex.core.exceptions.InvalidDataException; +import convex.core.lang.RT; +import convex.core.util.ErrorMessages; import convex.core.util.Utils; /** @@ -36,13 +34,14 @@ * than any established style or system." - Bruce Lee * */ -public final class Block extends ACVMRecord { - private final long timestamp; - private final AVector> transactions; +public final class Block extends ARecordGeneric { private static final Keyword[] BLOCK_KEYS = new Keyword[] { Keywords.TIMESTAMP, Keywords.TRANSACTIONS}; private static final RecordFormat FORMAT = RecordFormat.of(BLOCK_KEYS); + private final long timestamp; + private AVector> transactions; + /** * Comparator to sort blocks by timestamp */ @@ -55,11 +54,16 @@ public int compare(SignedData a, SignedData b) { }; private Block(long timestamp, AVector> transactions) { - super(CVMTag.BLOCK,FORMAT.count()); + super(CVMTag.BLOCK,FORMAT,Vectors.create(CVMLong.create(timestamp),transactions)); this.timestamp = timestamp; this.transactions = transactions; } + public Block(AVector values) { + super(CVMTag.BLOCK,FORMAT,values); + this.timestamp=RT.ensureLong(values.get(0)).longValue(); + } + @Override public ACell get(Keyword k) { if (Keywords.TIMESTAMP.equals(k)) return CVMLong.create(timestamp); @@ -67,15 +71,6 @@ public ACell get(Keyword k) { return null; } - @Override - public Block updateRefs(IRefFunction func) { - AVector> newTransactions = transactions.updateRefs(func); - if (this.transactions == newTransactions) { - return this; - } - return new Block(timestamp, newTransactions); - } - /** * Gets the timestamp of this block * @@ -117,7 +112,7 @@ public static Block create(long timestamp, AVector> tra */ @SafeVarargs public static Block of(long timestamp, SignedData... transactions) { - return new Block(timestamp, Vectors.of((Object[])transactions)); + return new Block(timestamp, Vectors.create(transactions)); } /** @@ -126,26 +121,14 @@ public static Block of(long timestamp, SignedData... transactions) * @return Number of transactions on this block */ public int length() { - return Utils.checkedInt(transactions.count()); - } - - @Override - public int encode(byte[] bs, int pos) { - bs[pos++]=getTag(); - // generic record writeRaw, handles all fields in declared order - return encodeRaw(bs,pos); + return Utils.checkedInt(getTransactions().count()); } - @Override - public int encodeRaw(byte[] bs, int pos) { - pos = Utils.writeLong(bs,pos, timestamp); - pos = Format.write(bs, pos, transactions); - return pos; - } @Override public int estimatedEncodingSize() { - return 10+transactions.estimatedEncodingSize()+AccountKey.LENGTH; + // allow for embedded transaction, timestamp always small + return 160; } /** @@ -153,15 +136,13 @@ public int estimatedEncodingSize() { * @throws BadFormatException In event of encoding error */ public static Block read(Blob b, int pos) throws BadFormatException { - int epos=pos+1; // skip tag - long timestamp = b.longAt(epos); - epos+=8; - - AVector> transactions = Format.read(b,epos); - epos+=Cells.getEncodingLength(transactions); - - Block result=Block.create(timestamp, transactions); - result.attachEncoding(b.slice(pos, epos)); + AVector values=Vectors.read(b, pos); + int epos=pos+values.getEncodingLength(); + + if (values.count()!=BLOCK_KEYS.length) throw new BadFormatException(ErrorMessages.RECORD_VALUE_NUMBER); + + Block result=new Block(values); + result.attachEncoding(b.slice(pos,epos)); return result; } @@ -170,18 +151,18 @@ public static Block read(Blob b, int pos) throws BadFormatException { * @return Vector of transactions */ public AVector> getTransactions() { + if (transactions==null) transactions=RT.ensureVector(values.get(1)); return transactions; } @Override public boolean isCanonical() { - if (!transactions.isCanonical()) return false; return true; } @Override public void validateCell() throws InvalidDataException { - transactions.validateCell(); + // nothing to do } @Override @@ -206,22 +187,13 @@ public boolean equals(Block a) { if (ha!=null) return Cells.equals(h, ha); } - if (!(Cells.equals(transactions, a.transactions))) return false; + if (!(Cells.equals(values, a.values))) return false; return true; } @Override - public int getRefCount() { - return transactions.getRefCount(); - } - - @Override - public Ref getRef(int i) { - return transactions.getRef(i); - } - - @Override - public RecordFormat getFormat() { - return FORMAT; + protected ARecordGeneric withValues(AVector newValues) { + if (values==newValues) return this; + return new Block(values); } } diff --git a/convex-core/src/main/java/convex/core/data/Format.java b/convex-core/src/main/java/convex/core/data/Format.java index a74afe38b..911b8d411 100644 --- a/convex-core/src/main/java/convex/core/data/Format.java +++ b/convex-core/src/main/java/convex/core/data/Format.java @@ -681,44 +681,47 @@ private static T readRecord(byte tag, Blob b, int pos) th @SuppressWarnings("unchecked") private static T readDenseRecord(byte tag, Blob b, int pos) throws BadFormatException { - if (tag == CVMTag.INVOKE) { - return (T) Invoke.read(b,pos); - } else if (tag == CVMTag.TRANSFER) { - return (T) Transfer.read(b,pos); - } else if (tag == CVMTag.CALL) { - return (T) Call.read(b,pos); - } else if (tag == CVMTag.MULTI) { - return (T) Multi.read(b,pos); - } - - if (tag == CVMTag.STATE) { - return (T) State.read(b,pos); - } - - if (tag == CVMTag.BELIEF) { - return (T) Belief.read(b,pos); - } - - if (tag == CVMTag.BLOCK) { - return (T) Block.read(b,pos); - } - - if (tag == CVMTag.RESULT) { - return (T) Result.read(b,pos); - } - - if (tag == CVMTag.ORDER) { - return (T) Order.read(b,pos); - } - - if (tag == CVMTag.BLOCK_RESULT) { - return (T) BlockResult.read(b,pos); + try { + if (tag == CVMTag.INVOKE) { + return (T) Invoke.read(b,pos); + } else if (tag == CVMTag.TRANSFER) { + return (T) Transfer.read(b,pos); + } else if (tag == CVMTag.CALL) { + return (T) Call.read(b,pos); + } else if (tag == CVMTag.MULTI) { + return (T) Multi.read(b,pos); + } + + if (tag == CVMTag.STATE) { + return (T) State.read(b,pos); + } + + if (tag == CVMTag.BELIEF) { + return (T) Belief.read(b,pos); + } + + if (tag == CVMTag.BLOCK) { + return (T) Block.read(b,pos); + } + + if (tag == CVMTag.RESULT) { + return (T) Result.read(b,pos); + } + + if (tag == CVMTag.ORDER) { + return (T) Order.read(b,pos); + } + + if (tag == CVMTag.BLOCK_RESULT) { + return (T) BlockResult.read(b,pos); + } + + if (tag == CVMTag.PEER_STATUS) return (T) PeerStatus.read(b,pos); + if (tag == CVMTag.ACCOUNT_STATUS) return (T) AccountStatus.read(b,pos); + } catch (Exception e) { + // something failed, might be generic DenseRecord } - if (tag == CVMTag.PEER_STATUS) return (T) PeerStatus.read(b,pos); - if (tag == CVMTag.ACCOUNT_STATUS) return (T) AccountStatus.read(b,pos); - - // Might be a generic Dense Record DenseRecord dr=DenseRecord.read(tag,b,pos); if (dr==null) throw new BadFormatException(ErrorMessages.badTagMessage(tag)); diff --git a/convex-core/src/test/java/convex/core/data/BlocksTest.java b/convex-core/src/test/java/convex/core/data/BlocksTest.java index be2745c78..7a69437d6 100644 --- a/convex-core/src/test/java/convex/core/data/BlocksTest.java +++ b/convex-core/src/test/java/convex/core/data/BlocksTest.java @@ -57,7 +57,7 @@ public void testBlockRefs() { ATransaction t = Transfer.create(InitTest.HERO,0, InitTest.VILLAIN, 1000); Block b1 = Block.create(ts, Vectors.of(t,t,t)); - assertEquals(3,b1.getRefCount()); + assertEquals(2,b1.getRefCount()); } } diff --git a/convex-core/src/test/java/convex/store/EtchStoreTest.java b/convex-core/src/test/java/convex/store/EtchStoreTest.java index 138c29abe..c11ccbb2c 100644 --- a/convex-core/src/test/java/convex/store/EtchStoreTest.java +++ b/convex-core/src/test/java/convex/store/EtchStoreTest.java @@ -196,7 +196,7 @@ public void testBeliefAnnounce() throws IOException { assertEquals(3,Cells.refCount(t1)); assertEquals(4,Cells.refCount(t2)); - assertEquals(22,Refs.totalRefCount(belief)); + assertEquals(24,Refs.totalRefCount(belief)); Consumer> noveltyHandler=r-> {