Search in sources :

Example 26 with AccumulatorState

use of com.radixdlt.ledger.AccumulatorState in project radixdlt by radixdlt.

the class LocalSyncServiceTest method createHeaderAtStateVersion.

private LedgerProof createHeaderAtStateVersion(long version) {
    final LedgerProof header = mock(LedgerProof.class);
    final AccumulatorState accumulatorState = mock(AccumulatorState.class);
    when(header.getAccumulatorState()).thenReturn(accumulatorState);
    when(accumulatorState.getStateVersion()).thenReturn(version);
    return header;
}
Also used : AccumulatorState(com.radixdlt.ledger.AccumulatorState) LedgerProof(com.radixdlt.hotstuff.LedgerProof) DtoLedgerProof(com.radixdlt.ledger.DtoLedgerProof)

Example 27 with AccumulatorState

use of com.radixdlt.ledger.AccumulatorState in project radixdlt by radixdlt.

the class TransactionsHandler method handleRequest.

@Override
public CommittedTransactionsResponse handleRequest(CommittedTransactionsRequest request) throws CoreApiException {
    coreModelMapper.verifyNetwork(request.getNetworkIdentifier());
    var stateIdentifier = coreModelMapper.partialStateIdentifier(request.getStateIdentifier());
    long stateVersion = stateIdentifier.getFirst();
    var accumulator = stateIdentifier.getSecond();
    var currentAccumulator = txnStore.getAccumulator(stateVersion).orElseThrow(() -> CoreApiException.notFound(coreModelMapper.notFoundErrorDetails(request.getStateIdentifier())));
    if (accumulator != null) {
        var matchesInput = accumulator.equals(currentAccumulator);
        if (!matchesInput) {
            throw CoreApiException.notFound(coreModelMapper.notFoundErrorDetails(request.getStateIdentifier()));
        }
    }
    var limit = coreModelMapper.limit(request.getLimit());
    var recoverable = txnStore.get(stateVersion, limit);
    var accumulatorState = new AccumulatorState(stateVersion, currentAccumulator);
    var response = new CommittedTransactionsResponse();
    var txns = ledgerEntryStore.getCommittedTxns(stateVersion, recoverable.size());
    for (int i = 0; i < txns.size(); i++) {
        var txn = txns.get(i);
        var recoveryInfo = recoverable.get(i);
        var nextAccumulatorState = ledgerAccumulator.accumulate(accumulatorState, txn.getId().asHashCode());
        accumulatorState = nextAccumulatorState;
        response.addTransactionsItem(construct(txn, recoveryInfo, nextAccumulatorState));
    }
    return response.stateIdentifier(new StateIdentifier().stateVersion(stateVersion).transactionAccumulator(Bytes.toHexString(currentAccumulator.asBytes())));
}
Also used : AccumulatorState(com.radixdlt.ledger.AccumulatorState) CommittedTransactionsResponse(com.radixdlt.api.core.openapitools.model.CommittedTransactionsResponse) StateIdentifier(com.radixdlt.api.core.openapitools.model.StateIdentifier)

Example 28 with AccumulatorState

use of com.radixdlt.ledger.AccumulatorState in project radixdlt by radixdlt.

the class TransactionsHandler method construct.

private CommittedTransaction construct(Txn txn, RecoverableProcessedTxn recoveryInfo, AccumulatorState accumulatorState) {
    var parser = radixEngineProvider.get().getParser();
    ParsedTxn parsedTxn;
    try {
        parsedTxn = parser.parse(txn);
    } catch (TxnParseException e) {
        throw new IllegalStateException("Could not parse already committed transaction", e);
    }
    var committedTransaction = new CommittedTransaction();
    recoveryInfo.recoverStateUpdates(parsedTxn).stream().map(stateUpdateGroup -> {
        var operationGroup = new OperationGroup();
        stateUpdateGroup.stream().map(stateUpdate -> {
            var substateOperation = stateUpdate.recover(radixEngineProvider);
            return coreModelMapper.operation(substateOperation.getSubstate(), substateOperation.getSubstateId(), substateOperation.isBootUp(), this::symbol);
        }).forEach(operationGroup::addOperationsItem);
        return operationGroup;
    }).forEach(committedTransaction::addOperationGroupsItem);
    var signedBy = parsedTxn.getPayloadHashAndSig().map(hashAndSig -> {
        var hash = hashAndSig.getFirst();
        var sig = hashAndSig.getSecond();
        return ECPublicKey.recoverFrom(hash, sig).orElseThrow(() -> new IllegalStateException("Invalid signature on already committed transaction"));
    });
    var transactionIdentifier = coreModelMapper.transactionIdentifier(txn.getId());
    return committedTransaction.committedStateIdentifier(coreModelMapper.stateIdentifier(accumulatorState)).metadata(new CommittedTransactionMetadata().fee(coreModelMapper.nativeTokenAmount(parsedTxn.getFeePaid())).message(parsedTxn.getMsg().map(Bytes::toHexString).orElse(null)).size(txn.getPayload().length).hex(Bytes.toHexString(txn.getPayload())).signedBy(signedBy.map(coreModelMapper::publicKey).orElse(null))).transactionIdentifier(transactionIdentifier);
}
Also used : SubstateTypeId(com.radixdlt.atom.SubstateTypeId) LedgerAndBFTProof(com.radixdlt.statecomputer.LedgerAndBFTProof) Inject(com.google.inject.Inject) RecoverableProcessedTxn(com.radixdlt.api.core.reconstruction.RecoverableProcessedTxn) StateIdentifier(com.radixdlt.api.core.openapitools.model.StateIdentifier) ECPublicKey(com.radixdlt.crypto.ECPublicKey) OperationGroup(com.radixdlt.api.core.openapitools.model.OperationGroup) ParsedTxn(com.radixdlt.engine.parser.ParsedTxn) CommittedTransaction(com.radixdlt.api.core.openapitools.model.CommittedTransaction) CoreJsonRpcHandler(com.radixdlt.api.core.CoreJsonRpcHandler) BerkeleyLedgerEntryStore(com.radixdlt.store.berkeley.BerkeleyLedgerEntryStore) SystemMapKey(com.radixdlt.constraintmachine.SystemMapKey) AccumulatorState(com.radixdlt.ledger.AccumulatorState) BerkeleyRecoverableProcessedTxnStore(com.radixdlt.api.core.reconstruction.BerkeleyRecoverableProcessedTxnStore) CoreModelMapper(com.radixdlt.api.core.model.CoreModelMapper) TokenResourceMetadata(com.radixdlt.application.tokens.state.TokenResourceMetadata) CoreApiException(com.radixdlt.api.core.model.CoreApiException) RadixEngine(com.radixdlt.engine.RadixEngine) Txn(com.radixdlt.atom.Txn) REAddr(com.radixdlt.identifiers.REAddr) CommittedTransactionsRequest(com.radixdlt.api.core.openapitools.model.CommittedTransactionsRequest) Provider(com.google.inject.Provider) Bytes(com.radixdlt.utils.Bytes) CommittedTransactionMetadata(com.radixdlt.api.core.openapitools.model.CommittedTransactionMetadata) CommittedTransactionsResponse(com.radixdlt.api.core.openapitools.model.CommittedTransactionsResponse) TxnParseException(com.radixdlt.engine.parser.exceptions.TxnParseException) LedgerAccumulator(com.radixdlt.ledger.LedgerAccumulator) OperationGroup(com.radixdlt.api.core.openapitools.model.OperationGroup) TxnParseException(com.radixdlt.engine.parser.exceptions.TxnParseException) CommittedTransactionMetadata(com.radixdlt.api.core.openapitools.model.CommittedTransactionMetadata) CommittedTransaction(com.radixdlt.api.core.openapitools.model.CommittedTransaction) ParsedTxn(com.radixdlt.engine.parser.ParsedTxn)

Example 29 with AccumulatorState

use of com.radixdlt.ledger.AccumulatorState in project radixdlt by radixdlt.

the class LargeEpochChangeTest method large_epoch.

@Test
public void large_epoch() throws Exception {
    var rt = Runtime.getRuntime();
    logger.info("max mem: {}MB", rt.maxMemory() / 1024 / 1024);
    int privKeyStart = 2;
    int numTxnsPerRound = 10;
    createInjector().injectMembers(this);
    // Arrange
    var request = TxnConstructionRequest.create();
    IntStream.range(privKeyStart, NUM_ROUNDS * numTxnsPerRound + privKeyStart).forEach(i -> {
        var k = PrivateKeys.ofNumeric(i);
        var addr = REAddr.ofPubKeyAccount(k.getPublicKey());
        request.action(new MintToken(REAddr.ofNativeToken(), addr, Amount.ofTokens(NUM_ROUNDS * 1000).toSubunits()));
        request.action(new RegisterValidator(k.getPublicKey()));
    });
    var mint = sut.construct(request).buildWithoutSignature();
    logger.info("mint_txn_size={}", mint.getPayload().length);
    var accumulator = new AccumulatorState(2, HashUtils.zero256());
    var proof = new LedgerProof(HashUtils.zero256(), LedgerHeader.create(1, View.of(1), accumulator, 0), new TimestampedECDSASignatures());
    sut.execute(List.of(mint), LedgerAndBFTProof.create(proof), PermissionLevel.SYSTEM);
    var systemConstruction = Stopwatch.createUnstarted();
    var construction = Stopwatch.createUnstarted();
    var signatures = Stopwatch.createUnstarted();
    var execution = Stopwatch.createUnstarted();
    var feesPaid = UInt256.ZERO;
    for (int round = 1; round <= NUM_ROUNDS; round++) {
        if (round % NUM_ROUNDS == 0) {
            logger.info("Staking txn {}/{} sys_construct_time: {}s user_construct_time: {}s sig_time: {}s" + " execute_time: {}s", round * (numTxnsPerRound + 1), NUM_ROUNDS * (numTxnsPerRound + 1), systemConstruction.elapsed(TimeUnit.SECONDS), construction.elapsed(TimeUnit.SECONDS), signatures.elapsed(TimeUnit.SECONDS), execution.elapsed(TimeUnit.SECONDS));
        }
        var txns = new ArrayList<Txn>();
        systemConstruction.start();
        var sysTxn = sut.construct(new NextRound(round, false, 1, v -> TEST_KEY.getPublicKey())).buildWithoutSignature();
        systemConstruction.stop();
        txns.add(sysTxn);
        for (int i = 0; i < numTxnsPerRound; i++) {
            var privateKey = PrivateKeys.ofNumeric((round - 1) * numTxnsPerRound + i + privKeyStart);
            var pubKey = privateKey.getPublicKey();
            var addr = REAddr.ofPubKeyAccount(privateKey.getPublicKey());
            construction.start();
            var builder = sut.construct(TxnConstructionRequest.create().feePayer(addr).action(new StakeTokens(addr, pubKey, Amount.ofTokens(100 + i).toSubunits())));
            construction.stop();
            signatures.start();
            var txn = builder.signAndBuild(privateKey::sign);
            signatures.stop();
            txns.add(txn);
        }
        var acc = new AccumulatorState(2 + round * (numTxnsPerRound + 1), HashUtils.zero256());
        var proof2 = new LedgerProof(HashUtils.zero256(), LedgerHeader.create(1, View.of(1), acc, 0), new TimestampedECDSASignatures());
        execution.start();
        var result = sut.execute(txns, LedgerAndBFTProof.create(proof2), PermissionLevel.SUPER_USER);
        execution.stop();
        for (var p : result.getProcessedTxns()) {
            feesPaid = feesPaid.add(p.getFeePaid());
        }
    }
    logger.info("total_fees_paid: {}", Amount.ofSubunits(feesPaid));
    // Act
    construction.reset();
    construction.start();
    logger.info("constructing epoch...");
    var txn = sut.construct(new NextEpoch(1)).buildWithoutSignature();
    construction.stop();
    logger.info("epoch_construction: size={}MB time={}s", txn.getPayload().length / 1024 / 1024, construction.elapsed(TimeUnit.SECONDS));
    construction.reset();
    construction.start();
    logger.info("preparing epoch...");
    var result = sut.transientBranch().execute(List.of(txn), PermissionLevel.SUPER_USER);
    sut.deleteBranches();
    var nextValidatorSet = result.getProcessedTxn().getEvents().stream().filter(REEvent.NextValidatorSetEvent.class::isInstance).map(REEvent.NextValidatorSetEvent.class::cast).findFirst().map(e -> BFTValidatorSet.from(e.nextValidators().stream().map(v -> BFTValidator.from(BFTNode.create(v.validatorKey()), v.amount()))));
    var stateUpdates = result.getProcessedTxn().stateUpdates().count();
    construction.stop();
    logger.info("epoch_preparation: state_updates={} verification_time={}s store_time={}s total_time={}s", stateUpdates, result.getVerificationTime() / 1000, result.getStoreTime() / 1000, construction.elapsed(TimeUnit.SECONDS));
    construction.reset();
    construction.start();
    logger.info("executing epoch...");
    var acc = new AccumulatorState(2 + 1 + NUM_ROUNDS * (1 + numTxnsPerRound), HashUtils.zero256());
    var header = LedgerHeader.create(1, View.of(10), acc, 0, nextValidatorSet.orElseThrow());
    var proof2 = new LedgerProof(HashUtils.zero256(), header, new TimestampedECDSASignatures());
    var executionResult = this.sut.execute(List.of(txn), LedgerAndBFTProof.create(proof2), PermissionLevel.SUPER_USER);
    construction.stop();
    logger.info("epoch_execution: verification_time={}s store_time={}s total_time={}s", executionResult.getVerificationTime() / 1000, executionResult.getStoreTime() / 1000, construction.elapsed(TimeUnit.SECONDS));
    for (var v : nextValidatorSet.orElseThrow().getValidators()) {
        logger.info("validator {} {}", v.getNode(), v.getPower());
    }
}
Also used : TimestampedECDSASignatures(com.radixdlt.hotstuff.TimestampedECDSASignatures) AccumulatorState(com.radixdlt.ledger.AccumulatorState) REEvent(com.radixdlt.constraintmachine.REEvent) ArrayList(java.util.ArrayList) LedgerProof(com.radixdlt.hotstuff.LedgerProof) Test(org.junit.Test)

Example 30 with AccumulatorState

use of com.radixdlt.ledger.AccumulatorState in project radixdlt by radixdlt.

the class ConsensusModuleTest method createNextVertex.

private Pair<QuorumCertificate, VerifiedVertex> createNextVertex(QuorumCertificate parent, BFTNode bftNode, Txn txn) {
    var unverifiedVertex = UnverifiedVertex.create(parent, View.of(1), List.of(txn), bftNode);
    var hash = hasher.hash(unverifiedVertex);
    var verifiedVertex = new VerifiedVertex(unverifiedVertex, hash);
    var next = new BFTHeader(View.of(1), verifiedVertex.getId(), LedgerHeader.create(1, View.of(1), new AccumulatorState(1, HashUtils.zero256()), 1));
    var voteData = new VoteData(next, parent.getProposed(), parent.getParent());
    var unsyncedQC = new QuorumCertificate(voteData, new TimestampedECDSASignatures(Map.of(bftNode, TimestampedECDSASignature.from(1, zeroSignature()))));
    return Pair.of(unsyncedQC, verifiedVertex);
}
Also used : VerifiedVertex(com.radixdlt.consensus.bft.VerifiedVertex) TimestampedECDSASignatures(com.radixdlt.consensus.TimestampedECDSASignatures) BFTHeader(com.radixdlt.consensus.BFTHeader) AccumulatorState(com.radixdlt.ledger.AccumulatorState) QuorumCertificate(com.radixdlt.consensus.QuorumCertificate) VoteData(com.radixdlt.consensus.VoteData)

Aggregations

AccumulatorState (com.radixdlt.ledger.AccumulatorState)33 Test (org.junit.Test)19 LedgerProof (com.radixdlt.hotstuff.LedgerProof)10 TimestampedECDSASignatures (com.radixdlt.hotstuff.TimestampedECDSASignatures)9 VerifiedVertex (com.radixdlt.hotstuff.bft.VerifiedVertex)7 ECKeyPair (com.radixdlt.crypto.ECKeyPair)6 RemoteEventDispatcher (com.radixdlt.environment.RemoteEventDispatcher)6 AbstractModule (com.google.inject.AbstractModule)5 TypeLiteral (com.google.inject.TypeLiteral)5 SystemCounters (com.radixdlt.counters.SystemCounters)5 SystemCountersImpl (com.radixdlt.counters.SystemCountersImpl)5 Hasher (com.radixdlt.crypto.Hasher)5 EventDispatcher (com.radixdlt.environment.EventDispatcher)5 WeightedRotatingLeaders (com.radixdlt.hotstuff.liveness.WeightedRotatingLeaders)5 LedgerUpdate (com.radixdlt.ledger.LedgerUpdate)5 Before (org.junit.Before)5 Inject (com.google.inject.Inject)4 VerifiedVertex (com.radixdlt.consensus.bft.VerifiedVertex)4 ScheduledEventDispatcher (com.radixdlt.environment.ScheduledEventDispatcher)4 BFTConfiguration (com.radixdlt.hotstuff.BFTConfiguration)4