diff --git a/.gitignore b/.gitignore
index 191f94965..e82472b4d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,12 @@ src/gen
# ignore slf4j test config
src/test/resources/log4j2-test.xml
+
+CMakeFiles
+CMakeFiles/
+/CMakeFiles/
+CMakeLists.txt.user
+CMakeCache.txt
+Makefile
+install_manifest.txt
+cmake_install.cmake
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b9368a2c3..227e7d4b3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Change Log
+## [v2.2.x](https://github.com/semuxproject/semux-core/tree/develop) (2020-xx-xx) (WIP)
+
+This release adds support for EIP-665 precompiled contract.
+
+NOTE: A softfork `EIP665_PRECOMPILED_UPGRADE` is introduced.
+
+
+
## [v2.1.x](https://github.com/semuxproject/semux-core/tree/v2.1.1) (2019-09-10)
This release tries to fix several issues about the voting precompiled contracts. All nodes
diff --git a/pom.xml b/pom.xml
index 58a89be46..ec88e76c1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
org.semux
semux
- 2.1.1
+ 2.2.0
jar
Semux is an experimental high-performance blockchain platform that powers decentralized application.
diff --git a/src/main/java/org/semux/api/http/HttpHandler.java b/src/main/java/org/semux/api/http/HttpHandler.java
index a10e8ceed..7de0fe939 100644
--- a/src/main/java/org/semux/api/http/HttpHandler.java
+++ b/src/main/java/org/semux/api/http/HttpHandler.java
@@ -53,7 +53,6 @@
import io.netty.handler.codec.http.HttpChunkedInput;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaders;
-import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.QueryStringDecoder;
diff --git a/src/main/java/org/semux/api/util/TransactionBuilder.java b/src/main/java/org/semux/api/util/TransactionBuilder.java
index 8572b072a..f2b8776bb 100644
--- a/src/main/java/org/semux/api/util/TransactionBuilder.java
+++ b/src/main/java/org/semux/api/util/TransactionBuilder.java
@@ -9,6 +9,7 @@
import org.semux.Kernel;
import org.semux.Network;
import org.semux.core.Amount;
+import org.semux.core.Fork;
import org.semux.core.Transaction;
import org.semux.core.TransactionType;
import org.semux.crypto.CryptoException;
@@ -218,7 +219,7 @@ public TransactionBuilder withGasPrice(String gasPrice) {
return this;
}
- public Transaction buildUnsigned() {
+ public Transaction buildUnsigned(byte[] from) {
Network network = (this.network != null) ? this.network : kernel.getConfig().network();
TransactionType type = this.type;
@@ -293,7 +294,7 @@ public Transaction buildUnsigned() {
}
}
- return new Transaction(network, type, to, value, fee, nonce, timestamp, data, gas, gasPrice);
+ return new Transaction(network, type, to, from, value, fee, nonce, timestamp, data, gas, gasPrice, kernel.getBlockchain().isForkActivated(Fork.ED25519_CONTRACT));
}
public Transaction buildSigned() {
@@ -301,6 +302,11 @@ public Transaction buildSigned() {
throw new IllegalArgumentException("The sender is not specified");
}
- return buildUnsigned().sign(account);
+ return buildUnsigned(account.toAddress()).sign(account);
+ }
+
+ public byte[] To ()
+ {
+ return to;
}
}
\ No newline at end of file
diff --git a/src/main/java/org/semux/api/v2/SemuxApiImpl.java b/src/main/java/org/semux/api/v2/SemuxApiImpl.java
index 841511172..24a77c426 100644
--- a/src/main/java/org/semux/api/v2/SemuxApiImpl.java
+++ b/src/main/java/org/semux/api/v2/SemuxApiImpl.java
@@ -70,6 +70,7 @@
import org.semux.core.Block;
import org.semux.core.Blockchain;
import org.semux.core.BlockchainImpl;
+import org.semux.core.Fork;
import org.semux.core.PendingManager;
import org.semux.core.SyncManager;
import org.semux.core.Transaction;
@@ -167,7 +168,9 @@ public Response composeRawTransaction(String network, String type, String to, St
.withData(data)
.withGas(gas)
.withGasPrice(gasPrice);
- Transaction transaction = transactionBuilder.buildUnsigned();
+
+ /*We can use TO address instead FROM address, only if transaction will be used for ComposeRawTransactionResponse*/
+ Transaction transaction = transactionBuilder.buildUnsigned(transactionBuilder.To());
ComposeRawTransactionResponse resp = new ComposeRawTransactionResponse();
resp.setResult(Hex.encode0x(transaction.getEncoded()));
@@ -662,7 +665,7 @@ public Response signRawTransaction(String raw, String address) {
return badRequest("Address doesn't belong to this wallet.");
}
- Transaction tx = Transaction.fromEncoded(txBytes).sign(signerKey);
+ Transaction tx = Transaction.fromEncoded(txBytes, signerKey.toAddress(), kernel.getBlockchain().isForkActivated(Fork.ED25519_CONTRACT)).sign(signerKey);
SignRawTransactionResponse resp = new SignRawTransactionResponse();
resp.setResult(Hex.encode0x(tx.toBytes()));
@@ -914,7 +917,7 @@ private TransactionResultType doLocalTransaction(TransactionType type, String to
SemuxBlock block = kernel.createEmptyBlock();
BlockStore blockStore = new SemuxBlockStore(chain);
TransactionExecutor exec = new TransactionExecutor(config, blockStore, chain.isVMEnabled(),
- chain.isVotingPrecompiledUpgraded());
+ chain.isVotingPrecompiledUpgraded(), chain.isEd25519ContractEnabled());
TransactionResult result = exec.execute(tx, asTrack, dsTrack, block, 0);
byte[] contractAddress = type.equals(TransactionType.CREATE)
diff --git a/src/main/java/org/semux/config/AbstractConfig.java b/src/main/java/org/semux/config/AbstractConfig.java
index b730f2266..94f865464 100644
--- a/src/main/java/org/semux/config/AbstractConfig.java
+++ b/src/main/java/org/semux/config/AbstractConfig.java
@@ -10,9 +10,7 @@
import static org.semux.Network.MAINNET;
import static org.semux.Network.TESTNET;
import static org.semux.core.Amount.ZERO;
-import static org.semux.core.Fork.UNIFORM_DISTRIBUTION;
-import static org.semux.core.Fork.VIRTUAL_MACHINE;
-import static org.semux.core.Fork.VOTING_PRECOMPILED_UPGRADE;
+import static org.semux.core.Fork.*;
import static org.semux.core.Unit.MILLI_SEM;
import static org.semux.core.Unit.SEM;
@@ -156,6 +154,7 @@ public abstract class AbstractConfig implements Config, ChainSpec {
protected boolean forkUniformDistributionEnabled = false;
protected boolean forkVirtualMachineEnabled = false;
protected boolean forkVotingPrecompiledUpgradeEnabled = false;
+ protected boolean forkEd25519ContractEnabled = false;
@Override
public ChainSpec spec() {
@@ -253,7 +252,7 @@ public String getPrimaryValidator(List validators, long height, int view
return validators.get(getUniformDistPrimaryValidatorNumber(validators.size(), height, view));
} else {
byte[] key = Bytes.merge(Bytes.of(height), Bytes.of(view));
- return validators.get((Hash.h256(key)[0] & 0xff) % validators.size());
+ return validators.get((Hash.h256_s(key, null)[0] & 0xff) % validators.size());
}
}
@@ -295,15 +294,18 @@ public Spec vmSpec() {
periods[MAINNET.id()][UNIFORM_DISTRIBUTION.id()] = new long[] { 200_001L, 400_000L };
periods[MAINNET.id()][VIRTUAL_MACHINE.id()] = new long[] { 1_500_001L, 1_700_000L };
periods[MAINNET.id()][VOTING_PRECOMPILED_UPGRADE.id()] = new long[] { 1_600_001L, 1_800_000L };
+ periods[MAINNET.id()][ED25519_CONTRACT.id()] = new long[] { 2_800_804L, 3_000_000L };
periods[TESTNET.id()][UNIFORM_DISTRIBUTION.id()] = new long[] { 1L, 200_000L };
periods[TESTNET.id()][VIRTUAL_MACHINE.id()] = new long[] { 1L, 200_000L };
periods[TESTNET.id()][VOTING_PRECOMPILED_UPGRADE.id()] = new long[] { 150_001L, 350_000L };
+ periods[MAINNET.id()][ED25519_CONTRACT.id()] = new long[] { 1_000_000L, 1_500_000L };
// as soon as possible
periods[DEVNET.id()][UNIFORM_DISTRIBUTION.id()] = new long[] { 1L, 200_000L };
periods[DEVNET.id()][VIRTUAL_MACHINE.id()] = new long[] { 1L, 200_000L };
periods[DEVNET.id()][VOTING_PRECOMPILED_UPGRADE.id()] = new long[] { 1, 200_000L };
+ periods[DEVNET.id()][ED25519_CONTRACT.id()] = new long[] { 1, 200_000L };
}
@Override
@@ -590,6 +592,11 @@ public boolean forkVotingPrecompiledUpgradeEnabled() {
return forkVotingPrecompiledUpgradeEnabled;
}
+ @Override
+ public boolean forkEd25519ContractEnabled() {
+ return forkEd25519ContractEnabled;
+ }
+
protected void init() {
File f = getFile();
if (!f.exists()) {
diff --git a/src/main/java/org/semux/config/Config.java b/src/main/java/org/semux/config/Config.java
index f072595fa..b57037b11 100644
--- a/src/main/java/org/semux/config/Config.java
+++ b/src/main/java/org/semux/config/Config.java
@@ -444,6 +444,13 @@ public interface Config {
*/
boolean forkVotingPrecompiledUpgradeEnabled();
+ /**
+ * Returns whether ED25519_CONTRACT fork is enabled.
+ *
+ * @return
+ */
+ boolean forkEd25519ContractEnabled();
+
// =========================
// Checkpoints
// =========================
@@ -462,4 +469,5 @@ public interface Config {
* [block height]
*/
Map manuallyActivatedForks();
+
}
diff --git a/src/main/java/org/semux/config/Constants.java b/src/main/java/org/semux/config/Constants.java
index a1f2d8ea8..68a66b57d 100644
--- a/src/main/java/org/semux/config/Constants.java
+++ b/src/main/java/org/semux/config/Constants.java
@@ -34,7 +34,7 @@ public class Constants {
/**
* Version of this client.
*/
- public static final String CLIENT_VERSION = "2.1.1";
+ public static final String CLIENT_VERSION = "2.2.0";
/**
* Algorithm name for the 256-bit hash.
diff --git a/src/main/java/org/semux/config/DevnetConfig.java b/src/main/java/org/semux/config/DevnetConfig.java
index aa8d867f9..4cfaeb5b5 100644
--- a/src/main/java/org/semux/config/DevnetConfig.java
+++ b/src/main/java/org/semux/config/DevnetConfig.java
@@ -23,6 +23,7 @@ public DevnetConfig(String dataDir) {
this.forkUniformDistributionEnabled = true;
this.forkVirtualMachineEnabled = true;
this.forkVotingPrecompiledUpgradeEnabled = true;
+ this.forkEd25519ContractEnabled = true;
// set fast blocks
bftNewHeightTimeout = 1000L;
@@ -48,6 +49,7 @@ public Map manuallyActivatedForks() {
forks.put(Fork.UNIFORM_DISTRIBUTION, 1l);
forks.put(Fork.VIRTUAL_MACHINE, 1l);
forks.put(Fork.VOTING_PRECOMPILED_UPGRADE, 1l);
+ forks.put(Fork.ED25519_CONTRACT, 1l);
return forks;
}
diff --git a/src/main/java/org/semux/config/MainnetConfig.java b/src/main/java/org/semux/config/MainnetConfig.java
index 7c3125d9b..8f8486cd7 100644
--- a/src/main/java/org/semux/config/MainnetConfig.java
+++ b/src/main/java/org/semux/config/MainnetConfig.java
@@ -45,6 +45,7 @@ public MainnetConfig(String dataDir) {
this.forkUniformDistributionEnabled = true;
this.forkVirtualMachineEnabled = true;
this.forkVotingPrecompiledUpgradeEnabled = true;
+ this.forkEd25519ContractEnabled = false; // enable this when we are ready to go
}
@Override
diff --git a/src/main/java/org/semux/config/TestnetConfig.java b/src/main/java/org/semux/config/TestnetConfig.java
index 5e1cb9cf1..d3c504140 100644
--- a/src/main/java/org/semux/config/TestnetConfig.java
+++ b/src/main/java/org/semux/config/TestnetConfig.java
@@ -20,6 +20,7 @@ public TestnetConfig(String dataDir) {
this.forkUniformDistributionEnabled = true;
this.forkVirtualMachineEnabled = true;
this.forkVotingPrecompiledUpgradeEnabled = true;
+ this.forkEd25519ContractEnabled = true;
}
@Override
diff --git a/src/main/java/org/semux/consensus/SemuxBft.java b/src/main/java/org/semux/consensus/SemuxBft.java
index 82f308c46..cfafb0f4f 100644
--- a/src/main/java/org/semux/consensus/SemuxBft.java
+++ b/src/main/java/org/semux/consensus/SemuxBft.java
@@ -27,6 +27,7 @@
import org.semux.core.Block;
import org.semux.core.BlockHeader;
import org.semux.core.Blockchain;
+import org.semux.core.Fork;
import org.semux.core.PendingManager;
import org.semux.core.SyncManager;
import org.semux.core.Transaction;
@@ -766,7 +767,7 @@ protected Block proposeBlock() {
final List includedResults = new ArrayList<>();
TransactionExecutor exec = new TransactionExecutor(config, blockStore, chain.isVMEnabled(),
- chain.isVotingPrecompiledUpgraded());
+ chain.isVotingPrecompiledUpgraded(), chain.isEd25519ContractEnabled());
SemuxBlock semuxBlock = new SemuxBlock(tempHeader, config.spec().maxBlockGasLimit());
// only propose gas used up to configured block gas limit
@@ -841,7 +842,7 @@ protected boolean validateBlockProposal(BlockHeader header, List tr
// [2] check transactions
List unvalidatedTransactions = getUnvalidatedTransactions(transactions);
- if (!block.validateTransactions(header, unvalidatedTransactions, transactions, config.network())) {
+ if (!block.validateTransactions(header, unvalidatedTransactions, transactions, config.network(), kernel.getBlockchain().isForkActivated(Fork.ED25519_CONTRACT))) {
logger.warn("Invalid transactions");
return false;
}
@@ -852,7 +853,7 @@ protected boolean validateBlockProposal(BlockHeader header, List tr
// [3] evaluate transactions
TransactionExecutor transactionExecutor = new TransactionExecutor(config, blockStore, chain.isVMEnabled(),
- chain.isVotingPrecompiledUpgraded());
+ chain.isVotingPrecompiledUpgraded(), chain.isEd25519ContractEnabled());
List results = transactionExecutor.execute(transactions, asTrack, dsTrack,
new SemuxBlock(header, config.spec().maxBlockGasLimit()), 0);
if (!block.validateResults(header, results)) {
diff --git a/src/main/java/org/semux/core/Block.java b/src/main/java/org/semux/core/Block.java
index 7698b573a..c3d13fa17 100644
--- a/src/main/java/org/semux/core/Block.java
+++ b/src/main/java/org/semux/core/Block.java
@@ -151,10 +151,11 @@ public boolean validateHeader(BlockHeader header, BlockHeader parentHeader) {
* @param header
* @param transactions
* @param network
+ * @param isFixTxHash
* @return
*/
- public boolean validateTransactions(BlockHeader header, List transactions, Network network) {
- return validateTransactions(header, transactions, transactions, network);
+ public boolean validateTransactions(BlockHeader header, List transactions, Network network, boolean isFixTxHash) {
+ return validateTransactions(header, transactions, transactions, network, isFixTxHash);
}
/**
@@ -169,18 +170,19 @@ public boolean validateTransactions(BlockHeader header, List transa
* all transactions within the block
* @param network
* network
+ * @param isFixTxHash
* @return
*/
public boolean validateTransactions(BlockHeader header, Collection unvalidatedTransactions,
- List allTransactions, Network network) {
+ List allTransactions, Network network, boolean isFixTxHash) {
// validate transactions
if (!Key.isVerifyBatchSupported() || unvalidatedTransactions.size() < 3) {
- if (!unvalidatedTransactions.parallelStream().allMatch(tx -> tx.validate(network))) {
+ if (!unvalidatedTransactions.parallelStream().allMatch(tx -> tx.validate_verify_sign(network, isFixTxHash))) {
return false;
}
} else {
- if (!unvalidatedTransactions.parallelStream().allMatch(tx -> tx.validate(network, false))) {
+ if (!unvalidatedTransactions.parallelStream().allMatch(tx -> tx.validate_no_verify_sign(network, isFixTxHash))) {
return false;
}
@@ -460,6 +462,7 @@ public byte[] getEncodedVotes() {
* Serialized transaction results
* @param v
* Serialized votes
+ * @param isFixTxHash
* @return
*/
public static Block fromComponents(byte[] h, byte[] t, byte[] r, byte[] v) {
diff --git a/src/main/java/org/semux/core/BlockHeader.java b/src/main/java/org/semux/core/BlockHeader.java
index 3653e7318..2bc8c562a 100644
--- a/src/main/java/org/semux/core/BlockHeader.java
+++ b/src/main/java/org/semux/core/BlockHeader.java
@@ -71,7 +71,7 @@ public BlockHeader(long number, byte[] coinbase, byte[] prevHash, long timestamp
enc.writeBytes(stateRoot);
enc.writeBytes(data);
this.encoded = enc.toBytes();
- this.hash = Hash.h256(encoded);
+ this.hash = Hash.h256_s(encoded, null);
}
/**
@@ -112,7 +112,7 @@ public boolean validate() {
&& stateRoot != null && Arrays.equals(Bytes.EMPTY_HASH, stateRoot) // RESERVED FOR VM
&& data != null && data.length <= BlockHeaderData.MAX_SIZE
&& encoded != null
- && Arrays.equals(Hash.h256(encoded), hash);
+ && Arrays.equals(Hash.h256_s(encoded, null), hash);
}
public byte[] getHash() {
diff --git a/src/main/java/org/semux/core/Blockchain.java b/src/main/java/org/semux/core/Blockchain.java
index db732b08f..0c7b08236 100644
--- a/src/main/java/org/semux/core/Blockchain.java
+++ b/src/main/java/org/semux/core/Blockchain.java
@@ -270,4 +270,6 @@ public interface Blockchain {
boolean isVMEnabled();
boolean isVotingPrecompiledUpgraded();
+
+ boolean isEd25519ContractEnabled();
}
diff --git a/src/main/java/org/semux/core/BlockchainImpl.java b/src/main/java/org/semux/core/BlockchainImpl.java
index a499e0340..93b5cce5b 100644
--- a/src/main/java/org/semux/core/BlockchainImpl.java
+++ b/src/main/java/org/semux/core/BlockchainImpl.java
@@ -6,9 +6,7 @@
*/
package org.semux.core;
-import static org.semux.core.Fork.UNIFORM_DISTRIBUTION;
-import static org.semux.core.Fork.VIRTUAL_MACHINE;
-import static org.semux.core.Fork.VOTING_PRECOMPILED_UPGRADE;
+import static org.semux.core.Fork.*;
import java.io.IOException;
import java.nio.file.FileVisitResult;
@@ -394,11 +392,13 @@ public synchronized void addBlock(Block block) {
Transaction tx = new Transaction(config.network(),
TransactionType.COINBASE,
block.getCoinbase(),
+ Constants.COINBASE_KEY.toAddress(),
reward,
Amount.ZERO,
block.getNumber(),
block.getTimestamp(),
- Bytes.EMPTY_BYTES);
+ Bytes.EMPTY_BYTES,
+ isForkActivated(Fork.ED25519_CONTRACT));
tx.sign(Constants.COINBASE_KEY);
indexDB.put(Bytes.merge(TYPE_TRANSACTION_INDEX_BY_HASH, tx.getHash()), tx.toBytes());
indexDB.put(Bytes.merge(TYPE_BLOCK_COINBASE_BY_NUMBER, Bytes.of(block.getNumber())), tx.getHash());
@@ -714,6 +714,11 @@ public boolean isVotingPrecompiledUpgraded() {
return isForkActivated(VOTING_PRECOMPILED_UPGRADE);
}
+ @Override
+ public boolean isEd25519ContractEnabled() {
+ return isForkActivated(ED25519_CONTRACT);
+ }
+
@Override
public byte[] constructBlockHeaderDataField() {
Set set = new HashSet<>();
@@ -729,6 +734,9 @@ public byte[] constructBlockHeaderDataField() {
if (config.forkVotingPrecompiledUpgradeEnabled()) {
addFork(set, VOTING_PRECOMPILED_UPGRADE);
}
+ if (config.forkEd25519ContractEnabled()) {
+ addFork(set, ED25519_CONTRACT);
+ }
return set.isEmpty() ? new BlockHeaderData().toBytes() : new BlockHeaderData(ForkSignalSet.of(set)).toBytes();
}
@@ -786,7 +794,7 @@ protected boolean validateBlock(Block block, AccountState asTrack, DelegateState
}
// [2] check transactions
- if (!block.validateTransactions(header, transactions, config.network())) {
+ if (!block.validateTransactions(header, transactions, config.network(), isForkActivated(Fork.ED25519_CONTRACT))) {
logger.error("Invalid transactions");
return false;
}
@@ -797,7 +805,7 @@ protected boolean validateBlock(Block block, AccountState asTrack, DelegateState
// [3] evaluate transactions
TransactionExecutor transactionExecutor = new TransactionExecutor(config, blockStore, isVMEnabled(),
- isVotingPrecompiledUpgraded());
+ isVotingPrecompiledUpgraded(), isEd25519ContractEnabled());
List results = transactionExecutor.execute(transactions, asTrack, dsTrack,
new SemuxBlock(block.getHeader(), config.spec().maxBlockGasLimit()),
0);
@@ -910,6 +918,10 @@ protected void activateForks() {
&& forks.activateFork(VOTING_PRECOMPILED_UPGRADE)) {
setActivatedForks(forks.getActivatedForks());
}
+ if (config.forkEd25519ContractEnabled()
+ && forks.activateFork(ED25519_CONTRACT)) {
+ setActivatedForks(forks.getActivatedForks());
+ }
}
/**
diff --git a/src/main/java/org/semux/core/Fork.java b/src/main/java/org/semux/core/Fork.java
index a35c6ae8b..099306845 100644
--- a/src/main/java/org/semux/core/Fork.java
+++ b/src/main/java/org/semux/core/Fork.java
@@ -29,7 +29,14 @@ public enum Fork implements Comparable {
/**
* This soft fork introduces an upgrade to the voting pre-compiled contracts.
*/
- VOTING_PRECOMPILED_UPGRADE((short) 3, 1500, 2000);
+ VOTING_PRECOMPILED_UPGRADE((short) 3, 1500, 2000),
+
+ /**
+ * This soft fork adds:
+ * - new pre-compiled contracts for ED25519 as well as will
+ * - new TX hash
+ */
+ ED25519_CONTRACT((short) 4, 1500, 2000);
/**
* An unique number of this fork.
diff --git a/src/main/java/org/semux/core/PendingManager.java b/src/main/java/org/semux/core/PendingManager.java
index 29318dc44..e306a136b 100644
--- a/src/main/java/org/semux/core/PendingManager.java
+++ b/src/main/java/org/semux/core/PendingManager.java
@@ -167,7 +167,7 @@ public synchronized void addTransaction(Transaction tx) {
if (queue.size() < QUEUE_SIZE_LIMIT
&& processedTxs.getIfPresent(hash) == null
- && tx.validate(kernel.getConfig().network())) {
+ && tx.validate_verify_sign(kernel.getConfig().network(), kernel.getBlockchain().isForkActivated(Fork.ED25519_CONTRACT))) {
// NOTE: re-insertion doesn't affect item order
queue.put(ByteArray.of(tx.getHash()), tx);
}
@@ -186,7 +186,7 @@ public synchronized ProcessingResult addTransactionSync(Transaction tx) {
return new ProcessingResult(0, TransactionResult.Code.INVALID_NONCE);
}
- if (tx.validate(kernel.getConfig().network())) {
+ if (tx.validate_verify_sign(kernel.getConfig().network(), kernel.getBlockchain().isForkActivated(Fork.ED25519_CONTRACT))) {
// proceed with the tx, ignoring transaction queue size limit
return processTransaction(tx, false, true);
} else {
@@ -352,7 +352,8 @@ protected ProcessingResult processTransaction(Transaction tx, boolean isIncluded
AccountState as = pendingAS.track();
DelegateState ds = pendingDS.track();
TransactionResult result = new TransactionExecutor(kernel.getConfig(), blockStore,
- kernel.getBlockchain().isVMEnabled(), kernel.getBlockchain().isVotingPrecompiledUpgraded())
+ kernel.getBlockchain().isVMEnabled(), kernel.getBlockchain().isVotingPrecompiledUpgraded(),
+ kernel.getBlockchain().isEd25519ContractEnabled())
.execute(tx, as, ds, dummyBlock, 0);
if (result.getCode().isAcceptable()) {
diff --git a/src/main/java/org/semux/core/Transaction.java b/src/main/java/org/semux/core/Transaction.java
index 529f10ff0..0926fcaef 100644
--- a/src/main/java/org/semux/core/Transaction.java
+++ b/src/main/java/org/semux/core/Transaction.java
@@ -20,8 +20,11 @@
import org.semux.crypto.Key.Signature;
import org.semux.util.SimpleDecoder;
import org.semux.util.SimpleEncoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class Transaction {
+ private static final Logger logger = LoggerFactory.getLogger(Transaction.class);
private final byte networkId;
@@ -54,6 +57,7 @@ public class Transaction {
* @param network
* @param type
* @param to
+ * @param from
* @param value
* @param fee
* @param nonce
@@ -61,9 +65,10 @@ public class Transaction {
* @param data
* @param gas
* @param gasPrice
+ * @param isFixTxHash
*/
- public Transaction(Network network, TransactionType type, byte[] to, Amount value, Amount fee, long nonce,
- long timestamp, byte[] data, long gas, Amount gasPrice) {
+ public Transaction(Network network, TransactionType type, byte[] to, byte[] from, Amount value, Amount fee, long nonce,
+ long timestamp, byte[] data, long gas, Amount gasPrice, boolean isFixTxHash) {
this.networkId = network.id();
this.type = type;
this.to = to;
@@ -90,7 +95,9 @@ public Transaction(Network network, TransactionType type, byte[] to, Amount valu
enc.writeAmount(gasPrice);
}
this.encoded = enc.toBytes();
- this.hash = Hash.h256(encoded);
+ this.hash = Hash.h256_s(encoded, isFixTxHash ? from : null);
+
+ logger.info("!!! isFixTxHash = " + isFixTxHash);
}
/**
@@ -99,11 +106,14 @@ public Transaction(Network network, TransactionType type, byte[] to, Amount valu
* @param hash
* @param encoded
* @param signature
+ * @param isFixTxHash
*/
- private Transaction(byte[] hash, byte[] encoded, byte[] signature) {
+ private Transaction(byte[] hash, byte[] encoded, byte[] signature, boolean isFixTxHash) {
this.hash = hash;
+
+ this.signature = Signature.fromBytes(signature);
- Transaction decodedTx = fromEncoded(encoded);
+ Transaction decodedTx = fromEncoded(encoded, this.signature.getAddress(), isFixTxHash);
this.networkId = decodedTx.networkId;
this.type = decodedTx.type;
this.to = decodedTx.to;
@@ -117,12 +127,13 @@ private Transaction(byte[] hash, byte[] encoded, byte[] signature) {
this.gasPrice = decodedTx.gasPrice;
this.encoded = encoded;
- this.signature = Signature.fromBytes(signature);
+
+ logger.info("isFixTxHash = " + isFixTxHash);
}
- public Transaction(Network network, TransactionType type, byte[] toAddress, Amount value, Amount fee, long nonce,
- long timestamp, byte[] data) {
- this(network, type, toAddress, value, fee, nonce, timestamp, data, 0, Amount.ZERO);
+ public Transaction(Network network, TransactionType type, byte[] toAddress, byte[] fromAddress, Amount value, Amount fee, long nonce,
+ long timestamp, byte[] data, boolean isFixTxHash) {
+ this(network, type, toAddress, fromAddress, value, fee, nonce, timestamp, data, 0, Amount.ZERO, isFixTxHash);
}
public boolean isVMTransaction() {
@@ -154,9 +165,13 @@ public Transaction sign(Key key) {
* Whether to verify the transaction signature or not. This is useful
* when there are multiple transaction signatures that can be
* verified in batch for performance reason.
+ * @param isFixTxHash
* @return true if success, otherwise false
*/
- public boolean validate(Network network, boolean verifySignature) {
+ private boolean validate(Network network, boolean verifySignature, boolean isFixTxHash) {
+
+ logger.info("isFixTxHash = " + isFixTxHash);
+
return hash != null && hash.length == Hash.HASH_LEN
&& networkId == network.id()
&& type != null
@@ -171,7 +186,7 @@ public boolean validate(Network network, boolean verifySignature) {
&& encoded != null
&& signature != null && !Arrays.equals(signature.getAddress(), EMPTY_ADDRESS)
- && Arrays.equals(Hash.h256(encoded), hash)
+ && Arrays.equals(Hash.h256_s(encoded, isFixTxHash ? signature.getAddress() : null), hash)
&& (!verifySignature || Key.verify(hash, signature))
// The coinbase key is publicly available. People can use it for transactions.
@@ -182,8 +197,12 @@ public boolean validate(Network network, boolean verifySignature) {
&& !Arrays.equals(to, Constants.COINBASE_ADDRESS)));
}
- public boolean validate(Network network) {
- return validate(network, true);
+ public boolean validate_verify_sign(Network network, boolean isFixTxHash) {
+ return validate(network, true, isFixTxHash);
+ }
+
+ public boolean validate_no_verify_sign(Network network, boolean isFixTxHash) {
+ return validate(network, false, isFixTxHash);
}
/**
@@ -293,9 +312,14 @@ public Amount getGasPrice() {
*
* @param encoded
* the bytes of encoded transaction
+ * @param from
+ * @param isFixTxHash
* @return the decoded transaction
*/
- public static Transaction fromEncoded(byte[] encoded) {
+ public static Transaction fromEncoded(byte[] encoded, byte[] from, boolean isFixTxHash) {
+
+ System.out.println("isFixTxHash = " + isFixTxHash);
+
SimpleDecoder decoder = new SimpleDecoder(encoded);
byte networkId = decoder.readByte();
@@ -316,8 +340,8 @@ public static Transaction fromEncoded(byte[] encoded) {
gasPrice = decoder.readAmount();
}
- return new Transaction(Network.of(networkId), transactionType, to, value, fee, nonce, timestamp, data,
- gas, gasPrice);
+ return new Transaction(Network.of(networkId), transactionType, to, from, value, fee, nonce, timestamp, data,
+ gas, gasPrice, isFixTxHash);
}
/**
@@ -347,6 +371,7 @@ public byte[] toBytes() {
* Parses from a byte array.
*
* @param bytes
+ * @param isFixTxHash
* @return
*/
public static Transaction fromBytes(byte[] bytes) {
@@ -355,7 +380,7 @@ public static Transaction fromBytes(byte[] bytes) {
byte[] encoded = dec.readBytes();
byte[] signature = dec.readBytes();
- return new Transaction(hash, encoded, signature);
+ return new Transaction(hash, encoded, signature, false);
}
/**
diff --git a/src/main/java/org/semux/core/TransactionExecutor.java b/src/main/java/org/semux/core/TransactionExecutor.java
index f5c9fa3d3..cdd9404d5 100644
--- a/src/main/java/org/semux/core/TransactionExecutor.java
+++ b/src/main/java/org/semux/core/TransactionExecutor.java
@@ -88,6 +88,7 @@ public static boolean validateDelegateName(byte[] data) {
private BlockStore blockStore;
private boolean isVMEnabled;
private boolean isVotingPrecompiledUpgraded;
+ private boolean isEd25519ContractEnabled;
/**
* Creates a new transaction executor.
@@ -95,11 +96,12 @@ public static boolean validateDelegateName(byte[] data) {
* @param config
*/
public TransactionExecutor(Config config, BlockStore blockStore, boolean isVMEnabled,
- boolean isVotingPrecompiledUpgraded) {
+ boolean isVotingPrecompiledUpgraded, boolean isEd25519ContractEnabled) {
this.spec = config.spec();
this.blockStore = blockStore;
this.isVMEnabled = isVMEnabled;
this.isVotingPrecompiledUpgraded = isVotingPrecompiledUpgraded;
+ this.isEd25519ContractEnabled = isEd25519ContractEnabled;
}
/**
@@ -319,6 +321,15 @@ private void executeVmTransaction(Transaction tx, AccountState as, DelegateState
byte[] returnData = receipt.getReturnData();
// NOTE: the following code is to simulate the behaviour of old clients
+ if (!isEd25519ContractEnabled) {
+ // Calling to a non existant precompiled contract just returns success/empty
+ //
+ if (DataWord.of(tx.getTo()).equals(DataWord.of(0x9))) {
+ code = Code.SUCCESS;
+ returnData = Bytes.EMPTY_BYTES;
+ gasUsed = tx.getGas();
+ }
+ }
if (!isVotingPrecompiledUpgraded) {
// the old GetVote and GetVotes precompiled contracts always fail
if (DataWord.of(tx.getTo()).equals(DataWord.of(102))
diff --git a/src/main/java/org/semux/core/Wallet.java b/src/main/java/org/semux/core/Wallet.java
index 6d84fbb91..d9f434822 100644
--- a/src/main/java/org/semux/core/Wallet.java
+++ b/src/main/java/org/semux/core/Wallet.java
@@ -141,11 +141,11 @@ public boolean unlock(String password) {
switch (version) {
case 1:
- key = Hash.h256(Bytes.of(password));
+ key = Hash.h256_s(Bytes.of(password), null);
newAccounts = readAccounts(key, dec, false, version);
break;
case 2:
- key = Hash.h256(Bytes.of(password));
+ key = Hash.h256_s(Bytes.of(password), null);
newAccounts = readAccounts(key, dec, true, version);
newAliases = readAddressAliases(key, dec);
break;
diff --git a/src/main/java/org/semux/crypto/Hash.java b/src/main/java/org/semux/crypto/Hash.java
index b17f722c7..2c0b05cd3 100644
--- a/src/main/java/org/semux/crypto/Hash.java
+++ b/src/main/java/org/semux/crypto/Hash.java
@@ -28,16 +28,19 @@ public class Hash {
* Generate the 256-bit hash.
*
* @param input
+ * @param salt
* @return
*/
- public static byte[] h256(byte[] input) {
+ public static byte[] h256_s(byte[] input, byte[] salt) {
if (Native.isEnabled()) {
- return Native.h256(input);
+ return Native.h256(input, salt);
} else {
try {
MessageDigest digest = MessageDigest.getInstance(Constants.HASH_ALGORITHM);
- return digest.digest(input);
+ digest.update(input);
+ digest.update(salt);
+ return digest.digest();
} catch (Exception e) {
throw new CryptoException(e);
}
@@ -49,14 +52,15 @@ public static byte[] h256(byte[] input) {
*
* @param one
* @param two
+ * @param salt
* @return
*/
- public static byte[] h256(byte[] one, byte[] two) {
+ public static byte[] h256_s(byte[] one, byte[] two, byte[] salt) {
byte[] all = new byte[one.length + two.length];
System.arraycopy(one, 0, all, 0, one.length);
System.arraycopy(two, 0, all, one.length, two.length);
- return Hash.h256(all);
+ return Hash.h256_s(all, null);
}
/**
@@ -70,7 +74,7 @@ public static byte[] h160(byte[] input) {
return Native.h160(input);
} else {
try {
- byte[] h256 = h256(input);
+ byte[] h256 = h256_s(input, null);
RIPEMD160Digest digest = new RIPEMD160Digest();
digest.update(h256, 0, h256.length);
diff --git a/src/main/java/org/semux/crypto/Native.java b/src/main/java/org/semux/crypto/Native.java
index b7bfe7fc1..4baf64a8a 100644
--- a/src/main/java/org/semux/crypto/Native.java
+++ b/src/main/java/org/semux/crypto/Native.java
@@ -122,9 +122,10 @@ public static void enable() {
* Computes the 256-bit hash. See {@link Hash#h256(byte[])}
*
* @param data
+ * @param salt (blake2b)
* @return
*/
- public static native byte[] h256(byte[] data);
+ public static native byte[] h256(byte[] data, byte[] salt);
/**
* Computes the 160-bit hash. See {@link Hash#h160(byte[])}
diff --git a/src/main/java/org/semux/gui/TransactionSender.java b/src/main/java/org/semux/gui/TransactionSender.java
index e4aa2b864..b0fab681f 100644
--- a/src/main/java/org/semux/gui/TransactionSender.java
+++ b/src/main/java/org/semux/gui/TransactionSender.java
@@ -9,6 +9,7 @@
import org.semux.Kernel;
import org.semux.Network;
import org.semux.core.Amount;
+import org.semux.core.Fork;
import org.semux.core.PendingManager;
import org.semux.core.Transaction;
import org.semux.core.TransactionType;
@@ -30,7 +31,7 @@ public static PendingManager.ProcessingResult send(Kernel kernel, WalletAccount
byte[] from = account.getKey().toAddress();
long nonce = pendingMgr.getNonce(from);
long timestamp = TimeUtil.currentTimeMillis();
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data, gas, gasPrice);
+ Transaction tx = new Transaction(network, type, to, from, value, fee, nonce, timestamp, data, gas, gasPrice, kernel.getBlockchain().isForkActivated(Fork.ED25519_CONTRACT));
tx.sign(account.getKey());
return pendingMgr.addTransactionSync(tx);
diff --git a/src/main/java/org/semux/util/MerkleTree.java b/src/main/java/org/semux/util/MerkleTree.java
index eb1629b36..a68fce75d 100644
--- a/src/main/java/org/semux/util/MerkleTree.java
+++ b/src/main/java/org/semux/util/MerkleTree.java
@@ -93,7 +93,7 @@ private Node build(List nodes) {
Node left = nodes.get(i);
if (i + 1 < nodes.size()) {
Node right = nodes.get(i + 1);
- list.add(new Node(Hash.h256(left.value, right.value), left, right));
+ list.add(new Node(Hash.h256_s(left.value, right.value, null), left, right));
} else {
list.add(new Node(left.value, left, null));
}
diff --git a/src/main/java/org/semux/util/MerkleUtil.java b/src/main/java/org/semux/util/MerkleUtil.java
index d8427fbd1..b57f4ee55 100644
--- a/src/main/java/org/semux/util/MerkleUtil.java
+++ b/src/main/java/org/semux/util/MerkleUtil.java
@@ -40,7 +40,7 @@ public static byte[] computeTransactionsRoot(List txs) {
public static byte[] computeResultsRoot(List results) {
List hashes = new ArrayList<>();
for (TransactionResult tx : results) {
- hashes.add(Hash.h256(tx.toBytesForMerkle()));
+ hashes.add(Hash.h256_s(tx.toBytesForMerkle(), null));
}
return new MerkleTree(hashes).getRootHash();
}
diff --git a/src/main/java/org/semux/vm/client/Ed25519Vfy.java b/src/main/java/org/semux/vm/client/Ed25519Vfy.java
new file mode 100644
index 000000000..61a681159
--- /dev/null
+++ b/src/main/java/org/semux/vm/client/Ed25519Vfy.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2017-2018 The Semux Developers
+ *
+ * Distributed under the MIT software license, see the accompanying file
+ * LICENSE or https://opensource.org/licenses/mit-license.php
+ */
+package org.semux.vm.client;
+
+import java.util.Arrays;
+
+import org.ethereum.vm.chainspec.PrecompiledContract;
+import org.ethereum.vm.chainspec.PrecompiledContractContext;
+import org.ethereum.vm.util.Pair;
+import org.semux.crypto.Key;
+import org.semux.util.Bytes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of
+ * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-665.md
+ */
+public class Ed25519Vfy implements PrecompiledContract {
+ private static final Logger logger = LoggerFactory.getLogger(Ed25519Vfy.class);
+
+ // any non-zero value indicates a signature verification failure
+ public static final Pair signatureVerificationFailure = new Pair<>(true, new byte[] { 1 });
+
+ @Override
+ public long getGasForData(byte[] bytes) {
+ return 2000;
+ }
+
+ @Override
+ public Pair execute(PrecompiledContractContext context) {
+
+ byte[] data = context.getInternalTransaction().getData();
+
+ if (data == null || data.length != 128) {
+ return SemuxPrecompiledContracts.failure;
+ }
+
+ /**
+ * ED25519VFY takes as input 128 octets:
+ *
+ * message: the 32-octet message that was signed public key: the 32-octet
+ * Ed25519 public key of the signer signature: the 64-octet Ed25519 signature
+ */
+ byte[] message = Arrays.copyOfRange(data, 0, 32);
+ byte[] publicKey = Arrays.copyOfRange(data, 32, 64);
+ byte[] signature = Arrays.copyOfRange(data, 64, 128);
+
+ byte[] semSignature = Bytes.merge(signature, publicKey);
+
+ boolean isValidSignature = false;
+ try {
+ Key.Signature sig = Key.Signature.fromBytes(semSignature);
+ if (sig != null) {
+ if (Key.verify(message, sig)) {
+ isValidSignature = true;
+ }
+ }
+ } catch (Exception e) {
+ logger.info("Exception while verifying signature", e);
+ return SemuxPrecompiledContracts.failure;
+ }
+
+ return isValidSignature ? SemuxPrecompiledContracts.success : signatureVerificationFailure;
+ }
+}
diff --git a/src/main/java/org/semux/vm/client/SemuxPrecompiledContracts.java b/src/main/java/org/semux/vm/client/SemuxPrecompiledContracts.java
index 51cf7b2b0..ae30d03b5 100644
--- a/src/main/java/org/semux/vm/client/SemuxPrecompiledContracts.java
+++ b/src/main/java/org/semux/vm/client/SemuxPrecompiledContracts.java
@@ -33,14 +33,18 @@ public class SemuxPrecompiledContracts extends ConstantinoplePrecompiledContract
private static final Unvote unvote = new Unvote();
private static final GetVotes getVotes = new GetVotes();
private static final GetVote getVote = new GetVote();
+ private static final Ed25519Vfy ed25519vfy = new Ed25519Vfy();
private static final DataWord voteAddr = DataWord.of(100);
private static final DataWord unvoteAddr = DataWord.of(101);
private static final DataWord getVotesAddr = DataWord.of(102);
private static final DataWord getVoteAddr = DataWord.of(103);
- private static final Pair success = new Pair<>(true, ArrayUtils.EMPTY_BYTE_ARRAY);
- private static final Pair failure = new Pair<>(false, ArrayUtils.EMPTY_BYTE_ARRAY);
+ // match the ethereum code, eip-665
+ private static final DataWord ed25519vfyAddr = DataWord.of(0x9);
+
+ public static final Pair success = new Pair<>(true, ArrayUtils.EMPTY_BYTE_ARRAY);
+ public static final Pair failure = new Pair<>(false, ArrayUtils.EMPTY_BYTE_ARRAY);
@Override
public PrecompiledContract getContractForAddress(DataWord address) {
@@ -53,6 +57,8 @@ public PrecompiledContract getContractForAddress(DataWord address) {
return getVotes;
} else if (address.equals(getVoteAddr)) {
return getVote;
+ } else if (address.equals(ed25519vfyAddr)) {
+ return ed25519vfy;
}
return super.getContractForAddress(address);
}
diff --git a/src/main/native/README.md b/src/main/native/README.md
index 7e6413e7e..da5abd320 100644
--- a/src/main/native/README.md
+++ b/src/main/native/README.md
@@ -25,6 +25,16 @@ Steps to build on Debian/Ubuntu based distributions with a x86_64 machine:
```
sudo apt install cmake automake autoconf gcc gcc-aarch64-linux-gnu gcc-mingw-w64 binutils binutils-aarch64-linux-gnu binutils-mingw-w64
+clone ed25519-donna:
+cd ../../native/crypto
+git clone https://github.com/floodyberry/ed25519-donna
+
+clone libsodium:
+cd ../../native/crypto
+git clone https://github.com/jedisct1/libsodium
+cd ./libsodium
+git checkout b732443c442239c2e0184820e9b23cca0de0828c
+
mkdir build && cd build
cmake -vvv -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain-Linux-x86_64.cmake ../
make -j$(nproc)
diff --git a/src/main/native/crypto/ed25519-donna b/src/main/native/crypto/ed25519-donna
index 68049dfa1..8757bd4cd 160000
--- a/src/main/native/crypto/ed25519-donna
+++ b/src/main/native/crypto/ed25519-donna
@@ -1 +1 @@
-Subproject commit 68049dfa1e44cb9a1113d216d1179a3d7cd087e5
+Subproject commit 8757bd4cd209cb032853ece0ce413f122eef212c
diff --git a/src/main/native/crypto/libsodium b/src/main/native/crypto/libsodium
index b732443c4..4f5e89fa8 160000
--- a/src/main/native/crypto/libsodium
+++ b/src/main/native/crypto/libsodium
@@ -1 +1 @@
-Subproject commit b732443c442239c2e0184820e9b23cca0de0828c
+Subproject commit 4f5e89fa84ce1d178a6765b8b46f2b6f91216677
diff --git a/src/main/native/crypto/org_semux_crypto_Native.cpp b/src/main/native/crypto/org_semux_crypto_Native.cpp
index 5fdfa3619..84daa2a76 100644
--- a/src/main/native/crypto/org_semux_crypto_Native.cpp
+++ b/src/main/native/crypto/org_semux_crypto_Native.cpp
@@ -8,7 +8,7 @@
#define ed25519_SIGNATUREBYTES 64U
JNIEXPORT jbyteArray JNICALL Java_org_semux_crypto_Native_h256
-(JNIEnv *env, jclass cls, jbyteArray msg)
+(JNIEnv *env, jclass cls, jbyteArray msg, jbyteArray salt)
{
// check inputs
if (msg == NULL) {
@@ -16,18 +16,34 @@ JNIEXPORT jbyteArray JNICALL Java_org_semux_crypto_Native_h256
return NULL;
}
- // read byte arrays
+ // read message bytes
jsize msg_size = env->GetArrayLength(msg);
jbyte *msg_buf = (jbyte *)malloc(msg_size);
env->GetByteArrayRegion(msg, 0, msg_size, msg_buf);
+ // read salt bytes
+ jsize salt_size = 0;
+ jbyte *salt_buf = NULL;
+
+ if (salt != NULL)
+ {
+ salt_size = env->GetArrayLength(salt);
+ salt_buf = (jbyte *)malloc(salt_size);
+ env->GetByteArrayRegion(salt, 0, salt_size, salt_buf);
+ }
+
// compute blake2b hash
unsigned char hash[crypto_generichash_blake2b_BYTES];
- crypto_generichash_blake2b(hash, sizeof(hash), (const unsigned char *)msg_buf, msg_size, NULL, 0);
+ crypto_generichash_blake2b(hash, sizeof(hash), (const unsigned char *)msg_buf, msg_size, (const unsigned char *)salt_buf, salt_size);
// release buffer
free(msg_buf);
+ if (salt_buf != NULL)
+ {
+ free(salt_buf);
+ }
+
jbyteArray result = env->NewByteArray(sizeof(hash));
env->SetByteArrayRegion(result, 0, sizeof(hash), (const jbyte*)hash);
return result;
@@ -42,14 +58,14 @@ JNIEXPORT jbyteArray JNICALL Java_org_semux_crypto_Native_h160
return NULL;
}
- // read byte arrays
+ // read message bytes
jsize msg_size = env->GetArrayLength(msg);
jbyte *msg_buf = (jbyte *)malloc(msg_size);
env->GetByteArrayRegion(msg, 0, msg_size, msg_buf);
// compute blake2b hash
unsigned char hash[crypto_generichash_blake2b_BYTES];
- crypto_generichash_blake2b(hash, sizeof(hash), (const unsigned char *)msg_buf, msg_size, NULL, 0);
+ crypto_generichash_blake2b(hash, sizeof(hash), (const unsigned char *)msg_buf, msg_size, NULL, 0);
// compute ripemd160 digest
unsigned char digest[20];
@@ -186,4 +202,4 @@ JNIEXPORT jboolean JNICALL Java_org_semux_crypto_Native_verifyBatch
delete[] valid;
return result;
-}
\ No newline at end of file
+}
diff --git a/src/main/native/crypto/org_semux_crypto_Native.h b/src/main/native/crypto/org_semux_crypto_Native.h
index 97a278db8..e0d506d52 100644
--- a/src/main/native/crypto/org_semux_crypto_Native.h
+++ b/src/main/native/crypto/org_semux_crypto_Native.h
@@ -10,10 +10,10 @@ extern "C" {
/*
* Class: org_semux_crypto_Native
* Method: h256
- * Signature: ([B)[B
+ * Signature: ([B[B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_semux_crypto_Native_h256
- (JNIEnv *, jclass, jbyteArray);
+ (JNIEnv *, jclass, jbyteArray, jbyteArray);
/*
* Class: org_semux_crypto_Native
diff --git a/src/main/resources/native/Darwin-x86_64/libsemuxcrypto.dylib b/src/main/resources/native/Darwin-x86_64/libsemuxcrypto.dylib
deleted file mode 100755
index 691b10c04..000000000
Binary files a/src/main/resources/native/Darwin-x86_64/libsemuxcrypto.dylib and /dev/null differ
diff --git a/src/main/resources/native/Linux-aarch64/libsemuxcrypto.so b/src/main/resources/native/Linux-aarch64/libsemuxcrypto.so
index 8d5f417eb..d823c3645 100755
Binary files a/src/main/resources/native/Linux-aarch64/libsemuxcrypto.so and b/src/main/resources/native/Linux-aarch64/libsemuxcrypto.so differ
diff --git a/src/main/resources/native/Linux-x86_64/libsemuxcrypto.so b/src/main/resources/native/Linux-x86_64/libsemuxcrypto.so
index 3f844d2d6..2b0c67b7e 100755
Binary files a/src/main/resources/native/Linux-x86_64/libsemuxcrypto.so and b/src/main/resources/native/Linux-x86_64/libsemuxcrypto.so differ
diff --git a/src/main/resources/native/Windows-x86_64/libsemuxcrypto.dll b/src/main/resources/native/Windows-x86_64/libsemuxcrypto.dll
deleted file mode 100755
index e67c41d40..000000000
Binary files a/src/main/resources/native/Windows-x86_64/libsemuxcrypto.dll and /dev/null differ
diff --git a/src/test/java/org/semux/TestUtils.java b/src/test/java/org/semux/TestUtils.java
index 7c56ad692..98aba80b7 100644
--- a/src/test/java/org/semux/TestUtils.java
+++ b/src/test/java/org/semux/TestUtils.java
@@ -69,7 +69,7 @@ public static Transaction createTransaction(Config config, TransactionType type,
long timestamp = TimeUtil.currentTimeMillis();
byte[] data = {};
- return new Transaction(network, type, to.toAddress(), value, fee, nonce, timestamp, data).sign(from);
+ return new Transaction(network, type, to.toAddress(), from.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled()).sign(from);
}
// Source:
diff --git a/src/test/java/org/semux/api/http/HttpHandlerTest.java b/src/test/java/org/semux/api/http/HttpHandlerTest.java
index 45cf6b8a6..4280dbba8 100644
--- a/src/test/java/org/semux/api/http/HttpHandlerTest.java
+++ b/src/test/java/org/semux/api/http/HttpHandlerTest.java
@@ -32,6 +32,7 @@
import org.semux.api.SemuxApiService;
import org.semux.config.Config;
import org.semux.core.Amount;
+import org.semux.core.Fork;
import org.semux.core.Transaction;
import org.semux.core.TransactionType;
import org.semux.crypto.Hex;
@@ -151,14 +152,19 @@ public void testGET() throws IOException {
@Test
public void testGETBigData() throws IOException {
Config config = kernelRule.getKernel().getConfig();
+
+ Key key = new Key();
+
+ final boolean isFixTxHashActivated = kernelRule.getKernel().getBlockchain().isForkActivated(Fork.ED25519_CONTRACT);
+
Transaction tx = new Transaction(config.network(),
- TransactionType.CALL, Bytes.random(20),
+ TransactionType.CALL, Bytes.random(20)/*to*/, key.toAddress()/*from*/,
Amount.ZERO, Amount.ZERO, 0,
TimeUtil.currentTimeMillis(),
new byte[config.spec().maxTransactionDataSize(TransactionType.CALL)],
- 5_000_000L, Amount.of(100));
- tx.sign(new Key());
- assertTrue(tx.validate(config.network()));
+ 5_000_000L, Amount.of(100), isFixTxHashActivated);
+ tx.sign(key);
+ assertTrue(tx.validate_verify_sign(config.network(), isFixTxHashActivated));
URL url = new URL(
"http://" + ip + ":" + port + "/broadcast-raw-transactions?raw=" + Hex.encode0x(tx.toBytes()));
diff --git a/src/test/java/org/semux/api/util/TransactionBuilderTest.java b/src/test/java/org/semux/api/util/TransactionBuilderTest.java
index d50eefd43..f48ecb566 100644
--- a/src/test/java/org/semux/api/util/TransactionBuilderTest.java
+++ b/src/test/java/org/semux/api/util/TransactionBuilderTest.java
@@ -19,6 +19,7 @@
import org.semux.core.Amount;
import org.semux.core.Transaction;
import org.semux.core.TransactionType;
+import org.semux.util.Bytes;
public class TransactionBuilderTest {
@@ -41,7 +42,7 @@ public void testDelegateWithWrongValue() {
.withValue("6")
.withNonce("7")
.withFee("8")
- .buildUnsigned();
+ .buildUnsigned(Bytes.random(20));
assertEquals(Amount.of(6), tx.getValue());
assertEquals(7L, tx.getNonce());
}
diff --git a/src/test/java/org/semux/bench/BlockchainPerformance.java b/src/test/java/org/semux/bench/BlockchainPerformance.java
index 47c8b5d18..6c14002dc 100644
--- a/src/test/java/org/semux/bench/BlockchainPerformance.java
+++ b/src/test/java/org/semux/bench/BlockchainPerformance.java
@@ -54,7 +54,7 @@ public static Block testBlockCreation() {
long nonce = 1 + i;
long timestamp = TimeUtil.currentTimeMillis();
byte[] data = Bytes.EMPTY_BYTES;
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data).sign(key);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled()).sign(key);
txs.add(tx);
res.add(new TransactionResult());
@@ -97,7 +97,7 @@ public static void testBlockValidation(Block block) {
long t1 = System.nanoTime();
block.validateHeader(block.getHeader(), genesis.getHeader());
- block.validateTransactions(block.getHeader(), block.getTransactions(), config.network());
+ block.validateTransactions(block.getHeader(), block.getTransactions(), config.network(), config.forkEd25519ContractEnabled());
block.validateResults(block.getHeader(), block.getResults());
// block votes validation skipped
long t2 = System.nanoTime();
@@ -116,13 +116,13 @@ public static void testTransactionValidation() {
long nonce = 1;
long timestamp = TimeUtil.currentTimeMillis();
byte[] data = {};
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled());
tx.sign(key);
int repeat = 1000;
long t1 = System.nanoTime();
for (int i = 0; i < repeat; i++) {
- tx.validate(network);
+ tx.validate_verify_sign(network, config.forkEd25519ContractEnabled());
}
long t2 = System.nanoTime();
logger.info("Perf_transaction_size: {} B", tx.toBytes().length);
diff --git a/src/test/java/org/semux/bench/CryptoPerformance.java b/src/test/java/org/semux/bench/CryptoPerformance.java
index e0dbe1dfc..2088be767 100644
--- a/src/test/java/org/semux/bench/CryptoPerformance.java
+++ b/src/test/java/org/semux/bench/CryptoPerformance.java
@@ -23,7 +23,7 @@ public static void testH256() {
long t1 = System.nanoTime();
for (int i = 0; i < REPEAT; i++) {
- Hash.h256(data);
+ Hash.h256_s(data, null);
}
long t2 = System.nanoTime();
@@ -49,7 +49,7 @@ public static void testSign() {
for (int size : DATA_SIZES) {
Key eckey = new Key();
byte[] data = new byte[size];
- byte[] hash = Hash.h256(data);
+ byte[] hash = Hash.h256_s(data, null);
long t1 = System.nanoTime();
for (int i = 0; i < REPEAT; i++) {
@@ -65,7 +65,7 @@ public static void testVerify() {
for (int size : DATA_SIZES) {
Key eckey = new Key();
byte[] data = new byte[size];
- byte[] hash = Hash.h256(data);
+ byte[] hash = Hash.h256_s(data, null);
byte[] sig = eckey.sign(hash).toBytes();
long t1 = System.nanoTime();
diff --git a/src/test/java/org/semux/bench/VMPerformance.java b/src/test/java/org/semux/bench/VMPerformance.java
index 136e2f49c..2c15154c1 100644
--- a/src/test/java/org/semux/bench/VMPerformance.java
+++ b/src/test/java/org/semux/bench/VMPerformance.java
@@ -78,7 +78,7 @@ public static void main(String[] args) throws Throwable {
byte[] data = Bytes.merge(Hex.decode0x("9c438a3d"), Bytes.of(j)); // sha1()
long gas = 100_000L;
Amount gasPrice = Amount.of(10);
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data, gas, gasPrice)
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled())
.sign(key);
txs.add(tx);
res.add(new TransactionResult());
diff --git a/src/test/java/org/semux/consensus/ProposalTest.java b/src/test/java/org/semux/consensus/ProposalTest.java
index 3b72cdbc2..d8e75f545 100644
--- a/src/test/java/org/semux/consensus/ProposalTest.java
+++ b/src/test/java/org/semux/consensus/ProposalTest.java
@@ -41,8 +41,9 @@ public void testBasics() {
long timestamp = TimeUtil.currentTimeMillis();
byte[] data = Bytes.of("data");
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data);
- tx.sign(new Key());
+ Key key1 = new Key();
+ Transaction tx = new Transaction(network, type, to, key1.toAddress(), value, fee, nonce, timestamp, data, true);
+ tx.sign(key1);
TransactionResult res = new TransactionResult();
long height = Long.MAX_VALUE;
diff --git a/src/test/java/org/semux/consensus/SemuxBftTest.java b/src/test/java/org/semux/consensus/SemuxBftTest.java
index 2d47e74c1..ff23d1c3c 100644
--- a/src/test/java/org/semux/consensus/SemuxBftTest.java
+++ b/src/test/java/org/semux/consensus/SemuxBftTest.java
@@ -265,10 +265,12 @@ private Transaction createTransaction(Key to, Key from, long time, long nonce) {
kernelRule.getKernel().getConfig().network(),
TransactionType.TRANSFER,
to.toAddress(),
+ from.toAddress(),
Amount.of(10, SEM),
kernelRule.getKernel().getConfig().spec().minTransactionFee(),
nonce,
time,
- Bytes.EMPTY_BYTES).sign(from);
+ Bytes.EMPTY_BYTES,
+ kernelRule.getKernel().getConfig().forkEd25519ContractEnabled()).sign(from);
}
}
diff --git a/src/test/java/org/semux/core/BlockTest.java b/src/test/java/org/semux/core/BlockTest.java
index 41a71fa2a..f9c497b6f 100644
--- a/src/test/java/org/semux/core/BlockTest.java
+++ b/src/test/java/org/semux/core/BlockTest.java
@@ -38,11 +38,18 @@ public class BlockTest {
private long timestamp = TimeUtil.currentTimeMillis();
private byte[] data = Bytes.of("data");
- private Transaction tx = new Transaction(Network.DEVNET, TransactionType.TRANSFER, Bytes.random(20), ZERO,
- config.spec().minTransactionFee(),
- 1, TimeUtil.currentTimeMillis(), Bytes.EMPTY_BYTES).sign(new Key());
+ private Transaction NewTx ()
+ {
+ Key key = new Key();
+
+ return new Transaction(Network.DEVNET, TransactionType.TRANSFER, Bytes.random(20), key.toAddress(), ZERO,
+ config.spec().minTransactionFee(),
+ 1, TimeUtil.currentTimeMillis(), Bytes.EMPTY_BYTES,
+ config.forkEd25519ContractEnabled()).sign(key);
+ }
+
private TransactionResult res = new TransactionResult();
- private List transactions = Collections.singletonList(tx);
+ private List transactions = Collections.singletonList(NewTx());
private List results = Collections.singletonList(res);
private int view = 1;
private List votes = new ArrayList<>();
@@ -107,7 +114,7 @@ public void testTransactionIndexes() {
Integer index = indexes.getRight().get(0);
SimpleDecoder dec = new SimpleDecoder(block.getEncodedTransactions(), index);
Transaction tx2 = Transaction.fromBytes(dec.readBytes());
- assertArrayEquals(tx.getHash(), tx2.getHash());
+ assertArrayEquals(NewTx().getHash(), tx2.getHash());
}
@Test
@@ -119,7 +126,7 @@ public void testValidateTransactions() {
Block block = new Block(header, transactions);
assertTrue(block.validateHeader(header, previousHeader));
- assertTrue(block.validateTransactions(previousHeader, transactions, Network.DEVNET));
+ assertTrue(block.validateTransactions(previousHeader, transactions, Network.DEVNET, config.forkEd25519ContractEnabled()));
assertTrue(block.validateResults(previousHeader, results));
}
@@ -133,7 +140,7 @@ public void testValidateTransactionsSparse() {
assertTrue(block.validateHeader(header, previousHeader));
assertTrue(block.validateTransactions(previousHeader, Collections.singleton(transactions.get(0)), transactions,
- Network.DEVNET));
+ Network.DEVNET, config.forkEd25519ContractEnabled()));
assertTrue(block.validateResults(previousHeader, results));
}
}
diff --git a/src/test/java/org/semux/core/BlockchainImplTest.java b/src/test/java/org/semux/core/BlockchainImplTest.java
index 35e5eded2..aaf0717be 100644
--- a/src/test/java/org/semux/core/BlockchainImplTest.java
+++ b/src/test/java/org/semux/core/BlockchainImplTest.java
@@ -55,8 +55,12 @@ public class BlockchainImplTest {
private long nonce = 12345;
private byte[] data = Bytes.of("test");
private long timestamp = TimeUtil.currentTimeMillis() - 60 * 1000;
- private Transaction tx = new Transaction(network, TransactionType.TRANSFER, to, value, fee, nonce, timestamp,
- data).sign(key);
+
+ private Transaction NewTx()
+ {
+ return new Transaction(network, TransactionType.TRANSFER, to, key.toAddress(), value, fee, nonce, timestamp,
+ data, chain.isForkActivated(Fork.ED25519_CONTRACT)).sign(key);
+ }
@Before
public void setUp() {
@@ -135,6 +139,8 @@ public void testGetBlockHeader() {
@Test
public void testGetTransaction() {
+ Transaction tx = NewTx();
+
assertNull(chain.getTransaction(tx.getHash()));
Block newBlock = createBlock(1);
@@ -152,6 +158,8 @@ public void testGetTransaction() {
@Test
public void testHasTransaction() {
+ Transaction tx = NewTx();
+
assertFalse(chain.hasTransaction(tx.getHash()));
Block newBlock = createBlock(1);
@@ -162,6 +170,8 @@ public void testHasTransaction() {
@Test
public void testGetTransactionResult() {
+ Transaction tx = NewTx();
+
assertNull(chain.getTransaction(tx.getHash()));
Block newBlock = createBlock(1);
@@ -173,6 +183,8 @@ public void testGetTransactionResult() {
@Test
public void testGetInternalTransaction() {
+ Transaction tx = NewTx();
+
assertNull(chain.getTransaction(tx.getHash()));
byte[] rootTxHash = Bytes.random(32);
@@ -218,6 +230,8 @@ public void testGetInternalTransaction() {
@Test
public void testGetTransactionBlockNumber() {
+ Transaction tx = NewTx();
+
Block newBlock = createBlock(1);
chain.addBlock(newBlock);
@@ -241,6 +255,8 @@ public void testGetCoinbaseTransactionBlockNumber() {
@Test
public void testGetTransactionCount() {
+ Transaction tx = NewTx();
+
assertNull(chain.getTransaction(tx.getHash()));
Block newBlock = createBlock(1);
@@ -251,6 +267,8 @@ public void testGetTransactionCount() {
@Test
public void testGetAccountTransactions() {
+ Transaction tx = NewTx();
+
assertNull(chain.getTransaction(tx.getHash()));
Block newBlock = createBlock(1);
@@ -264,7 +282,7 @@ public void testGetAccountTransactions() {
@Test
public void testSerialization() {
Block block1 = createBlock(1);
-
+
Block block2 = Block.fromComponents(block1.getEncodedHeader(), block1.getEncodedTransactions(),
block1.getEncodedResults(),
block1.getEncodedVotes());
@@ -278,6 +296,8 @@ public void testSerialization() {
@Test
public void testGetTransactions() {
+ Transaction tx = NewTx();
+
Block block = createBlock(1);
chain.addBlock(block);
@@ -292,8 +312,8 @@ public void testGetTransactions() {
@Test
public void testGetTransactionsSelfTx() {
- Transaction selfTx = new Transaction(network, TransactionType.TRANSFER, key.toAddress(), value, fee, nonce,
- timestamp, data).sign(key);
+ Transaction selfTx = new Transaction(network, TransactionType.TRANSFER, key.toAddress(), key.toAddress(), value, fee, nonce,
+ timestamp, data, chain.isForkActivated(Fork.ED25519_CONTRACT)).sign(key);
Block block = createBlock(
1,
Collections.singletonList(selfTx),
@@ -329,6 +349,8 @@ public void testValidatorStates() {
@Test
public void testForkActivated() {
+ Transaction tx = NewTx();
+
final Fork fork = Fork.UNIFORM_DISTRIBUTION;
for (long i = 1; i <= fork.blocksToCheck(); i++) {
chain.addBlock(
@@ -346,6 +368,8 @@ public void testForkActivated() {
@Test
public void testForkCompatibility() {
+ Transaction tx = NewTx();
+
Fork fork = Fork.UNIFORM_DISTRIBUTION;
Block block = createBlock(1, coinbase, new BlockHeaderData(ForkSignalSet.of(fork)).toBytes(),
Collections.singletonList(tx), Collections.singletonList(res));
@@ -355,6 +379,8 @@ public void testForkCompatibility() {
}
private Block createBlock(long number) {
+ Transaction tx = NewTx();
+
return createBlock(number, Collections.singletonList(tx), Collections.singletonList(res));
}
diff --git a/src/test/java/org/semux/core/BlockchainImportTest.java b/src/test/java/org/semux/core/BlockchainImportTest.java
index d505a9369..ebb5b6ca2 100644
--- a/src/test/java/org/semux/core/BlockchainImportTest.java
+++ b/src/test/java/org/semux/core/BlockchainImportTest.java
@@ -53,11 +53,13 @@ public void testDuplicatedTransaction() {
kernelRule.getKernel().getConfig().network(),
TransactionType.TRANSFER,
to.toAddress(),
+ from1.toAddress(),
Amount.of(10, SEM),
kernelRule.getKernel().getConfig().spec().minTransactionFee(),
0,
time,
- Bytes.EMPTY_BYTES).sign(from1);
+ Bytes.EMPTY_BYTES,
+ kernelRule.getKernel().getConfig().forkEd25519ContractEnabled()).sign(from1);
kernelRule.getKernel().setBlockchain(new BlockchainImpl(kernelRule.getKernel().getConfig(), temporaryDBRule));
kernelRule.getKernel().getBlockchain().getAccountState().adjustAvailable(from1.toAddress(), Amount.of(
1000, SEM));
@@ -72,11 +74,13 @@ public void testDuplicatedTransaction() {
kernelRule.getKernel().getConfig().network(),
TransactionType.TRANSFER,
to.toAddress(),
+ from2.toAddress(),
Amount.of(10, SEM),
kernelRule.getKernel().getConfig().spec().minTransactionFee(),
0,
time,
- Bytes.EMPTY_BYTES).sign(from2);
+ Bytes.EMPTY_BYTES,
+ kernelRule.getKernel().getConfig().forkEd25519ContractEnabled()).sign(from2);
Block block2 = kernelRule.createBlock(Collections.singletonList(tx2));
// this test case is valid if and only if tx1 and tx2 have the same tx hash
diff --git a/src/test/java/org/semux/core/CorePerformanceTest.java b/src/test/java/org/semux/core/CorePerformanceTest.java
index 9a6bfdcc6..4b06747f3 100644
--- a/src/test/java/org/semux/core/CorePerformanceTest.java
+++ b/src/test/java/org/semux/core/CorePerformanceTest.java
@@ -72,21 +72,21 @@ public void testTransactionProcessing() {
long timestamp = TimeUtil.currentTimeMillis();
byte[] data = Bytes.random(16);
- Transaction tx = new Transaction(Network.DEVNET, type, to, value, fee, nonce, timestamp, data);
+ Transaction tx = new Transaction(Network.DEVNET, type, to, key.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled());
tx.sign(key);
txs.add(tx);
}
long t1 = System.nanoTime();
for (Transaction tx : txs) {
- assertTrue(tx.validate(Network.DEVNET));
+ assertTrue(tx.validate_verify_sign(Network.DEVNET, config.forkEd25519ContractEnabled()));
}
long t2 = System.nanoTime();
logger.info("Perf_transaction_1: {} μs/tx", (t2 - t1) / 1_000 / repeat);
Blockchain chain = new BlockchainImpl(config, temporaryDBFactory);
TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), chain.isVMEnabled(),
- chain.isVotingPrecompiledUpgraded());
+ chain.isVotingPrecompiledUpgraded(), chain.isEd25519ContractEnabled());
t1 = System.nanoTime();
exec.execute(txs, chain.getAccountState().track(), chain.getDelegateState().track(),
diff --git a/src/test/java/org/semux/core/PendingManagerTest.java b/src/test/java/org/semux/core/PendingManagerTest.java
index e44619bad..4c73b604a 100644
--- a/src/test/java/org/semux/core/PendingManagerTest.java
+++ b/src/test/java/org/semux/core/PendingManagerTest.java
@@ -82,8 +82,9 @@ public void start() {
public void testGetTransaction() throws InterruptedException {
long now = TimeUtil.currentTimeMillis();
long nonce = accountState.getAccount(from).getNonce();
+ boolean isFixTxHash = kernel.getConfig().forkEd25519ContractEnabled();
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, now, Bytes.EMPTY_BYTES).sign(key);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, now, Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
pendingMgr.addTransaction(tx);
Thread.sleep(100);
@@ -94,10 +95,11 @@ public void testGetTransaction() throws InterruptedException {
public void testAddTransaction() throws InterruptedException {
long now = TimeUtil.currentTimeMillis();
long nonce = accountState.getAccount(from).getNonce();
+ boolean isFixTxHash = kernel.getConfig().forkEd25519ContractEnabled();
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, now, Bytes.EMPTY_BYTES).sign(key);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, now, Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
pendingMgr.addTransaction(tx);
- Transaction tx2 = new Transaction(network, type, to, value, fee, nonce + 128, now, Bytes.EMPTY_BYTES)
+ Transaction tx2 = new Transaction(network, type, to, key.toAddress(), value, fee, nonce + 128, now, Bytes.EMPTY_BYTES, isFixTxHash)
.sign(key);
pendingMgr.addTransaction(tx2);
@@ -107,7 +109,8 @@ public void testAddTransaction() throws InterruptedException {
@Test
public void testAddTransactionSyncErrorInvalidFormat() {
- Transaction tx = new Transaction(network, type, to, value, fee, 0, 0, Bytes.EMPTY_BYTES).sign(key);
+ boolean isFixTxHash = kernel.getConfig().forkEd25519ContractEnabled();
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, 0, 0, Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
PendingManager.ProcessingResult result = pendingMgr.addTransactionSync(tx);
assertEquals(0, pendingMgr.getPendingTransactions().size());
assertNotNull(result.error);
@@ -116,8 +119,9 @@ public void testAddTransactionSyncErrorInvalidFormat() {
@Test
public void testAddTransactionSyncErrorDuplicatedHash() {
- Transaction tx = new Transaction(network, type, to, value, fee, 0, TimeUtil.currentTimeMillis(),
- Bytes.EMPTY_BYTES)
+ boolean isFixTxHash = kernel.getConfig().forkEd25519ContractEnabled();
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, 0, TimeUtil.currentTimeMillis(),
+ Bytes.EMPTY_BYTES, isFixTxHash)
.sign(key);
kernel.setBlockchain(spy(kernel.getBlockchain()));
@@ -133,8 +137,9 @@ public void testAddTransactionSyncErrorDuplicatedHash() {
@Test
public void testAddTransactionSyncInvalidRecipient() {
- Transaction tx = new Transaction(network, type, Constants.COINBASE_KEY.toAddress(), value, fee, 0,
- TimeUtil.currentTimeMillis(), Bytes.EMPTY_BYTES)
+ boolean isFixTxHash = kernel.getConfig().forkEd25519ContractEnabled();
+ Transaction tx = new Transaction(network, type, Constants.COINBASE_KEY.toAddress(), key.toAddress(), value, fee, 0,
+ TimeUtil.currentTimeMillis(), Bytes.EMPTY_BYTES, isFixTxHash)
.sign(key);
PendingManager.ProcessingResult result = pendingMgr.addTransactionSync(tx);
@@ -145,18 +150,19 @@ public void testAddTransactionSyncInvalidRecipient() {
@Test
public void testNonceJump() throws InterruptedException {
- long now = TimeUtil.currentTimeMillis();
+ long now = TimeUtil.currentTimeMillis();
long nonce = accountState.getAccount(from).getNonce();
+ boolean isFixTxHash = kernel.getConfig().forkEd25519ContractEnabled();
- Transaction tx3 = new Transaction(network, type, to, value, fee, nonce + 2, now, Bytes.EMPTY_BYTES).sign(key);
+ Transaction tx3 = new Transaction(network, type, to, key.toAddress(), value, fee, nonce + 2, now, Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
pendingMgr.addTransaction(tx3);
- Transaction tx2 = new Transaction(network, type, to, value, fee, nonce + 1, now, Bytes.EMPTY_BYTES).sign(key);
+ Transaction tx2 = new Transaction(network, type, to, key.toAddress(), value, fee, nonce + 1, now, Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
pendingMgr.addTransaction(tx2);
Thread.sleep(100);
assertEquals(0, pendingMgr.getPendingTransactions().size());
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, now, Bytes.EMPTY_BYTES).sign(key);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, now, Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
pendingMgr.addTransaction(tx);
Thread.sleep(100);
@@ -167,18 +173,19 @@ public void testNonceJump() throws InterruptedException {
public void testNonceJumpTimestampError() throws InterruptedException {
long now = TimeUtil.currentTimeMillis();
long nonce = accountState.getAccount(from).getNonce();
+ boolean isFixTxHash = kernel.getConfig().forkEd25519ContractEnabled();
- Transaction tx3 = new Transaction(network, type, to, value, fee, nonce + 2,
+ Transaction tx3 = new Transaction(network, type, to, key.toAddress(), value, fee, nonce + 2,
now - TimeUnit.HOURS.toMillis(2) + TimeUnit.SECONDS.toMillis(1),
- Bytes.EMPTY_BYTES).sign(key);
+ Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
pendingMgr.addTransaction(tx3);
- Transaction tx2 = new Transaction(network, type, to, value, fee, nonce + 1, now, Bytes.EMPTY_BYTES).sign(key);
+ Transaction tx2 = new Transaction(network, type, to, key.toAddress(), value, fee, nonce + 1, now, Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
pendingMgr.addTransaction(tx2);
TimeUnit.SECONDS.sleep(1);
assertEquals(0, pendingMgr.getPendingTransactions().size());
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, now, Bytes.EMPTY_BYTES).sign(key);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, now, Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
pendingMgr.addTransaction(tx);
TimeUnit.SECONDS.sleep(1);
@@ -190,9 +197,10 @@ public void testNonceJumpTimestampError() throws InterruptedException {
public void testTimestampError() {
long now = TimeUtil.currentTimeMillis();
long nonce = accountState.getAccount(from).getNonce();
+ boolean isFixTxHash = kernel.getConfig().forkEd25519ContractEnabled();
- Transaction tx3 = new Transaction(network, type, to, value, fee, nonce, now - ALLOWED_TIME_DRIFT - 1,
- Bytes.EMPTY_BYTES).sign(key);
+ Transaction tx3 = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, now - ALLOWED_TIME_DRIFT - 1,
+ Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
PendingManager.ProcessingResult result = pendingMgr.addTransactionSync(tx3);
assertEquals(INVALID_TIMESTAMP, result.error);
}
@@ -201,10 +209,11 @@ public void testTimestampError() {
public void testHighVolumeTransaction() throws InterruptedException {
long now = TimeUtil.currentTimeMillis();
long nonce = accountState.getAccount(from).getNonce();
+ boolean isFixTxHash = kernel.getConfig().forkEd25519ContractEnabled();
int[] perm = ArrayUtil.permutation(5000);
for (int p : perm) {
- Transaction tx = new Transaction(network, type, to, value, fee, nonce + p, now, Bytes.EMPTY_BYTES)
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce + p, now, Bytes.EMPTY_BYTES, isFixTxHash)
.sign(key);
pendingMgr.addTransaction(tx);
}
@@ -216,10 +225,11 @@ public void testHighVolumeTransaction() throws InterruptedException {
public void testNewBlock() throws InterruptedException {
long now = TimeUtil.currentTimeMillis();
long nonce = accountState.getAccount(from).getNonce();
+ boolean isFixTxHash = kernel.getConfig().forkEd25519ContractEnabled();
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, now, Bytes.EMPTY_BYTES).sign(key);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, now, Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
pendingMgr.addTransaction(tx);
- Transaction tx2 = new Transaction(network, type, to, value, fee, nonce + 1, now, Bytes.EMPTY_BYTES).sign(key);
+ Transaction tx2 = new Transaction(network, type, to, key.toAddress(), value, fee, nonce + 1, now, Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
// pendingMgr.addTransaction(tx3);
Thread.sleep(100);
@@ -242,7 +252,7 @@ public void testNewBlock() throws InterruptedException {
kernel.getBlockchain().getAccountState().increaseNonce(from);
pendingMgr.onBlockAdded(block);
- Transaction tx3 = new Transaction(network, type, to, value, fee, nonce + 2, now, Bytes.EMPTY_BYTES).sign(key);
+ Transaction tx3 = new Transaction(network, type, to, key.toAddress(), value, fee, nonce + 2, now, Bytes.EMPTY_BYTES, isFixTxHash).sign(key);
pendingMgr.addTransaction(tx3);
Thread.sleep(100);
diff --git a/src/test/java/org/semux/core/TransactionExecutorTest.java b/src/test/java/org/semux/core/TransactionExecutorTest.java
index 33b0943b3..4d6afe313 100644
--- a/src/test/java/org/semux/core/TransactionExecutorTest.java
+++ b/src/test/java/org/semux/core/TransactionExecutorTest.java
@@ -52,7 +52,7 @@ public void prepare() {
as = chain.getAccountState();
ds = chain.getDelegateState();
exec = new TransactionExecutor(config, new SemuxBlockStore(chain), chain.isVMEnabled(),
- chain.isVotingPrecompiledUpgraded());
+ chain.isVotingPrecompiledUpgraded(), chain.isEd25519ContractEnabled());
network = config.network();
block = new SemuxBlock(mock(BlockHeader.class), config.spec().maxBlockGasLimit());
}
@@ -69,7 +69,7 @@ private TransactionResult executeAndCommit(TransactionExecutor exec, Transaction
@Test
public void testTransfer() {
Key key = new Key();
-
+
TransactionType type = TransactionType.TRANSFER;
byte[] from = key.toAddress();
byte[] to = Bytes.random(20);
@@ -79,9 +79,9 @@ public void testTransfer() {
long timestamp = TimeUtil.currentTimeMillis();
byte[] data = Bytes.random(16);
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled());
tx.sign(key);
- assertTrue(tx.validate(network));
+ assertTrue(tx.validate_verify_sign(network, config.forkEd25519ContractEnabled()));
// insufficient available
TransactionResult result = exec.execute(tx, as.track(), ds.track(), block, 0);
@@ -120,18 +120,21 @@ public void testDelegate() {
byte[] data = Bytes.random(16);
// register delegate (to != EMPTY_ADDRESS, random name)
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data).sign(delegate);
+ Transaction tx = new Transaction(network, type, to, delegate.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled())
+ .sign(delegate);
TransactionResult result = exec.execute(tx, as.track(), ds.track(), block, 0);
assertFalse(result.getCode().isSuccess());
// register delegate (to == EMPTY_ADDRESS, random name)
- tx = new Transaction(network, type, Bytes.EMPTY_ADDRESS, value, fee, nonce, timestamp, data).sign(delegate);
+ tx = new Transaction(network, type, Bytes.EMPTY_ADDRESS, delegate.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled())
+ .sign(delegate);
result = exec.execute(tx, as.track(), ds.track(), block, 0);
assertFalse(result.getCode().isSuccess());
// register delegate (to == EMPTY_ADDRESS, normal name) and commit
data = Bytes.of("test");
- tx = new Transaction(network, type, Bytes.EMPTY_ADDRESS, value, fee, nonce, timestamp, data).sign(delegate);
+ tx = new Transaction(network, type, Bytes.EMPTY_ADDRESS, delegate.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled())
+ .sign(delegate);
result = executeAndCommit(exec, tx, as.track(), ds.track(), block);
assertTrue(result.getCode().isSuccess());
@@ -159,7 +162,8 @@ public void testVote() {
byte[] data = {};
// vote for non-existing delegate
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data).sign(voter);
+ Transaction tx = new Transaction(network, type, to, voter.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled())
+ .sign(voter);
TransactionResult result = exec.execute(tx, as.track(), ds.track(), block, 0);
assertFalse(result.getCode().isSuccess());
@@ -193,7 +197,8 @@ public void testUnvote() {
byte[] data = {};
// unvote (never voted before)
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data).sign(voter);
+ Transaction tx = new Transaction(network, type, to, voter.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled())
+ .sign(voter);
TransactionResult result = exec.execute(tx, as.track(), ds.track(), block, 0);
assertFalse(result.getCode().isSuccess());
assertEquals(INSUFFICIENT_LOCKED, result.code);
@@ -232,7 +237,8 @@ public void testUnvoteInsufficientFee() {
byte[] data = {};
// unvote (never voted before)
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data).sign(voter);
+ Transaction tx = new Transaction(network, type, to, voter.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled())
+ .sign(voter);
TransactionResult result = exec.execute(tx, as.track(), ds.track(), block, 0);
assertFalse(result.getCode().isSuccess());
diff --git a/src/test/java/org/semux/core/TransactionTest.java b/src/test/java/org/semux/core/TransactionTest.java
index cbb452266..24f340077 100644
--- a/src/test/java/org/semux/core/TransactionTest.java
+++ b/src/test/java/org/semux/core/TransactionTest.java
@@ -44,11 +44,11 @@ public class TransactionTest {
@Test
public void testNew() {
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled());
assertNotNull(tx.getHash());
assertNull(tx.getSignature());
tx.sign(key);
- assertTrue(tx.validate(network));
+ assertTrue(tx.validate_verify_sign(network, config.forkEd25519ContractEnabled()));
testFields(tx);
}
@@ -58,7 +58,7 @@ public void testNew() {
*/
@Test
public void testSerialization() {
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, timestamp, data, config.forkEd25519ContractEnabled());
tx.sign(key);
testFields(Transaction.fromBytes(tx.toBytes()));
@@ -66,7 +66,7 @@ public void testSerialization() {
@Test
public void testTransactionSize() {
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, Bytes.random(128))
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, timestamp, Bytes.random(128), config.forkEd25519ContractEnabled())
.sign(key);
byte[] bytes = tx.toBytes();
@@ -86,9 +86,9 @@ private void testFields(Transaction tx) {
@Test
public void testEquality() {
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, Bytes.random(128))
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, timestamp, Bytes.random(128), config.forkEd25519ContractEnabled())
.sign(key);
- Transaction tx2 = new Transaction(network, type, to, value, fee, nonce, timestamp, tx.getData())
+ Transaction tx2 = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, timestamp, tx.getData(), config.forkEd25519ContractEnabled())
.sign(key);
assertEquals(tx, tx2);
@@ -104,11 +104,13 @@ public void testEncoding() {
network,
type,
to,
+ key.toAddress(),
value,
fee,
nonce,
timestamp,
- data);
+ data,
+ config.forkEd25519ContractEnabled());
assertArrayEquals(encodedBytes, tx.getEncoded());
}
@@ -118,7 +120,7 @@ public void testEncoding() {
*/
@Test
public void testDecoding() {
- Transaction tx = Transaction.fromEncoded(encodedBytes);
+ Transaction tx = Transaction.fromEncoded(encodedBytes, Bytes.random(20), config.forkEd25519ContractEnabled());
assertEquals(network.id(), tx.getNetworkId());
assertEquals(type, tx.getType());
diff --git a/src/test/java/org/semux/core/WalletVersionTest.java b/src/test/java/org/semux/core/WalletVersionTest.java
index 8d13edb5d..edd08e4bf 100644
--- a/src/test/java/org/semux/core/WalletVersionTest.java
+++ b/src/test/java/org/semux/core/WalletVersionTest.java
@@ -49,7 +49,7 @@ public void testVersion1Wallet() throws IOException {
}
private void writeVersion1Wallet(List accounts, File file, String password) throws IOException {
- byte[] key = Hash.h256(Bytes.of(password));
+ byte[] key = Hash.h256_s(Bytes.of(password), null);
// write a version 1 wallet
SimpleEncoder enc = new SimpleEncoder();
diff --git a/src/test/java/org/semux/crypto/HashTest.java b/src/test/java/org/semux/crypto/HashTest.java
index e5188bcba..86838e7df 100644
--- a/src/test/java/org/semux/crypto/HashTest.java
+++ b/src/test/java/org/semux/crypto/HashTest.java
@@ -24,7 +24,7 @@ public class HashTest {
@Test
public void testEmptyHash() {
byte[] x = new byte[0];
- byte[] hash = Hash.h256(x);
+ byte[] hash = Hash.h256_s(x, null);
logger.info("Hash of empty byte array = {}", Hex.encode(hash));
}
@@ -32,7 +32,7 @@ public void testEmptyHash() {
@Test
public void testH256() {
byte[] raw = Bytes.of(msg);
- byte[] hash = Hash.h256(raw);
+ byte[] hash = Hash.h256_s(raw, null);
assertEquals(msgBlake2b, Hex.encode(hash));
}
@@ -41,7 +41,7 @@ public void testH256() {
public void testH256Merge() {
byte[] raw1 = Bytes.of(msg.substring(0, 1));
byte[] raw2 = Bytes.of(msg.substring(1));
- byte[] hash = Hash.h256(raw1, raw2);
+ byte[] hash = Hash.h256_s(raw1, raw2, null);
assertEquals(msgBlake2b, Hex.encode(hash));
}
diff --git a/src/test/java/org/semux/crypto/KeyTest.java b/src/test/java/org/semux/crypto/KeyTest.java
index f8398565d..727ba5f80 100644
--- a/src/test/java/org/semux/crypto/KeyTest.java
+++ b/src/test/java/org/semux/crypto/KeyTest.java
@@ -51,7 +51,7 @@ public void testKeyStorage() {
public void testMalleability() {
Key key = new Key();
byte[] data = Bytes.of("test");
- byte[] hash = Hash.h256(data);
+ byte[] hash = Hash.h256_s(data, null);
Signature sig = key.sign(hash);
assertTrue(Key.verify(hash, sig));
@@ -93,7 +93,7 @@ public void testSignAndVerify() throws SignatureException {
Key key = new Key();
byte[] data = Bytes.of("test");
- byte[] hash = Hash.h256(data);
+ byte[] hash = Hash.h256_s(data, null);
byte[] sig = key.sign(hash).toBytes();
assertEquals(Signature.LENGTH, sig.length);
@@ -116,7 +116,7 @@ public void testSignLargeData() throws SignatureException {
@Test
public void testInvalidSignature() throws SignatureException {
byte[] data = Bytes.of("test");
- byte[] hash = Hash.h256(data);
+ byte[] hash = Hash.h256_s(data, null);
assertFalse(Key.verify(hash, Bytes.random(20)));
assertFalse(Key.verify(hash, Bytes.random(Signature.LENGTH)));
@@ -128,7 +128,7 @@ public void testSignatureSize() {
Key key = new Key();
byte[] data = Bytes.of("test");
- byte[] hash = Hash.h256(data);
+ byte[] hash = Hash.h256_s(data, null);
byte[] sig = key.sign(hash).toBytes();
logger.info("signature size: {} B, {} GB per year", sig.length,
diff --git a/src/test/java/org/semux/crypto/NativeTest.java b/src/test/java/org/semux/crypto/NativeTest.java
index a6088f7a2..038f42ff0 100644
--- a/src/test/java/org/semux/crypto/NativeTest.java
+++ b/src/test/java/org/semux/crypto/NativeTest.java
@@ -54,12 +54,12 @@ public static void teardown() {
@Test(expected = CryptoException.class)
public void testH256Null() {
- Native.h256(null);
+ Native.h256(null, null);
}
@Test
public void testH256() {
- assertArrayEquals(H256, Native.h256(MESSAGE));
+ assertArrayEquals(H256, Native.h256(MESSAGE, null));
}
@Test(expected = CryptoException.class)
@@ -335,7 +335,7 @@ public void testVerifyBatch_large() {
@Test
public void testCompatibility() {
- assertArrayEquals(Native.h256(MESSAGE), Hash.h256(MESSAGE));
+ assertArrayEquals(Native.h256(MESSAGE, null), Hash.h256_s(MESSAGE, null));
assertArrayEquals(Native.h160(MESSAGE), Hash.h160(MESSAGE));
Key key = new Key();
@@ -354,13 +354,13 @@ public void benchmarkH256() {
// warm up
for (int i = 0; i < repeat / 10; i++) {
- Hash.h256(data);
+ Hash.h256_s(data, null);
}
// native
Instant start = Instant.now();
for (int i = 0; i < repeat; i++) {
- Native.h256(data);
+ Native.h256(data, null);
}
Instant end = Instant.now();
logger.debug("H256 Native: " + Duration.between(start, end).toMillis() + "ms");
@@ -368,12 +368,12 @@ public void benchmarkH256() {
// java (JIT)
start = Instant.now();
for (int i = 0; i < repeat; i++) {
- Hash.h256(data);
+ Hash.h256_s(data, null);
}
end = Instant.now();
logger.debug("H256 Java: " + Duration.between(start, end).toMillis() + "ms");
- assertArrayEquals(Hash.h256(data), Native.h256(data));
+ assertArrayEquals(Hash.h256_s(data, null), Native.h256(data, null));
}
@Test
@@ -402,7 +402,7 @@ public void benchmarkH160() {
end = Instant.now();
logger.debug("H160 Java: " + Duration.between(start, end).toMillis() + "ms");
- assertArrayEquals(Hash.h256(data), Native.h256(data));
+ assertArrayEquals(Hash.h256_s(data, null), Native.h256(data, null));
}
@Test
diff --git a/src/test/java/org/semux/gui/dialog/TransactionDialogTest.java b/src/test/java/org/semux/gui/dialog/TransactionDialogTest.java
index a5ff5ee40..7cb813f67 100644
--- a/src/test/java/org/semux/gui/dialog/TransactionDialogTest.java
+++ b/src/test/java/org/semux/gui/dialog/TransactionDialogTest.java
@@ -21,6 +21,7 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
+import org.semux.Kernel;
import org.semux.core.Amount;
import org.semux.core.Transaction;
import org.semux.crypto.Hex;
@@ -40,7 +41,8 @@ public class TransactionDialogTest extends AssertJSwingJUnitTestCase {
@Test
public void testDisplayTransferTransaction() {
- kernelRule1.getKernel().start();
+ Kernel kernel = kernelRule1.getKernel();
+ kernel.start();
Key from = new Key();
Key to = new Key();
@@ -49,8 +51,8 @@ public void testDisplayTransferTransaction() {
long nonce = 0L;
long now = Instant.now().toEpochMilli();
byte[] data = "some data".getBytes();
- Transaction tx = new Transaction(kernelRule1.getKernel().getConfig().network(), TRANSFER, to.toAddress(), value,
- fee, nonce, now, data).sign(from);
+ Transaction tx = new Transaction(kernel.getConfig().network(), TRANSFER, to.toAddress(),
+ from.toAddress(), value, fee, nonce, now, data, kernel.getConfig().forkEd25519ContractEnabled()).sign(from);
TransactionDialogTestApplication application = GuiActionRunner
.execute(() -> new TransactionDialogTestApplication(walletModel, kernelRule1.getKernel(), tx));
diff --git a/src/test/java/org/semux/gui/dialog/TransactionDialogTestApplication.java b/src/test/java/org/semux/gui/dialog/TransactionDialogTestApplication.java
index f4a0c8dc4..cba196a27 100644
--- a/src/test/java/org/semux/gui/dialog/TransactionDialogTestApplication.java
+++ b/src/test/java/org/semux/gui/dialog/TransactionDialogTestApplication.java
@@ -8,7 +8,6 @@
import org.semux.KernelMock;
import org.semux.core.Transaction;
-import org.semux.core.TransactionResult;
import org.semux.gui.BaseTestApplication;
import org.semux.gui.SemuxGui;
import org.semux.gui.model.WalletModel;
@@ -25,7 +24,7 @@ public class TransactionDialogTestApplication extends BaseTestApplication {
Transaction tx) {
super();
gui = new SemuxGui(walletModel, kernelMock);
- TransactionResult result = new TransactionResult(TransactionResult.Code.SUCCESS);
+ //TransactionResult result = new TransactionResult(TransactionResult.Code.SUCCESS);
transactionDialog = new TransactionDialog(this, tx, gui.getKernel());
transactionDialog.setVisible(true);
}
diff --git a/src/test/java/org/semux/gui/dialog/TransactionResultDialogTest.java b/src/test/java/org/semux/gui/dialog/TransactionResultDialogTest.java
index e7f9df71d..797aa5b60 100644
--- a/src/test/java/org/semux/gui/dialog/TransactionResultDialogTest.java
+++ b/src/test/java/org/semux/gui/dialog/TransactionResultDialogTest.java
@@ -23,6 +23,7 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
+import org.semux.Kernel;
import org.semux.core.Amount;
import org.semux.core.Transaction;
import org.semux.core.TransactionResult;
@@ -42,7 +43,8 @@ public class TransactionResultDialogTest extends AssertJSwingJUnitTestCase {
@Test
public void testTransactionResult() {
- kernelRule1.getKernel().start();
+ Kernel kernel = kernelRule1.getKernel();
+ kernel.start();
Key from = new Key();
Key to = new Key();
@@ -53,8 +55,8 @@ public void testTransactionResult() {
byte[] data = "some data".getBytes();
long gas = 10_000;
Amount gasPrice = Amount.of(10);
- Transaction tx = new Transaction(kernelRule1.getKernel().getConfig().network(), CREATE, to.toAddress(), value,
- fee, nonce, now, data, gas, gasPrice).sign(from);
+ Transaction tx = new Transaction(kernel.getConfig().network(), CREATE, to.toAddress(), from.toAddress(),
+ value, fee, nonce, now, data, gas, gasPrice, kernel.getConfig().forkEd25519ContractEnabled()).sign(from);
TransactionResult result = new TransactionResult();
result.setCode(TransactionResult.Code.FAILURE);
diff --git a/src/test/java/org/semux/gui/panel/TransactionsPanelTest.java b/src/test/java/org/semux/gui/panel/TransactionsPanelTest.java
index 88e12f7e8..b5d0ba48a 100644
--- a/src/test/java/org/semux/gui/panel/TransactionsPanelTest.java
+++ b/src/test/java/org/semux/gui/panel/TransactionsPanelTest.java
@@ -59,19 +59,25 @@ protected void onSetUp() {
}
@Test
- public void testTransactions() {
+ public void testTransactions()
+ {
+ KernelMock kernel = kernelRule.getKernel();
+ kernel.start();
+
Key key = new Key();
Amount $1 = Amount.of(1);
WalletAccount acc = spy(new WalletAccount(key, new Account(key.toAddress(), $1, $1, 1), null));
- Transaction tx = new Transaction(kernelRule.getKernel().getConfig().network(),
+ Transaction tx = new Transaction(kernel.getConfig().network(),
TransactionType.TRANSFER,
Bytes.random(Key.ADDRESS_LEN),
+ key.toAddress(),
Amount.of(1, SEM),
Amount.of(10, MILLI_SEM),
0,
TimeUtil.currentTimeMillis(),
- Bytes.EMPTY_BYTES);
+ Bytes.EMPTY_BYTES,
+ kernel.getConfig().forkEd25519ContractEnabled());
tx.sign(new Key());
acc.setTransactions(Collections.singletonList(tx));
@@ -79,7 +85,7 @@ public void testTransactions() {
when(walletModel.getAccounts()).thenReturn(Collections.singletonList(acc));
// mock kernel
- KernelMock kernelMock = spy(kernelRule.getKernel());
+ KernelMock kernelMock = spy(kernel);
Blockchain chain = mock(Blockchain.class);
DelegateState ds = mock(DelegateState.class);
PendingManager pendingManager = mock(PendingManager.class);
diff --git a/src/test/java/org/semux/integration/SyncingTest.java b/src/test/java/org/semux/integration/SyncingTest.java
index 756eb0da0..289ae0f93 100644
--- a/src/test/java/org/semux/integration/SyncingTest.java
+++ b/src/test/java/org/semux/integration/SyncingTest.java
@@ -141,7 +141,7 @@ public void testSync() {
Block previousBlock = kernel4.getBlockchain().getBlock(i - 1);
assertTrue(block.validateHeader(block.getHeader(), previousBlock.getHeader()));
assertTrue(block.validateTransactions(previousBlock.getHeader(), block.getTransactions(),
- kernel4.getConfig().network()));
+ kernel4.getConfig().network(), kernel4.getConfig().forkEd25519ContractEnabled()));
assertTrue(block.validateResults(previousBlock.getHeader(), block.getResults()));
assertTrue(block.getVotes().size() >= 3 * 2 / 3);
diff --git a/src/test/java/org/semux/integration/UniformDistForkSyncingTest.java b/src/test/java/org/semux/integration/UniformDistForkSyncingTest.java
index b0c42c6f3..a05b4954e 100644
--- a/src/test/java/org/semux/integration/UniformDistForkSyncingTest.java
+++ b/src/test/java/org/semux/integration/UniformDistForkSyncingTest.java
@@ -6,9 +6,6 @@
*/
package org.semux.integration;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
import org.junit.experimental.categories.Category;
import org.semux.IntegrationTest;
import org.semux.TestUtils;
diff --git a/src/test/java/org/semux/net/msg/p2p/TransactionMessageTest.java b/src/test/java/org/semux/net/msg/p2p/TransactionMessageTest.java
index 4ee5985f8..5ab2e3ae3 100644
--- a/src/test/java/org/semux/net/msg/p2p/TransactionMessageTest.java
+++ b/src/test/java/org/semux/net/msg/p2p/TransactionMessageTest.java
@@ -29,9 +29,11 @@ public void testSerialization() {
long nonce = 1;
long timestamp = TimeUtil.currentTimeMillis();
byte[] data = Bytes.of("data");
+
+ Key key = new Key();
- Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data);
- tx.sign(new Key());
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, fee, nonce, timestamp, data, true);
+ tx.sign(key);
TransactionMessage msg = new TransactionMessage(tx);
TransactionMessage msg2 = new TransactionMessage(msg.getBody());
diff --git a/src/test/java/org/semux/util/MerkleTreeTest.java b/src/test/java/org/semux/util/MerkleTreeTest.java
index 73da6db17..550ae7b99 100644
--- a/src/test/java/org/semux/util/MerkleTreeTest.java
+++ b/src/test/java/org/semux/util/MerkleTreeTest.java
@@ -47,7 +47,7 @@ public void testOneElement() {
@Test
public void testTwoElements() {
- byte[] hash12 = Hash.h256(hash1, hash2);
+ byte[] hash12 = Hash.h256_s(hash1, hash2, null);
MerkleTree tree = new MerkleTree(Arrays.asList(hash1, hash2));
assertEquals(2, tree.size());
@@ -61,9 +61,9 @@ public void testTwoElements() {
@Test
public void testThreeElements() {
- byte[] hash12 = Hash.h256(hash1, hash2);
+ byte[] hash12 = Hash.h256_s(hash1, hash2, null);
byte[] hash33 = hash3;
- byte[] hash1233 = Hash.h256(hash12, hash33);
+ byte[] hash1233 = Hash.h256_s(hash12, hash33, null);
MerkleTree tree = new MerkleTree(Arrays.asList(hash1, hash2, hash3));
assertEquals(3, tree.size());
diff --git a/src/test/java/org/semux/util/MerkleUtilTest.java b/src/test/java/org/semux/util/MerkleUtilTest.java
index 5df9e8623..5b75ab30b 100644
--- a/src/test/java/org/semux/util/MerkleUtilTest.java
+++ b/src/test/java/org/semux/util/MerkleUtilTest.java
@@ -33,8 +33,12 @@ public void testComputeTransactionsRoot() {
long nonce = 1;
long timestamp = TimeUtil.currentTimeMillis();
byte[] data = Bytes.random(128);
- Transaction tx1 = new Transaction(network, type, to, value, fee, nonce, timestamp, data).sign(new Key());
- Transaction tx2 = new Transaction(network, type, to, value, fee, nonce, timestamp, data).sign(new Key());
+
+ Key key1 = new Key();
+ Key key2 = new Key();
+
+ Transaction tx1 = new Transaction(network, type, to, key1.toAddress(), value, fee, nonce, timestamp, data, true).sign(key1);
+ Transaction tx2 = new Transaction(network, type, to, key2.toAddress(), value, fee, nonce, timestamp, data, true).sign(key2);
byte[] b1 = tx1.getHash();
byte[] b2 = tx2.getHash();
byte[] root = new MerkleTree(Arrays.asList(b1, b2)).getRootHash();
@@ -51,8 +55,8 @@ public void testComputeResultsRoot() {
res1.setReturnData(Bytes.random(20));
res2.setReturnData(Bytes.random(20));
- byte[] b1 = Hash.h256(res1.toBytesForMerkle());
- byte[] b2 = Hash.h256(res2.toBytesForMerkle());
+ byte[] b1 = Hash.h256_s(res1.toBytesForMerkle(), null);
+ byte[] b2 = Hash.h256_s(res2.toBytesForMerkle(), null);
byte[] root = new MerkleTree(Arrays.asList(b1, b2)).getRootHash();
byte[] merkle = MerkleUtil.computeResultsRoot(Arrays.asList(res1, res2));
diff --git a/src/test/java/org/semux/vm/client/InternalTransactionTest.java b/src/test/java/org/semux/vm/client/InternalTransactionTest.java
index 6636bf10f..bfedbe892 100644
--- a/src/test/java/org/semux/vm/client/InternalTransactionTest.java
+++ b/src/test/java/org/semux/vm/client/InternalTransactionTest.java
@@ -69,7 +69,8 @@ public void prepare() {
// }
@Test
public void testInternalTransfer() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key key = new Key();
TransactionType type = TransactionType.CALL;
@@ -93,8 +94,8 @@ public void testInternalTransfer() {
long gas = 100000;
Amount gasPrice = Amount.of(1);
- Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, contract, gas,
- gasPrice);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, Amount.ZERO, nonce, timestamp, contract, gas,
+ gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
TransactionResult result = exec.execute(tx, as, ds, bh, 0);
diff --git a/src/test/java/org/semux/vm/client/PrecompiledContractTest.java b/src/test/java/org/semux/vm/client/PrecompiledContractTest.java
index c640109f2..cdece932c 100644
--- a/src/test/java/org/semux/vm/client/PrecompiledContractTest.java
+++ b/src/test/java/org/semux/vm/client/PrecompiledContractTest.java
@@ -6,9 +6,7 @@
*/
package org.semux.vm.client;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -16,6 +14,11 @@
import static org.semux.core.Amount.ZERO;
import static org.semux.core.Unit.SEM;
+import java.util.Random;
+
+import org.hamcrest.core.IsEqual;
+import org.hamcrest.core.IsNot;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -80,7 +83,8 @@ public void prepare() {
@Test
public void testSuccess() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key key = new Key();
byte[] delegate = Bytes.random(20);
@@ -96,7 +100,7 @@ public void testSuccess() {
long gas = 100000;
Amount gasPrice = Amount.of(1);
- Transaction tx = new Transaction(network, type, to, value, ZERO, nonce, timestamp, data, gas, gasPrice);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
SemuxBlock block = new SemuxBlock(
@@ -128,7 +132,7 @@ public void testSuccess() {
Hex.decode("000000000000000000000000"), delegate,
Hex.decode("000000000000000000000000000000000000000000000000000000003B9ACA00")); // 1 nanoSEM
- tx = new Transaction(network, type, to, value, ZERO, nonce + 1, timestamp, data, gas, gasPrice);
+ tx = new Transaction(network, type, to, key.toAddress(), value, ZERO, nonce + 1, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
result = exec.execute(tx, as, ds, block, 0);
@@ -145,7 +149,8 @@ public void testSuccess() {
// it would fail because the contract doesn't have balance.
@Test
public void testFailure1() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key key = new Key();
byte[] delegate = Bytes.random(20);
@@ -161,7 +166,7 @@ public void testFailure1() {
long gas = 100000;
Amount gasPrice = Amount.of(1);
- Transaction tx = new Transaction(network, type, to, value, ZERO, nonce, timestamp, data, gas, gasPrice);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
SemuxBlock block = new SemuxBlock(
@@ -181,7 +186,8 @@ public void testFailure1() {
// it would fail because the sender doesn't have enough balance.
@Test
public void testFailure2() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key key = new Key();
TransactionType type = TransactionType.CALL;
@@ -197,7 +203,7 @@ public void testFailure2() {
long gas = 100000;
Amount gasPrice = Amount.of(1);
- Transaction tx = new Transaction(network, type, to, value, ZERO, nonce, timestamp, data, gas, gasPrice);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
SemuxBlock block = new SemuxBlock(
@@ -211,4 +217,186 @@ public void testFailure2() {
TransactionResult result = exec.execute(tx, as, ds, block, 0);
assertFalse(result.getCode().isSuccess());
}
+
+ @Test
+ public void testEd25519Vfy() {
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
+ Key key = new Key();
+
+ byte[] message = new byte[32];
+ new Random().nextBytes(message);
+
+ Key signingKey = new Key();
+ Key.Signature sig = signingKey.sign(message);
+ byte[] signature = sig.getS();
+ byte[] publicKey = sig.getA();
+
+ // our signatures are (S,A), eth spec is (A,S)
+ TransactionType type = TransactionType.CALL;
+ byte[] from = key.toAddress();
+ byte[] to = Hex.decode0x("0x0000000000000000000000000000000000000009");
+ byte[] delegate = Bytes.random(20);
+ Amount value = Amount.of(0);
+
+ long nonce = as.getAccount(from).getNonce();
+ long timestamp = TimeUtil.currentTimeMillis();
+ byte[] data = Bytes.merge(message, publicKey, signature);
+
+ long gas = 100000;
+ Amount gasPrice = Amount.of(1);
+
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
+ tx.sign(key);
+
+ SemuxBlock block = new SemuxBlock(
+ new BlockHeader(123, Bytes.random(20), Bytes.random(20), TimeUtil.currentTimeMillis(),
+ Bytes.random(20), Bytes.random(20), Bytes.random(20), Bytes.random(20)),
+ config.spec().maxBlockGasLimit());
+ as.adjustAvailable(from, Amount.of(1000, SEM));
+ as.adjustAvailable(to, Amount.of(1000, SEM));
+ ds.register(delegate, "abc".getBytes());
+
+ TransactionResult result = exec.execute(tx, as, ds, block, 0);
+ assertTrue(result.getCode().isSuccess());
+ assertArrayEquals(new byte[0], result.getReturnData());
+
+ // check if message is tampered
+ nonce = as.getAccount(from).getNonce();
+ timestamp = TimeUtil.currentTimeMillis();
+ message[0] = (byte) ((int) message[0] + 1 % 8);
+ data = Bytes.merge(message, publicKey, signature);
+
+ tx = new Transaction(network, type, to, key.toAddress(), value, ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
+ tx.sign(key);
+
+ block = new SemuxBlock(
+ new BlockHeader(123, Bytes.random(20), Bytes.random(20), TimeUtil.currentTimeMillis(),
+ Bytes.random(20), Bytes.random(20), Bytes.random(20), Bytes.random(20)),
+ config.spec().maxBlockGasLimit());
+ as.adjustAvailable(from, Amount.of(1000, SEM));
+ as.adjustAvailable(to, Amount.of(1000, SEM));
+ ds.register(delegate, "abc".getBytes());
+
+ result = exec.execute(tx, as, ds, block, 0);
+
+ // call is still a success, but data is not empty
+ assertTrue(result.getCode().isSuccess());
+ Assert.assertThat(new byte[0], IsNot.not(IsEqual.equalTo(result.getReturnData())));
+
+ // check that invalid set of data is failure
+ nonce = as.getAccount(from).getNonce();
+ timestamp = TimeUtil.currentTimeMillis();
+ message[0] = (byte) ((int) message[0] + 1 % 8);
+ data = Bytes.merge(message, publicKey); // no signature
+
+ tx = new Transaction(network, type, to, key.toAddress(), value, ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
+ tx.sign(key);
+
+ block = new SemuxBlock(
+ new BlockHeader(123, Bytes.random(20), Bytes.random(20), TimeUtil.currentTimeMillis(),
+ Bytes.random(20), Bytes.random(20), Bytes.random(20), Bytes.random(20)),
+ config.spec().maxBlockGasLimit());
+ as.adjustAvailable(from, Amount.of(1000, SEM));
+ as.adjustAvailable(to, Amount.of(1000, SEM));
+ ds.register(delegate, "abc".getBytes());
+
+ result = exec.execute(tx, as, ds, block, 0);
+
+ // call is still a success, but data is not empty
+ assertFalse(result.getCode().isSuccess());
+ assertArrayEquals(new byte[0], result.getReturnData());
+ }
+
+ @Test
+ public void testEd25519Vfy_Prefork() {
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ false);
+ Key key = new Key();
+
+ byte[] message = new byte[32];
+ new Random().nextBytes(message);
+
+ Key signingKey = new Key();
+ Key.Signature sig = signingKey.sign(message);
+ byte[] signature = sig.getS();
+ byte[] publicKey = sig.getA();
+
+ // our signatures are (S,A), eth spec is (A,S)
+ TransactionType type = TransactionType.CALL;
+ byte[] from = key.toAddress();
+ byte[] to = Hex.decode0x("0x0000000000000000000000000000000000000009");
+ byte[] delegate = Bytes.random(20);
+ Amount value = Amount.of(0);
+
+ long nonce = as.getAccount(from).getNonce();
+ long timestamp = TimeUtil.currentTimeMillis();
+ byte[] data = Bytes.merge(message, publicKey, signature);
+
+ long gas = 100000;
+ Amount gasPrice = Amount.of(1);
+
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
+ tx.sign(key);
+
+ SemuxBlock block = new SemuxBlock(
+ new BlockHeader(123, Bytes.random(20), Bytes.random(20), TimeUtil.currentTimeMillis(),
+ Bytes.random(20), Bytes.random(20), Bytes.random(20), Bytes.random(20)),
+ config.spec().maxBlockGasLimit());
+ as.adjustAvailable(from, Amount.of(1000, SEM));
+ as.adjustAvailable(to, Amount.of(1000, SEM));
+ ds.register(delegate, "abc".getBytes());
+
+ TransactionResult result = exec.execute(tx, as, ds, block, 0);
+ // calls to nonimplemented precompiled contracts just return success/empty
+ assertTrue(result.getCode().isSuccess());
+ assertArrayEquals(new byte[0], result.getReturnData());
+
+ // check if message is tampered
+ nonce = as.getAccount(from).getNonce();
+ timestamp = TimeUtil.currentTimeMillis();
+ message[0] = (byte) ((int) message[0] + 1 % 8);
+ data = Bytes.merge(message, publicKey, signature);
+
+ tx = new Transaction(network, type, to, key.toAddress(), value, ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
+ tx.sign(key);
+
+ block = new SemuxBlock(
+ new BlockHeader(123, Bytes.random(20), Bytes.random(20), TimeUtil.currentTimeMillis(),
+ Bytes.random(20), Bytes.random(20), Bytes.random(20), Bytes.random(20)),
+ config.spec().maxBlockGasLimit());
+ as.adjustAvailable(from, Amount.of(1000, SEM));
+ as.adjustAvailable(to, Amount.of(1000, SEM));
+ ds.register(delegate, "abc".getBytes());
+
+ result = exec.execute(tx, as, ds, block, 0);
+ // calls to nonimplemented precompiled contracts just return success/empty
+ assertTrue(result.getCode().isSuccess());
+ assertArrayEquals(new byte[0], result.getReturnData());
+
+ // check that invalid set of data is not a failure (since it should default to
+ // default calling of non-address
+ nonce = as.getAccount(from).getNonce();
+ timestamp = TimeUtil.currentTimeMillis();
+ message[0] = (byte) ((int) message[0] + 1 % 8);
+ data = Bytes.merge(message, publicKey); // no signature
+
+ tx = new Transaction(network, type, to, key.toAddress(), value, ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
+ tx.sign(key);
+
+ block = new SemuxBlock(
+ new BlockHeader(123, Bytes.random(20), Bytes.random(20), TimeUtil.currentTimeMillis(),
+ Bytes.random(20), Bytes.random(20), Bytes.random(20), Bytes.random(20)),
+ config.spec().maxBlockGasLimit());
+ as.adjustAvailable(from, Amount.of(1000, SEM));
+ as.adjustAvailable(to, Amount.of(1000, SEM));
+ ds.register(delegate, "abc".getBytes());
+
+ result = exec.execute(tx, as, ds, block, 0);
+
+ // call is still a success, but data is not empty
+ assertTrue(result.getCode().isSuccess());
+ assertArrayEquals(new byte[0], result.getReturnData());
+
+ }
}
diff --git a/src/test/java/org/semux/vm/client/VmTransactionTest.java b/src/test/java/org/semux/vm/client/VmTransactionTest.java
index e706ea3a1..cf2d65b46 100644
--- a/src/test/java/org/semux/vm/client/VmTransactionTest.java
+++ b/src/test/java/org/semux/vm/client/VmTransactionTest.java
@@ -77,7 +77,8 @@ public void prepare() {
*/
@Test
public void testCall() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key key = new Key();
TransactionType type = TransactionType.CALL;
@@ -98,9 +99,9 @@ public void testCall() {
long gas = 30000;
Amount gasPrice = Amount.of(1);
- Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
- assertTrue(tx.validate(network));
+ assertTrue(tx.validate_verify_sign(network, config.forkEd25519ContractEnabled()));
// insufficient available
TransactionResult result = exec.execute(tx, as.track(), ds.track(), block, 0);
@@ -128,7 +129,8 @@ public void testCall() {
*/
@Test
public void testCreate() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key key = new Key();
TransactionType type = TransactionType.CREATE;
@@ -146,10 +148,10 @@ public void testCreate() {
long gas = 1000000;
Amount gasPrice = Amount.of(1);
- Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, create, gas,
- gasPrice);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, Amount.ZERO, nonce, timestamp, create, gas,
+ gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
- assertTrue(tx.validate(network));
+ assertTrue(tx.validate_verify_sign(network, config.forkEd25519ContractEnabled()));
// insufficient available
TransactionResult result = exec.execute(tx, as.track(), ds.track(), block, 0);
@@ -190,7 +192,8 @@ public void testCreate() {
// }
@Test
public void testCreateAndCall() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key key = new Key();
TransactionType type = TransactionType.CREATE;
@@ -210,9 +213,9 @@ public void testCreateAndCall() {
Amount available = Amount.of(1000, SEM);
as.adjustAvailable(key.toAddress(), available);
- Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
- assertTrue(tx.validate(network));
+ assertTrue(tx.validate_verify_sign(network, config.forkEd25519ContractEnabled()));
TransactionResult result = exec.execute(tx, as, ds, block, 0);
assertTrue(result.getCode().isSuccess());
@@ -223,9 +226,9 @@ public void testCreateAndCall() {
to = newContractAddress;
nonce += 1;
data = Hex.decode0x("0x60fe47b10000000000000000000000000000000000000000000000000000000000000009");
- tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice);
+ tx = new Transaction(network, type, to, key.toAddress(), value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
- assertTrue(tx.validate(network));
+ assertTrue(tx.validate_verify_sign(network, config.forkEd25519ContractEnabled()));
result = exec.execute(tx, as, ds, block, 0);
assertTrue(result.getCode().isSuccess());
@@ -241,7 +244,8 @@ public void testCreateAndCall() {
// }
@Test
public void testInternalTransferNotEnoughGas() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key key = new Key();
TransactionType type = TransactionType.CREATE;
@@ -261,9 +265,9 @@ public void testInternalTransferNotEnoughGas() {
Amount available = Amount.of(1000, SEM);
as.adjustAvailable(key.toAddress(), available);
- Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
- assertTrue(tx.validate(network));
+ assertTrue(tx.validate_verify_sign(network, config.forkEd25519ContractEnabled()));
TransactionResult result = exec.execute(tx, as, ds, block, 0);
assertFalse(result.getCode().isSuccess());
@@ -271,7 +275,8 @@ public void testInternalTransferNotEnoughGas() {
@Test
public void testInternalTransfer() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key key = new Key();
TransactionType type = TransactionType.CREATE;
@@ -291,9 +296,9 @@ public void testInternalTransfer() {
Amount available = Amount.of(1000, SEM);
as.adjustAvailable(key.toAddress(), available);
- Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
- assertTrue(tx.validate(network));
+ assertTrue(tx.validate_verify_sign(network, config.forkEd25519ContractEnabled()));
TransactionResult result = exec.execute(tx, as, ds, block, 0);
assertTrue(result.getCode().isSuccess());
@@ -305,9 +310,9 @@ public void testInternalTransfer() {
nonce += 1;
data = Hex.decode0x("0x3e58c58c000000000000000000000000791f1c3f06b19f1b3a4c7774675df9933a091d10");
value = Amount.of(1, SEM);
- tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice);
+ tx = new Transaction(network, type, to, key.toAddress(), value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
- assertTrue(tx.validate(network));
+ assertTrue(tx.validate_verify_sign(network, config.forkEd25519ContractEnabled()));
assertEquals(ZERO, as.getAccount(newContractAddress).getAvailable());
assertEquals(ZERO, as.getAccount(Hex.decode0x("791f1c3f06b19f1b3a4c7774675df9933a091d10")).getAvailable());
@@ -324,7 +329,8 @@ public void testInternalTransfer() {
@Test
public void testTransferToContract() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key key = new Key();
TransactionType type = TransactionType.CALL;
@@ -341,8 +347,8 @@ public void testTransferToContract() {
long gas = 100000;
Amount gasPrice = Amount.of(1);
- Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, contract, gas,
- gasPrice);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, Amount.ZERO, nonce, timestamp, contract, gas,
+ gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
TransactionResult result = exec.execute(tx, as, ds, block, 0);
@@ -359,7 +365,8 @@ public void testTransferToContract() {
@Test
public void testTransferToContractOutOfGas() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key key = new Key();
TransactionType type = TransactionType.CALL;
@@ -376,8 +383,8 @@ public void testTransferToContractOutOfGas() {
long gas = 21073;
Amount gasPrice = Amount.of(1);
- Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, contract, gas,
- gasPrice);
+ Transaction tx = new Transaction(network, type, to, key.toAddress(), value, Amount.ZERO, nonce, timestamp, contract, gas,
+ gasPrice, config.forkEd25519ContractEnabled());
tx.sign(key);
TransactionResult result = exec.execute(tx, as, ds, block, 0);
@@ -394,7 +401,8 @@ public void testTransferToContractOutOfGas() {
// tx: 0x31d6c6c1c5e82b286b8179f4368543fb4595beb57ee1fd2a01dbbb22f6cca9f1
@Test
public void testCallFailureRevertBeforeFork() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, false);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, false,
+ true);
Key sender = new Key();
TransactionType type = TransactionType.CREATE;
@@ -406,7 +414,7 @@ public void testCallFailureRevertBeforeFork() {
"0x608060405234801561001057600080fd5b50610165806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bc5de3014610046575b600080fd5b34801561005257600080fd5b5061005b6100d6565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009b578082015181840152602081019050610080565b50505050905090810190601f1680156100c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60608060405190810160405280602281526020017f466972737420636f6e7472616374212053656d757820746f20746865204d6f6f81526020017f6e210000000000000000000000000000000000000000000000000000000000008152509050905600a165627a7a72305820934582d75405e634939862f4188ebbb6c2765362add401961e8f44aa91b91f040029");
long gas = 1000000;
Amount gasPrice = Amount.of(1);
- Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice)
+ Transaction tx = new Transaction(network, type, to, sender.toAddress(), value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled())
.sign(sender);
// credit the sender some balance
@@ -424,7 +432,8 @@ public void testCallFailureRevertBeforeFork() {
nonce = as.getAccount(sender.toAddress()).getNonce();
data = Hex.decode0x("0x3bc5de30");
value = Amount.of(1, SEM);
- tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice).sign(sender);
+ tx = new Transaction(network, type, to, sender.toAddress(), value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled())
+ .sign(sender);
// call the contract
result = exec.execute(tx, as, ds, block, 0);
@@ -438,7 +447,8 @@ public void testCallFailureRevertBeforeFork() {
@Test
public void testCallFailureRevertAfterFork() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key sender = new Key();
TransactionType type = TransactionType.CREATE;
@@ -450,7 +460,7 @@ public void testCallFailureRevertAfterFork() {
"0x608060405234801561001057600080fd5b50610165806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bc5de3014610046575b600080fd5b34801561005257600080fd5b5061005b6100d6565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009b578082015181840152602081019050610080565b50505050905090810190601f1680156100c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60608060405190810160405280602281526020017f466972737420636f6e7472616374212053656d757820746f20746865204d6f6f81526020017f6e210000000000000000000000000000000000000000000000000000000000008152509050905600a165627a7a72305820934582d75405e634939862f4188ebbb6c2765362add401961e8f44aa91b91f040029");
long gas = 1000000;
Amount gasPrice = Amount.of(1);
- Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice)
+ Transaction tx = new Transaction(network, type, to, sender.toAddress(), value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled())
.sign(sender);
// credit the sender some balance
@@ -468,7 +478,8 @@ public void testCallFailureRevertAfterFork() {
nonce = as.getAccount(sender.toAddress()).getNonce();
data = Hex.decode0x("0x3bc5de30");
value = Amount.of(1, SEM);
- tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice).sign(sender);
+ tx = new Transaction(network, type, to, sender.toAddress(), value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled())
+ .sign(sender);
// call the contract
result = exec.execute(tx, as, ds, block, 0);
@@ -483,7 +494,8 @@ public void testCallFailureRevertAfterFork() {
// tx: 0x64fa2479faaeca0dcefbb57c2fc96f785336663f27726e8e7225e7dce3096452
@Test
public void testCreateFailure() {
- TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true);
+ TransactionExecutor exec = new TransactionExecutor(config, new SemuxBlockStore(chain), true, true,
+ true);
Key sender = new Key();
TransactionType type = TransactionType.CREATE;
@@ -495,7 +507,7 @@ public void testCreateFailure() {
"0x608060405234801561001057600080fd5b50610165806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bc5de3014610046575b600080fd5b34801561005257600080fd5b5061005b6100d6565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009b578082015181840152602081019050610080565b50505050905090810190601f1680156100c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60608060405190810160405280602281526020017f466972737420636f6e7472616374212053656d757820746f20746865204d6f6f81526020017f6e210000000000000000000000000000000000000000000000000000000000008152509050905600a165627a7a72305820934582d75405e634939862f4188ebbb6c2765362add401961e8f44aa91b91f040029");
long gas = 121000;
Amount gasPrice = Amount.of(200);
- Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice)
+ Transaction tx = new Transaction(network, type, to, sender.toAddress(), value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice, config.forkEd25519ContractEnabled())
.sign(sender);
// credit the sender some balance