Skip to content

Commit

Permalink
Make Block work as generic record
Browse files Browse the repository at this point in the history
  • Loading branch information
mikera committed Dec 2, 2024
1 parent c2e496b commit 14b54e2
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 96 deletions.
88 changes: 30 additions & 58 deletions convex-core/src/main/java/convex/core/cpos/Block.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -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<SignedData<ATransaction>> 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<SignedData<ATransaction>> transactions;

/**
* Comparator to sort blocks by timestamp
*/
Expand All @@ -55,27 +54,23 @@ public int compare(SignedData<Block> a, SignedData<Block> b) {
};

private Block(long timestamp, AVector<SignedData<ATransaction>> 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<ACell> 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);
if (Keywords.TRANSACTIONS.equals(k)) return transactions;
return null;
}

@Override
public Block updateRefs(IRefFunction func) {
AVector<SignedData<ATransaction>> newTransactions = transactions.updateRefs(func);
if (this.transactions == newTransactions) {
return this;
}
return new Block(timestamp, newTransactions);
}

/**
* Gets the timestamp of this block
*
Expand Down Expand Up @@ -117,7 +112,7 @@ public static Block create(long timestamp, AVector<SignedData<ATransaction>> tra
*/
@SafeVarargs
public static Block of(long timestamp, SignedData<ATransaction>... transactions) {
return new Block(timestamp, Vectors.of((Object[])transactions));
return new Block(timestamp, Vectors.create(transactions));
}

/**
Expand All @@ -126,42 +121,28 @@ public static Block of(long timestamp, SignedData<ATransaction>... 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;
}

/**
* Read a Block from a Blob encoding
* @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<SignedData<ATransaction>> transactions = Format.read(b,epos);
epos+=Cells.getEncodingLength(transactions);

Block result=Block.create(timestamp, transactions);
result.attachEncoding(b.slice(pos, epos));
AVector<ACell> 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;
}

Expand All @@ -170,18 +151,18 @@ public static Block read(Blob b, int pos) throws BadFormatException {
* @return Vector of transactions
*/
public AVector<SignedData<ATransaction>> 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
Expand All @@ -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 <R extends ACell> Ref<R> getRef(int i) {
return transactions.getRef(i);
}

@Override
public RecordFormat getFormat() {
return FORMAT;
protected ARecordGeneric withValues(AVector<ACell> newValues) {
if (values==newValues) return this;
return new Block(values);
}
}
75 changes: 39 additions & 36 deletions convex-core/src/main/java/convex/core/data/Format.java
Original file line number Diff line number Diff line change
Expand Up @@ -681,44 +681,47 @@ private static <T extends ACVMRecord> T readRecord(byte tag, Blob b, int pos) th

@SuppressWarnings("unchecked")
private static <T extends ACell> 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));
Expand Down
2 changes: 1 addition & 1 deletion convex-core/src/test/java/convex/core/data/BlocksTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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());

}
}
2 changes: 1 addition & 1 deletion convex-core/src/test/java/convex/store/EtchStoreTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<Ref<ACell>> noveltyHandler=r-> {
Expand Down

0 comments on commit 14b54e2

Please sign in to comment.