Skip to content

Commit

Permalink
Merge pull request #149 from semuxgo/db-transaction-result
Browse files Browse the repository at this point in the history
Enhance transaction result
  • Loading branch information
semuxgo committed Mar 16, 2019
2 parents 2310ca0 + fb8e54d commit 9def0cb
Show file tree
Hide file tree
Showing 17 changed files with 337 additions and 153 deletions.
14 changes: 7 additions & 7 deletions src/main/java/org/semux/api/v2/SemuxApiImpl.java
Expand Up @@ -53,8 +53,8 @@
import org.semux.api.v2.model.GetPendingTransactionsResponse;
import org.semux.api.v2.model.GetSyncingProgressResponse;
import org.semux.api.v2.model.GetTransactionLimitsResponse;
import org.semux.api.v2.model.GetTransactionReceiptResponse;
import org.semux.api.v2.model.GetTransactionResponse;
import org.semux.api.v2.model.GetTransactionResultResponse;
import org.semux.api.v2.model.GetValidatorsResponse;
import org.semux.api.v2.model.GetVoteResponse;
import org.semux.api.v2.model.GetVotesResponse;
Expand Down Expand Up @@ -555,9 +555,9 @@ public Response getTransactionLimits(String type) {
}

@Override
public Response getTransactionReceipt(
public Response getTransactionResult(
@NotNull @javax.validation.constraints.Pattern(regexp = "^(0x)?[0-9a-fA-F]{64}$") String hash) {
GetTransactionReceiptResponse resp = new GetTransactionReceiptResponse();
GetTransactionResultResponse resp = new GetTransactionResultResponse();

if (!isSet(hash)) {
return badRequest(resp, "Parameter `hash` is required");
Expand All @@ -575,7 +575,7 @@ public Response getTransactionReceipt(
return badRequest(resp, "The request transaction was not found");
}

resp.setResult(TypeFactory.transactionReceiptType(result));
resp.setResult(TypeFactory.transactionResultType(result));

return success(resp);
}
Expand Down Expand Up @@ -788,11 +788,11 @@ public Response call(String from, String to, String value, String gasPrice, Stri
org.ethereum.vm.client.TransactionExecutor executor = new org.ethereum.vm.client.TransactionExecutor(
transaction, block, repository, blockStore,
Spec.DEFAULT, invokeFactory, gasUsedInBlock, true);
TransactionReceipt results = executor.run();
TransactionReceipt receipt = executor.run();

DoTransactionResponse resp = new DoTransactionResponse();
resp.setResult(Hex.encode0x(results.getReturnData()));
if (!results.isSuccess()) {
resp.setResult(Hex.encode0x(receipt.getReturnData()));
if (!receipt.isSuccess()) {
return badRequest(resp, "Error calling method");
} else {
return success(resp);
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/org/semux/api/v2/TypeFactory.java
Expand Up @@ -24,7 +24,7 @@
import org.semux.api.v2.model.LogInfoType;
import org.semux.api.v2.model.PeerType;
import org.semux.api.v2.model.TransactionLimitsType;
import org.semux.api.v2.model.TransactionReceiptType;
import org.semux.api.v2.model.TransactionResultType;
import org.semux.api.v2.model.TransactionType;
import org.semux.core.Amount;
import org.semux.core.Block;
Expand Down Expand Up @@ -153,8 +153,8 @@ public static TransactionType transactionType(Transaction tx) {
return txType;
}

public static TransactionReceiptType transactionReceiptType(TransactionResult result) {
return new TransactionReceiptType()
public static TransactionResultType transactionResultType(TransactionResult result) {
return new TransactionResultType()
.logs(result.getLogs().stream().map(TypeFactory::logInfoType).collect(Collectors.toList()))
.gasUsed(String.valueOf(result.getGasUsed()))
.code(result.getCode().name())
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/semux/consensus/SemuxBft.java
Expand Up @@ -814,7 +814,7 @@ protected Block proposeBlock() {
TransactionResult result = exec.execute(tx.transaction, as, ds, semuxBlock, chain);
gasUsed += result.getGasUsed();

if (result.getCode().isAccepted() && gasUsed < config.vmBlockGasLimit()) {
if (result.getCode().isAcceptable() && gasUsed < config.vmBlockGasLimit()) {
pendingResults.add(result);
pendingTxs.add(tx.transaction);
} else {
Expand Down Expand Up @@ -907,6 +907,8 @@ protected boolean validateBlockProposal(Block block) {
// when proposing
List<TransactionResult> results = exec.execute(transactions, as, ds,
new SemuxBlock(header, Long.MAX_VALUE), chain);
block.setResults(results);

if (!block.validateResults(header, results)) {
logger.warn("Invalid transactions");
return false;
Expand All @@ -915,7 +917,6 @@ protected boolean validateBlockProposal(Block block) {
long t2 = TimeUtil.currentTimeMillis();
logger.debug("Block validation: # txs = {}, time = {} ms", transactions.size(), t2 - t1);

block.setResults(results);
validBlocks.put(ByteArray.of(block.getHash()), block);
return true;
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/semux/consensus/SemuxSync.java
Expand Up @@ -566,6 +566,8 @@ protected boolean validateBlock(Block block, AccountState asSnapshot, DelegateSt
TransactionExecutor transactionExecutor = new TransactionExecutor(config, blockStore);
List<TransactionResult> results = transactionExecutor.execute(transactions, asSnapshot, dsSnapshot,
new SemuxBlock(block.getHeader(), config.vmMaxBlockGasLimit()), chain);
block.setResults(results);

if (!block.validateResults(header, results)) {
logger.error("Invalid transactions");
return false;
Expand Down
22 changes: 13 additions & 9 deletions src/main/java/org/semux/core/Block.java
Expand Up @@ -117,10 +117,6 @@ public Block(BlockHeader header, List<Transaction> transactions) {
this(header, transactions, new ArrayList<>(), 0, new ArrayList<>());
}

public Block(BlockHeader header, List<Transaction> transactions, int view, List<Signature> votes) {
this(header, transactions, new ArrayList<>(), view, votes);
}

public Block(BlockHeader header, List<Transaction> transactions, List<TransactionResult> results) {
this(header, transactions, results, 0, new ArrayList<>());
}
Expand Down Expand Up @@ -476,6 +472,13 @@ public byte[] getEncodedVotes() {
* @return
*/
public static Block fromComponents(byte[] h, byte[] t, byte[] r, byte[] v) {
if (h == null) {
throw new IllegalArgumentException("Block header can't be null");
}
if (t == null) {
throw new IllegalArgumentException("Block transactions can't be null");
}

BlockHeader header = BlockHeader.fromBytes(h);

SimpleDecoder dec = new SimpleDecoder(t);
Expand All @@ -485,16 +488,17 @@ public static Block fromComponents(byte[] h, byte[] t, byte[] r, byte[] v) {
transactions.add(Transaction.fromBytes(dec.readBytes()));
}

dec = new SimpleDecoder(r);
List<TransactionResult> results = new ArrayList<>();
n = dec.readInt();
for (int i = 0; i < n; i++) {
results.add(TransactionResult.fromBytes(dec.readBytes()));
if (r != null) {
dec = new SimpleDecoder(r);
n = dec.readInt();
for (int i = 0; i < n; i++) {
results.add(TransactionResult.fromBytes(dec.readBytes()));
}
}

int view = 0;
List<Signature> votes = new ArrayList<>();

if (v != null) {
dec = new SimpleDecoder(v);
view = dec.readInt();
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/semux/core/BlockchainImpl.java
Expand Up @@ -281,7 +281,7 @@ public TransactionResult getTransactionResult(byte[] hash) {
if (bytes != null) {
// coinbase transaction
if (bytes.length > 64) {
return new TransactionResult();
return null; // no results for coinbase transaction
}

SimpleDecoder dec = new SimpleDecoder(bytes);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/semux/core/PendingManager.java
Expand Up @@ -318,7 +318,7 @@ protected ProcessingResult processTransaction(Transaction tx, boolean relay) {

// reject transactions with a duplicated tx hash
if (kernel.getBlockchain().hasTransaction(tx.getHash())) {
return new ProcessingResult(0, TransactionResult.Code.DUPLICATE_TRANSACTION);
return new ProcessingResult(0, TransactionResult.Code.INVALID);
}

// check transaction timestamp if this is a fresh transaction:
Expand Down Expand Up @@ -355,7 +355,7 @@ protected ProcessingResult processTransaction(Transaction tx, boolean relay) {
TransactionResult result = new TransactionExecutor(kernel.getConfig(), blockStore).execute(tx,
as, ds, block, chain);

if (result.getCode().isAccepted()) {
if (result.getCode().isAcceptable()) {
// commit state updates
as.commit();
ds.commit();
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/org/semux/core/Transaction.java
Expand Up @@ -46,8 +46,7 @@ public class Transaction {
private Signature signature;

private final long gas;

private final long gasPrice;
private final long gasPrice; // nanoSEM per gas

/**
* Create a new transaction.
Expand Down Expand Up @@ -169,8 +168,8 @@ public boolean validate(Network network) {
// It won't introduce any fundamental loss to the system but could potentially
// cause confusion for block explorer, and thus are prohibited.
&& (type == TransactionType.COINBASE
|| (!Arrays.equals(signature.getAddress(), Constants.COINBASE_ADDRESS) &&
!Arrays.equals(to, Constants.COINBASE_ADDRESS)));
|| (!Arrays.equals(signature.getAddress(), Constants.COINBASE_ADDRESS)
&& !Arrays.equals(to, Constants.COINBASE_ADDRESS)));
}

/**
Expand Down
20 changes: 13 additions & 7 deletions src/main/java/org/semux/core/TransactionExecutor.java
Expand Up @@ -232,7 +232,7 @@ public List<TransactionResult> execute(List<Transaction> txs, AccountState as, D
result.setCode(Code.INVALID_GAS);
} else {
executeVmTransaction(result, tx, as, block, gasUsedInBlock);
if (result.getCode().isAccepted()) {
if (result.getCode().isAcceptable()) {
gasUsedInBlock += result.getGasUsed();
}
}
Expand All @@ -247,9 +247,11 @@ public List<TransactionResult> execute(List<Transaction> txs, AccountState as, D

// increase nonce if success
// creates and calls increase their own nonces internal to VM
if (result.getCode().isAccepted() && !isVmCall) {
if (result.getCode().isAcceptable() && !isVmCall) {
as.increaseNonce(from);
}

result.setBlockNumber(block.getNumber());
}

return results;
Expand All @@ -266,16 +268,20 @@ private void executeVmTransaction(TransactionResult result, Transaction tx, Acco
Spec.DEFAULT, invokeFactory, gasUsedInBlock, false);

TransactionReceipt summary = executor.run();

if (summary == null) {
result.setCode(Code.INVALID_GAS);
result.setGasUsed(tx.getGas());
result.setCode(Code.INVALID);
} else {
result.setCode(summary.isSuccess() ? Code.SUCCESS : Code.FAILURE);
result.setReturnData(summary.getReturnData());
for (LogInfo log : summary.getLogs()) {
result.addLog(log);
}
result.setGasUsed(summary.getGasUsed());
result.setReturnData(summary.getReturnData());
result.setCode(summary.isSuccess() ? Code.SUCCESS : Code.FAILURE);

result.setGas(tx.getGas(), tx.getGasPrice(), summary.getGasUsed());

result.setBlockNumber(block.getNumber());
result.setInternalTransactions(summary.getInternalTransactions());
}
}

Expand Down

0 comments on commit 9def0cb

Please sign in to comment.