Skip to content
This repository has been archived by the owner on Feb 19, 2024. It is now read-only.

Feature/stake cleanup #168

Merged
merged 18 commits into from
Apr 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.google.inject.TypeLiteral;
import com.google.inject.multibindings.MapBinder;
import com.google.inject.multibindings.Multibinder;
import com.radixdlt.api.construction.ConstructionController;
import com.radixdlt.client.store.berkeley.ScheduledQueueFlush;
import com.radixdlt.environment.LocalEvents;
import com.radixdlt.mempool.MempoolAddFailure;
Expand All @@ -46,6 +47,7 @@ public final class ApiModule extends AbstractModule {
public void configure() {
bind(RadixHttpServer.class).in(Scopes.SINGLETON);
var controllers = Multibinder.newSetBinder(binder(), Controller.class);
controllers.addBinding().to(ConstructionController.class).in(Scopes.SINGLETON);
controllers.addBinding().to(ChaosController.class).in(Scopes.SINGLETON);
controllers.addBinding().to(FaucetController.class).in(Scopes.SINGLETON);
controllers.addBinding().to(NodeController.class).in(Scopes.SINGLETON);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* (C) Copyright 2021 Radix DLT Ltd
*
* Radix DLT Ltd licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the
* License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*
*/

package com.radixdlt.api.construction;

import com.google.inject.Inject;
import com.radixdlt.DefaultSerialization;
import com.radixdlt.atom.Atom;
import com.radixdlt.constraintmachine.Particle;
import com.radixdlt.constraintmachine.REInstruction;
import com.radixdlt.identifiers.AID;
import com.radixdlt.store.AtomIndex;
import com.radixdlt.utils.Ints;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.RoutingHandler;
import org.bouncycastle.util.encoders.Hex;
import org.radix.api.http.Controller;

import static org.radix.api.http.RestUtils.respond;
import static org.radix.api.http.RestUtils.withBodyAsync;
import static org.radix.api.jsonrpc.JsonRpcUtil.jsonArray;
import static org.radix.api.jsonrpc.JsonRpcUtil.jsonObject;

public final class ConstructionController implements Controller {
private final AtomIndex atomIndex;

@Inject
public ConstructionController(AtomIndex atomIndex) {
this.atomIndex = atomIndex;
}

@Override
public void configureRoutes(RoutingHandler handler) {
handler.post("/node/parse", this::handleParse);
}

void handleParse(HttpServerExchange exchange) {
withBodyAsync(exchange, values -> {
var transactionHex = values.getString("transaction");
var transactionBytes = Hex.decode(transactionHex);
var txn = DefaultSerialization.getInstance().fromDson(transactionBytes, Atom.class);
var ops = jsonArray();
var response = jsonObject().put("operations", ops);

for (int i = 0; i < txn.getInstructions().size(); i += 2) {
var b = txn.getInstructions().get(i);
var payload = txn.getInstructions().get(i + 1);
var instruction = REInstruction.create(b[0], payload);
var op = instruction.getMicroOp();
var jsonOp = jsonObject()
.put("type", op.toString())
.put("data", Hex.toHexString(instruction.getData()));
if (op == REInstruction.REOp.DOWN) {
var prevTxnBytes = atomIndex.get(AID.from(instruction.getData(), 0)).orElseThrow();
var index = Ints.fromByteArray(instruction.getData(), AID.BYTES);
var prevTxn = DefaultSerialization.getInstance().fromDson(prevTxnBytes.getPayload(), Atom.class);
var particleBytes = prevTxn.getInstructions().get(index * 2 + 1);
var particle = DefaultSerialization.getInstance().fromDson(particleBytes, Particle.class);
jsonOp.put("parsedData", particle.toString());
} else if (op == REInstruction.REOp.UP) {
var particle = DefaultSerialization.getInstance().fromDson(instruction.getData(), Particle.class);
jsonOp.put("parsedData", particle.toString());
} else if (op == REInstruction.REOp.VDOWN) {
var particle = DefaultSerialization.getInstance().fromDson(instruction.getData(), Particle.class);
jsonOp.put("parsedData", particle.toString());
} else if (op == REInstruction.REOp.LDOWN) {
var index = Ints.fromByteArray(instruction.getData());
jsonOp.put("parsedData", index);
}

ops.put(jsonOp);
}

respond(exchange, response);
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,26 @@
import com.radixdlt.engine.RadixEngine;
import com.radixdlt.environment.EventDispatcher;
import com.radixdlt.environment.EventProcessor;
import com.radixdlt.identifiers.AID;
import com.radixdlt.identifiers.RadixAddress;
import com.radixdlt.mempool.MempoolAdd;
import com.radixdlt.mempool.MempoolAddFailure;
import com.radixdlt.mempool.MempoolAddSuccess;
import com.radixdlt.statecomputer.LedgerAndBFTProof;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.HashMap;
import java.util.Map;

public class NodeApplication {
private static final Logger log = LogManager.getLogger();

private final RadixAddress self;
private final RadixEngine<LedgerAndBFTProof> radixEngine;
private final HashSigner hashSigner;
private final EventDispatcher<MempoolAdd> mempoolAddEventDispatcher;
private final Map<AID, NodeApplicationRequest> inflightRequests = new HashMap<>();

@Inject
public NodeApplication(
Expand All @@ -60,13 +67,36 @@ private void processRequest(NodeApplicationRequest request) {
// TODO: remove use of mempoolAdd message and add to mempool synchronously
var txBuilder = radixEngine.construct(self, request.getActions());
var txn = txBuilder.signAndBuild(hashSigner::sign);
this.mempoolAddEventDispatcher.dispatch(MempoolAdd.create(txn, request::onSuccess, request::onFailure));
this.inflightRequests.put(txn.getId(), request);
this.mempoolAddEventDispatcher.dispatch(MempoolAdd.create(txn));
} catch (TxBuilderException e) {
log.error("Faucet failed to fulfil request {}", request, e);
request.onFailure(e.getMessage());
log.error("Faucet failed to fulfil request {}", request);
request.onFailure(null, e.getMessage());
}
}

public EventProcessor<MempoolAddSuccess> mempoolAddSuccessEventProcessor() {
return mempoolAddSuccess -> {
var req = inflightRequests.remove(mempoolAddSuccess.getTxn().getId());
if (req == null) {
return;
}

req.onSuccess(mempoolAddSuccess.getTxn(), mempoolAddSuccess.getTxn().getId());
};
}

public EventProcessor<MempoolAddFailure> mempoolAddFailureEventProcessor() {
return failure -> {
var req = inflightRequests.remove(failure.getTxn().getId());
if (req == null) {
return;
}

req.onFailure(failure.getTxn(), failure.getException().getMessage());
};
}

public EventProcessor<NodeApplicationRequest> requestEventProcessor() {
return this::processRequest;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
import com.google.inject.multibindings.Multibinder;
import com.google.inject.multibindings.ProvidesIntoSet;
import com.radixdlt.atommodel.tokens.TransferrableTokensParticle;
import com.radixdlt.atommodel.validators.RegisteredValidatorParticle;
import com.radixdlt.atommodel.validators.UnregisteredValidatorParticle;
import com.radixdlt.atommodel.validators.ValidatorParticle;
import com.radixdlt.chaos.mempoolfiller.MempoolFiller;
import com.radixdlt.consensus.bft.Self;
import com.radixdlt.engine.StateReducer;
Expand All @@ -35,6 +34,8 @@
import com.radixdlt.fees.NativeToken;
import com.radixdlt.identifiers.RRI;
import com.radixdlt.identifiers.RadixAddress;
import com.radixdlt.mempool.MempoolAddFailure;
import com.radixdlt.mempool.MempoolAddSuccess;

/**
* Module which manages different applications a node can run with
Expand All @@ -58,16 +59,13 @@ public void configure() {
var eventBinder = Multibinder.newSetBinder(binder(), new TypeLiteral<Class<?>>() { }, LocalEvents.class)
.permitDuplicates();
eventBinder.addBinding().toInstance(NodeApplicationRequest.class);
eventBinder.addBinding().toInstance(MempoolAddSuccess.class);
eventBinder.addBinding().toInstance(MempoolAddFailure.class);
}

@ProvidesIntoSet
private SubstateCacheRegister<?> registeredSubstate(@Self RadixAddress self) {
return new SubstateCacheRegister<>(RegisteredValidatorParticle.class, p -> p.getAddress().equals(self));
}

@ProvidesIntoSet
private SubstateCacheRegister<?> unregisteredSubstate(@Self RadixAddress self) {
return new SubstateCacheRegister<>(UnregisteredValidatorParticle.class, p -> p.getAddress().equals(self));
return new SubstateCacheRegister<>(ValidatorParticle.class, p -> p.getAddress().equals(self));
}

@ProvidesIntoSet
Expand All @@ -89,4 +87,22 @@ public EventProcessorOnRunner<?> nodeApplication(NodeApplication nodeApplication
nodeApplication.requestEventProcessor()
);
}

@ProvidesIntoSet
public EventProcessorOnRunner<?> mempoolAddSuccess(NodeApplication nodeApplication) {
return new EventProcessorOnRunner<>(
"application",
MempoolAddSuccess.class,
nodeApplication.mempoolAddSuccessEventProcessor()
);
}

@ProvidesIntoSet
public EventProcessorOnRunner<?> mempoolAddFailure(NodeApplication nodeApplication) {
return new EventProcessorOnRunner<>(
"application",
MempoolAddFailure.class,
nodeApplication.mempoolAddFailureEventProcessor()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,22 @@
package com.radixdlt.application;

import com.radixdlt.atom.TxAction;
import com.radixdlt.atom.Txn;
import com.radixdlt.identifiers.AID;

import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.BiConsumer;

public final class NodeApplicationRequest {
private final List<TxAction> actions;
private final Consumer<AID> onSuccess;
private final Consumer<String> onError;
private final BiConsumer<Txn, AID> onSuccess;
private final BiConsumer<Txn, String> onError;

private NodeApplicationRequest(
List<TxAction> actions,
Consumer<AID> onSuccess,
Consumer<String> onError
BiConsumer<Txn, AID> onSuccess,
BiConsumer<Txn, String> onError
) {
this.actions = actions;
this.onSuccess = onSuccess;
Expand All @@ -45,13 +46,13 @@ public static NodeApplicationRequest create(TxAction action) {
}

public static NodeApplicationRequest create(List<TxAction> actions) {
return create(actions, aid -> { }, error -> { });
return create(actions, (txn, aid) -> { }, (txn, error) -> { });
}

public static NodeApplicationRequest create(
List<TxAction> actions,
Consumer<AID> onSuccess,
Consumer<String> onError
BiConsumer<Txn, AID> onSuccess,
BiConsumer<Txn, String> onError
) {
Objects.requireNonNull(actions);
Objects.requireNonNull(onSuccess);
Expand All @@ -63,11 +64,11 @@ public List<TxAction> getActions() {
return actions;
}

public void onSuccess(AID aid) {
onSuccess.accept(aid);
public void onSuccess(Txn txn, AID aid) {
onSuccess.accept(txn, aid);
}

public void onFailure(String errorMessage) {
onError.accept(errorMessage);
public void onFailure(Txn txn, String errorMessage) {
onError.accept(txn, errorMessage);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
import com.radixdlt.atommodel.tokens.StakedTokensParticle;
import com.radixdlt.consensus.bft.Self;
import com.radixdlt.engine.StateReducer;
import com.radixdlt.fees.NativeToken;
import com.radixdlt.identifiers.RRI;
import com.radixdlt.identifiers.RadixAddress;

import java.util.Objects;
Expand All @@ -34,15 +32,10 @@
* Reduces radix engine to stake received
*/
public final class StakeReceivedReducer implements StateReducer<StakeReceived, StakedTokensParticle> {
private final RRI tokenRRI;
private final RadixAddress address;

@Inject
public StakeReceivedReducer(
@NativeToken RRI tokenRRI,
@Self RadixAddress address
) {
this.tokenRRI = Objects.requireNonNull(tokenRRI);
public StakeReceivedReducer(@Self RadixAddress address) {
this.address = Objects.requireNonNull(address);
}

Expand All @@ -64,7 +57,7 @@ public Supplier<StakeReceived> initial() {
@Override
public BiFunction<StakeReceived, StakedTokensParticle, StakeReceived> outputReducer() {
return (stakes, p) -> {
if (p.getDelegateAddress().equals(address) && p.getTokDefRef().equals(tokenRRI)) {
if (p.getDelegateAddress().equals(address)) {
stakes.addStake(p.getAddress(), p.getAmount());
}
return stakes;
Expand All @@ -74,7 +67,7 @@ public BiFunction<StakeReceived, StakedTokensParticle, StakeReceived> outputRedu
@Override
public BiFunction<StakeReceived, StakedTokensParticle, StakeReceived> inputReducer() {
return (stakes, p) -> {
if (p.getDelegateAddress().equals(address) && p.getTokDefRef().equals(tokenRRI)) {
if (p.getDelegateAddress().equals(address)) {
stakes.removeStake(p.getAddress(), p.getAmount());
}
return stakes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,17 @@
import com.radixdlt.atommodel.tokens.StakedTokensParticle;
import com.radixdlt.consensus.bft.Self;
import com.radixdlt.engine.StateReducer;
import com.radixdlt.fees.NativeToken;
import com.radixdlt.identifiers.RRI;
import com.radixdlt.identifiers.RadixAddress;

import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Supplier;

public final class StakedBalanceReducer implements StateReducer<StakedBalance, StakedTokensParticle> {
private final RRI tokenRRI;
private final RadixAddress address;

@Inject
public StakedBalanceReducer(
@NativeToken RRI tokenRRI,
@Self RadixAddress address
) {
this.tokenRRI = Objects.requireNonNull(tokenRRI);
public StakedBalanceReducer(@Self RadixAddress address) {
this.address = Objects.requireNonNull(address);
}

Expand All @@ -61,7 +54,7 @@ public Supplier<StakedBalance> initial() {
@Override
public BiFunction<StakedBalance, StakedTokensParticle, StakedBalance> outputReducer() {
return (stakes, p) -> {
if (p.getAddress().equals(address) && p.getTokDefRef().equals(tokenRRI)) {
if (p.getAddress().equals(address)) {
stakes.addStake(p.getDelegateAddress(), p.getAmount());
}
return stakes;
Expand All @@ -71,7 +64,7 @@ public BiFunction<StakedBalance, StakedTokensParticle, StakedBalance> outputRedu
@Override
public BiFunction<StakedBalance, StakedTokensParticle, StakedBalance> inputReducer() {
return (balance, p) -> {
if (p.getAddress().equals(address) && p.getTokDefRef().equals(tokenRRI)) {
if (p.getAddress().equals(address)) {
balance.removeStake(p.getDelegateAddress(), p.getAmount());
}
return balance;
Expand Down
Loading