use of com.radixdlt.atom.Txn in project radixdlt by radixdlt.
the class Pacemaker method generateProposal.
private Optional<Proposal> generateProposal(View view) {
final HighQC highQC = this.latestViewUpdate.getHighQC();
final QuorumCertificate highestQC = highQC.highestQC();
final List<Txn> nextTxns;
// TODO: Remove isEndOfEpoch knowledge from consensus
if (highestQC.getProposed().getLedgerHeader().isEndOfEpoch()) {
nextTxns = List.of();
} else {
final List<PreparedVertex> preparedVertices = vertexStore.getPathFromRoot(highestQC.getProposed().getVertexId());
nextTxns = nextTxnsGenerator.generateNextTxns(view, preparedVertices);
systemCounters.add(SystemCounters.CounterType.BFT_PACEMAKER_PROPOSED_TRANSACTIONS, nextTxns.size());
}
final UnverifiedVertex proposedVertex = UnverifiedVertex.create(highestQC, view, nextTxns, self);
final VerifiedVertex verifiedVertex = new VerifiedVertex(proposedVertex, hasher.hash(proposedVertex));
return safetyRules.signProposal(verifiedVertex, highQC.highestCommittedQC(), highQC.highestTC());
}
use of com.radixdlt.atom.Txn in project radixdlt by radixdlt.
the class BerkeleyLedgerEntryStore method getNextCommittedTxns.
@Override
public VerifiedTxnsAndProof getNextCommittedTxns(DtoLedgerProof start) {
long stateVersion = start.getLedgerHeader().getAccumulatorState().getStateVersion();
final var startTime = System.nanoTime();
com.sleepycat.je.Transaction txn = beginTransaction();
final LedgerProof nextHeader;
try (var proofCursor = proofDatabase.openCursor(txn, null)) {
final var headerSearchKey = toPKey(stateVersion + 1);
final var headerValue = entry();
var headerCursorStatus = proofCursor.getSearchKeyRange(headerSearchKey, headerValue, DEFAULT);
if (headerCursorStatus != SUCCESS) {
return null;
}
nextHeader = deserializeOrElseFail(headerValue.getData(), LedgerProof.class);
} finally {
txn.commit();
}
final var txns = ImmutableList.<Txn>builder();
final var atomSearchKey = toPKey(stateVersion + 1);
final var atomPosData = entry();
try (var txnCursor = txnDatabase.openCursor(null, null)) {
int atomCount = (int) (nextHeader.getStateVersion() - stateVersion);
int count = 0;
var atomCursorStatus = txnCursor.getSearchKeyRange(atomSearchKey, atomPosData, DEFAULT);
do {
if (atomCursorStatus != SUCCESS) {
throw new BerkeleyStoreException("Atom database search failure");
}
var offset = fromByteArray(atomPosData.getData());
var txnBytes = txnLog.read(offset);
txns.add(Txn.create(txnBytes));
atomCursorStatus = txnCursor.getNext(atomSearchKey, atomPosData, DEFAULT);
count++;
} while (count < atomCount);
return VerifiedTxnsAndProof.create(txns.build(), nextHeader);
} catch (IOException e) {
throw new BerkeleyStoreException("Unable to read from atom store.", e);
} finally {
addTime(startTime, CounterType.ELAPSED_BDB_LEDGER_ENTRIES, CounterType.COUNT_BDB_LEDGER_ENTRIES);
}
}
use of com.radixdlt.atom.Txn in project radixdlt by radixdlt.
the class BerkeleyLedgerEntryStore method getCommittedTxns.
public List<Txn> getCommittedTxns(long stateVersion, long limit) {
try (var txnCursor = txnDatabase.openCursor(null, null)) {
var iterator = new Iterator<Txn>() {
final DatabaseEntry key = new DatabaseEntry(Longs.toByteArray(stateVersion + 1));
final DatabaseEntry value = new DatabaseEntry();
OperationStatus status = txnCursor.get(key, value, Get.SEARCH, null) != null ? SUCCESS : OperationStatus.NOTFOUND;
@Override
public boolean hasNext() {
return status == SUCCESS;
}
@Override
public Txn next() {
if (status != SUCCESS) {
throw new NoSuchElementException();
}
var offset = fromByteArray(value.getData());
byte[] txnBytes;
try {
txnBytes = txnLog.read(offset);
} catch (IOException e) {
throw new IllegalStateException("Unable to read transaction", e);
}
Txn next = Txn.create(txnBytes);
status = txnCursor.getNext(key, value, null);
return next;
}
};
return Streams.stream(iterator).limit(limit).onClose(txnCursor::close).toList();
}
}
use of com.radixdlt.atom.Txn in project radixdlt by radixdlt.
the class ConsensusToLedgerCommittedInvariant method check.
@Override
public Observable<TestInvariantError> check(RunningNetwork network) {
BehaviorSubject<Set<Txn>> committedTxns = BehaviorSubject.create();
Disposable d = network.ledgerUpdates().<Set<Txn>>scan(new HashSet<>(), (set, next) -> {
set.addAll(next.getSecond().getNewTxns());
return set;
}).subscribe(committedTxns::onNext);
return Observable.<BFTCommittedUpdate>create(emitter -> commits.addListener((node, event) -> emitter.onNext(event), BFTCommittedUpdate.class)).serialize().concatMap(committedUpdate -> Observable.fromStream(committedUpdate.committed().stream().flatMap(PreparedVertex::successfulCommands))).flatMapMaybe(txn -> committedTxns.filter(cmdSet -> cmdSet.contains(txn.txn())).timeout(10, TimeUnit.SECONDS).firstOrError().ignoreElement().onErrorReturn(e -> new TestInvariantError("Committed command in vertex has not been inserted into the ledger" + " after 10 seconds"))).doFinally(d::dispose);
}
use of com.radixdlt.atom.Txn in project radixdlt by radixdlt.
the class LedgerInOrderInvariant method check.
@Override
public Observable<TestInvariantError> check(RunningNetwork network) {
Map<BFTNode, List<Txn>> commandsPerNode = new HashMap<>();
network.getNodes().forEach(n -> commandsPerNode.put(n, new ArrayList<>()));
return network.ledgerUpdates().flatMap(nodeAndCommand -> {
BFTNode node = nodeAndCommand.getFirst();
LedgerUpdate ledgerUpdate = nodeAndCommand.getSecond();
List<Txn> nodeTxns = commandsPerNode.get(node);
nodeTxns.addAll(ledgerUpdate.getNewTxns());
return commandsPerNode.values().stream().filter(list -> nodeTxns != list).filter(list -> list.size() >= nodeTxns.size()).findFirst().flatMap(list -> {
if (Collections.indexOfSubList(list, nodeTxns) != 0) {
TestInvariantError err = new TestInvariantError("Two nodes don't agree on commands: " + list + " " + nodeTxns);
return Optional.of(Observable.just(err));
}
return Optional.empty();
}).orElse(Observable.empty());
});
}
Aggregations