Skip to content
Permalink
Browse files

Merge pull request #90 from orogvany/testnet_rc

RC: 1.5.0 Testnet - VM + HD Wallets
  • Loading branch information...
orogvany committed Nov 17, 2018
2 parents 40a00cc + f1982a7 commit 021d510ecfeb321b2d95eaea3dcccfa317aba16b
Showing with 4,526 additions and 258 deletions.
  1. +10 −0 config/semux.properties
  2. +1 −0 evm
  3. +23 −4 pom.xml
  4. +1 −0 src/main/java/org/semux/api/ApiHandlerImpl.java
  5. +4 −2 src/main/java/org/semux/api/ApiVersion.java
  6. +10 −0 src/main/java/org/semux/api/SemuxApiService.java
  7. +41 −1 src/main/java/org/semux/api/util/TransactionBuilder.java
  8. +88 −23 src/main/java/org/semux/api/v2/SemuxApiImpl.java
  9. +28 −10 src/main/java/org/semux/cli/SemuxCli.java
  10. +45 −25 src/main/java/org/semux/config/AbstractConfig.java
  11. +21 −7 src/main/java/org/semux/config/Config.java
  12. +1 −1 src/main/java/org/semux/config/Constants.java
  13. +14 −1 src/main/java/org/semux/config/DevnetConfig.java
  14. +62 −23 src/main/java/org/semux/consensus/SemuxBft.java
  15. +11 −9 src/main/java/org/semux/consensus/SemuxSync.java
  16. +4 −0 src/main/java/org/semux/core/Amount.java
  17. +37 −1 src/main/java/org/semux/core/Block.java
  18. +12 −8 src/main/java/org/semux/core/BlockchainImpl.java
  19. +1 −1 src/main/java/org/semux/core/Fork.java
  20. +12 −1 src/main/java/org/semux/core/PendingManager.java
  21. +46 −7 src/main/java/org/semux/core/Transaction.java
  22. +82 −20 src/main/java/org/semux/core/TransactionExecutor.java
  23. +72 −13 src/main/java/org/semux/core/TransactionResult.java
  24. +155 −10 src/main/java/org/semux/core/Wallet.java
  25. +5 −0 src/main/java/org/semux/core/state/Account.java
  26. +27 −2 src/main/java/org/semux/core/state/AccountState.java
  27. +64 −9 src/main/java/org/semux/core/state/AccountStateImpl.java
  28. +15 −0 src/main/java/org/semux/crypto/Key.java
  29. +4 −0 src/main/java/org/semux/gui/Action.java
  30. +66 −21 src/main/java/org/semux/gui/MenuBar.java
  31. +14 −2 src/main/java/org/semux/gui/SemuxGui.java
  32. +5 −0 src/main/java/org/semux/gui/SwingUtil.java
  33. +1 −2 src/main/java/org/semux/gui/WelcomeFrame.java
  34. +153 −0 src/main/java/org/semux/gui/dialog/CreateHdWalletDialog.java
  35. +134 −0 src/main/java/org/semux/gui/dialog/RecoverHdWalletDialog.java
  36. +37 −2 src/main/java/org/semux/gui/dialog/TransactionDialog.java
  37. +1 −3 src/main/java/org/semux/gui/panel/ReceivePanel.java
  38. +3 −1 src/main/java/org/semux/gui/panel/TransactionsPanel.java
  39. +49 −0 src/main/java/org/semux/vm/client/SemuxBlock.java
  40. +28 −0 src/main/java/org/semux/vm/client/SemuxBlockStore.java
  41. +117 −0 src/main/java/org/semux/vm/client/SemuxRepository.java
  42. +64 −0 src/main/java/org/semux/vm/client/SemuxTransaction.java
  43. +1 −1 src/main/resources/org/semux/api/index.html
  44. +2,606 −0 src/main/resources/org/semux/api/swagger/v2.2.0.json
  45. +3 −0 src/main/resources/org/semux/cli/messages.properties
  46. +17 −1 src/main/resources/org/semux/gui/messages.properties
  47. +41 −3 src/test/java/org/semux/cli/SemuxCliTest.java
  48. +5 −2 src/test/java/org/semux/core/CorePerformanceTest.java
  49. +1 −2 src/test/java/org/semux/core/PendingManagerTest.java
  50. +19 −15 src/test/java/org/semux/core/TransactionExecutorTest.java
  51. +23 −5 src/test/java/org/semux/core/TransactionResultTest.java
  52. +172 −0 src/test/java/org/semux/core/VmTest.java
  53. +10 −7 src/test/java/org/semux/core/WalletTest.java
  54. +2 −1 src/test/java/org/semux/core/WalletVersionTest.java
  55. +33 −0 src/test/java/org/semux/core/state/AccountStateTest.java
  56. +5 −3 src/test/java/org/semux/gui/WelcomeFrameTest.java
  57. +3 −1 src/test/java/org/semux/gui/dialog/TransactionDialogTest.java
  58. +3 −1 src/test/java/org/semux/gui/dialog/TransactionDialogTestApplication.java
  59. +1 −1 src/test/java/org/semux/integration/ConnectionTest.java
  60. +1 −1 src/test/java/org/semux/integration/SyncingTest.java
  61. +1 −1 src/test/java/org/semux/integration/TransactTest.java
  62. +6 −0 src/test/java/org/semux/net/msg/MessageQueueTest.java
  63. +3 −2 src/test/java/org/semux/rules/KernelRule.java
  64. +2 −2 src/test/java/org/semux/util/MerkleUtilTest.java
@@ -75,3 +75,13 @@ api.password = YOUR_API_PASSWORD
# ui.unit must be one of SEM, mSEM, μSEM
ui.unit = SEM
ui.fractionDigits = 9

#================
# VM
#================

# Set the maximum gas this client can process in one block proposal
vm.blockGasLimit = 2000000

# The minimum price this client will accept for gas
vm.minGasPrice = 1
1 evm
Submodule evm added at f0cd32
27 pom.xml
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.semux</groupId>
<artifactId>semux</artifactId>
<version>1.4.0</version>
<version>1.5.0</version>
<packaging>jar</packaging>
<description>Semux is an experimental high-performance blockchain platform that powers decentralized application.</description>

@@ -14,6 +14,7 @@
<dist.windowsExecutableVersion>${project.version}.0</dist.windowsExecutableVersion>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<skip.git.info>false</skip.git.info>
</properties>

<organization>
@@ -107,7 +108,7 @@
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/org/semux/api/swagger/v2.1.0.json</inputSpec>
<inputSpec>${project.basedir}/src/main/resources/org/semux/api/swagger/v2.2.0.json</inputSpec>
<language>jaxrs-cxf</language>
<configOptions>
<useGenericResponse>true</useGenericResponse>
@@ -137,7 +138,7 @@
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/org/semux/api/swagger/v2.1.0.json</inputSpec>
<inputSpec>${project.basedir}/src/main/resources/org/semux/api/swagger/v2.2.0.json</inputSpec>
<language>jaxrs-cxf-client</language>
<configOptions>
<useBeanValidation>false</useBeanValidation>
@@ -244,6 +245,7 @@
</execution>
</executions>
<configuration>
<skip>${skip.git.info}</skip>
<abbrevLength>7</abbrevLength>
<verbose>false</verbose>
<skipPoms>false</skipPoms>
@@ -676,7 +678,7 @@
<dependency>
<groupId>com.github.semuxproject</groupId>
<artifactId>evm</artifactId>
<version>-SNAPSHOT</version>
<version>f0cd3256aad61634e0efb320478e8075beec076f</version>
</dependency>

<!-- Swagger & JAX-RS API -->
@@ -1017,9 +1019,26 @@
<version>2.9.7</version>
<scope>test</scope>
</dependency>

<!-- HD wallets -->
<dependency>
<groupId>com.github.orogvany</groupId>
<artifactId>BIP32-Ed25519-java</artifactId>
<version>a5865ea2916197e2da83c38a3b50972f01a8c93c</version>
</dependency>
</dependencies>

<profiles>
<profile>
<id>src-build</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<skip.git.info>true</skip.git.info>
<git.commit.id.abbrev>local</git.commit.id.abbrev>
</properties>
</profile>
<profile>
<id>windows</id>
<activation>
@@ -59,6 +59,7 @@ public ApiHandlerImpl(Kernel kernel) {

this.routes.put(ApiVersion.v2_0_0, routesV2);
this.routes.put(ApiVersion.v2_1_0, routesV2);
this.routes.put(ApiVersion.v2_2_0, routesV2);
}

@Override
@@ -28,9 +28,11 @@

v2_0_0("v2.0.0"),

v2_1_0("v2.1.0");
v2_1_0("v2.1.0"),

public final static ApiVersion DEFAULT = v2_1_0;
v2_2_0("v2.2.0");

public final static ApiVersion DEFAULT = v2_2_0;

public final String prefix;

@@ -9,9 +9,12 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import io.netty.channel.ChannelOption;
import io.netty.channel.FixedRecvByteBufAllocator;
import org.semux.Kernel;
import org.semux.api.http.HttpChannelInitializer;
import org.semux.api.http.HttpHandler;
import org.semux.net.Frame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@@ -97,6 +100,13 @@ public HttpHandler initHandler() {

logger.info("Starting API server: address = {}:{}", ip, port);
channel = b.bind(ip, port).sync().channel();

// allow larger messages for local contract calls.
// contract/call data is 64 * 1024, plus another 1024 for rest of call
int bufferSize = 65 * 1024;
channel.config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(bufferSize));
channel.config().setOption(ChannelOption.SO_RCVBUF, bufferSize);

logger.info("API server started. Base URL: {}, Explorer: {}", getApiBaseUrl(), getApiExplorerUrl());
} catch (Exception e) {
logger.error("Failed to start API server", e);
@@ -72,6 +72,9 @@
*/
private byte[] data;

private long gasPrice = 0;
private long gas = 0;

public TransactionBuilder(Kernel kernel) {
this.kernel = kernel;
}
@@ -129,6 +132,12 @@ public TransactionBuilder withTo(String to) {
}
return this; // ignore the provided parameter
}
if (type == TransactionType.CREATE) {
if (to != null && !to.isEmpty()) {
throw new IllegalArgumentException("Parameter `to` is not needed for CREATE transaction");
}
return this; // ignore the provided parameter
}

if (to == null) {
throw new IllegalArgumentException("Parameter `to` is required");
@@ -211,12 +220,43 @@ public TransactionBuilder withData(String data) {
return this;
}

public TransactionBuilder withGasPrice(String gasPrice) {
if (gasPrice == null) {
throw new IllegalArgumentException("Parameter `gasPrice` is required");
}

try {
this.gasPrice = Long.parseLong(gasPrice);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Parameter `gasPrice` is not a valid number");
}

return this;
}

public TransactionBuilder withGas(String gasLimit) {
if (gasLimit == null) {
throw new IllegalArgumentException("Parameter `gas` is required");
}

try {
this.gas = Long.parseLong(gasLimit);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Parameter `gas` is not a valid number");
}

return this;
}

public Transaction buildUnsigned() {
// DELEGATE transaction has fixed receiver and value
if (type == TransactionType.DELEGATE) {
to = Bytes.EMPTY_ADDRESS;
value = kernel.getConfig().minDelegateBurnAmount();
}
if (type == TransactionType.CREATE) {
to = Bytes.EMPTY_ADDRESS;
}

return new Transaction(
network != null ? network : kernel.getConfig().network(),
@@ -226,7 +266,7 @@ public Transaction buildUnsigned() {
fee,
nonce != null ? nonce : kernel.getPendingManager().getNonce(account.toAddress()),
timestamp != null ? timestamp : TimeUtil.currentTimeMillis(),
data);
data, gas, gasPrice);
}

public Transaction buildSigned() {
@@ -25,6 +25,12 @@

import org.apache.commons.validator.routines.DomainValidator;
import org.apache.commons.validator.routines.InetAddressValidator;
import org.ethereum.vm.chainspec.Spec;
import org.ethereum.vm.client.BlockStore;
import org.ethereum.vm.client.Repository;
import org.ethereum.vm.client.TransactionReceipt;
import org.ethereum.vm.program.invoke.ProgramInvokeFactory;
import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl;
import org.semux.Kernel;
import org.semux.api.util.TransactionBuilder;
import org.semux.api.v2.model.AddNodeResponse;
@@ -75,6 +81,10 @@
import org.semux.net.filter.SemuxIpFilter;

import net.i2p.crypto.eddsa.EdDSAPublicKey;
import org.semux.vm.client.SemuxBlock;
import org.semux.vm.client.SemuxBlockStore;
import org.semux.vm.client.SemuxRepository;
import org.semux.vm.client.SemuxTransaction;

public final class SemuxApiImpl implements SemuxApi {

@@ -730,6 +740,45 @@ public Response transfer(String from, String to, String value, String fee, Strin
return doTransaction(TransactionType.TRANSFER, from, to, value, fee, nonce, validateNonce, data);
}

@Override
public Response create(String from, String value, String data, String gasPrice, String gas, String fee,
String nonce, Boolean validateNonce) {
return doTransaction(TransactionType.CREATE, from, null, value, fee, nonce, validateNonce, data, gasPrice,
gas);
}

@Override
public Response call(String from, String to, String value, String gasPrice, String gas, String fee,
String nonce, Boolean validateNonce, String data, Boolean local) {
if (local) {
Transaction tx = getTransaction(TransactionType.CALL, from, to, value, fee, nonce, validateNonce, data,
gasPrice, gas);

SemuxTransaction transaction = new SemuxTransaction(tx);
SemuxBlock block = new SemuxBlock(kernel.getBlockchain().getLatestBlock().getHeader(), 0);
Repository repository = new SemuxRepository(kernel.getBlockchain().getAccountState());
ProgramInvokeFactory invokeFactory = new ProgramInvokeFactoryImpl();
BlockStore blockStore = new SemuxBlockStore(kernel.getBlockchain());
long gasUsedInBlock = 0l;

org.ethereum.vm.client.TransactionExecutor executor = new org.ethereum.vm.client.TransactionExecutor(
transaction, block, repository, blockStore,
Spec.DEFAULT, invokeFactory, gasUsedInBlock, true);
TransactionReceipt results = executor.run();

DoTransactionResponse resp = new DoTransactionResponse();
resp.setResult(Hex.encode0x(results.getReturnData()));
if (!results.isSuccess()) {
return badRequest(resp, "Error calling method");
} else {
return success(resp);
}
} else {
return doTransaction(TransactionType.CALL, from, to, value, fee, nonce, validateNonce, data, gasPrice,
gas);
}
}

@Override
public Response unvote(String from, String to, String value, String fee, String nonce, Boolean validateNonce) {
return doTransaction(TransactionType.UNVOTE, from, to, value, fee, nonce, validateNonce, null);
@@ -857,6 +906,43 @@ private Response badRequest(ApiHandlerResponse resp, String message) {
return new NodeManager.Node(host, port);
}

private Response doTransaction(TransactionType type, String from, String to, String value, String fee, String nonce,
Boolean validateNonce, String data) {
return doTransaction(type, from, to, value, fee, nonce, validateNonce, data, null, null);
}

private Transaction getTransaction(TransactionType type, String from, String to, String value, String fee,
String nonce,
Boolean validateNonce, String data, String gasPrice, String gas) {
TransactionBuilder transactionBuilder = new TransactionBuilder(kernel)
.withType(type)
.withFrom(from)
.withTo(to)
.withValue(value)
.withFee(fee, true)
.withData(data);
if (type == TransactionType.CREATE || type == TransactionType.CALL) {
transactionBuilder.withGasPrice(gasPrice).withGas(gas);
}

if (nonce != null) {
transactionBuilder.withNonce(nonce);
} else {
// TODO: fix race condition of auto-assigned nonce
}

Transaction tx = transactionBuilder.buildSigned();

// tx nonce is validated in advance to avoid silently pushing the tx into
// delayed queue of pending manager
if ((validateNonce != null && validateNonce)
&& tx.getNonce() != kernel.getPendingManager().getNonce(tx.getFrom())) {
throw new IllegalArgumentException("Invalid transaction nonce.");
}
return tx;

}

/**
* Constructs a transaction and adds it to pending manager.
*
@@ -871,31 +957,10 @@ private Response badRequest(ApiHandlerResponse resp, String message) {
* @return
*/
private Response doTransaction(TransactionType type, String from, String to, String value, String fee, String nonce,
Boolean validateNonce, String data) {
Boolean validateNonce, String data, String gasPrice, String gas) {
DoTransactionResponse resp = new DoTransactionResponse();
try {
TransactionBuilder transactionBuilder = new TransactionBuilder(kernel)
.withType(type)
.withFrom(from)
.withTo(to)
.withValue(value)
.withFee(fee, true)
.withData(data);

if (nonce != null) {
transactionBuilder.withNonce(nonce);
} else {
// TODO: fix race condition of auto-assigned nonce
}

Transaction tx = transactionBuilder.buildSigned();

// tx nonce is validated in advance to avoid silently pushing the tx into
// delayed queue of pending manager
if ((validateNonce != null && validateNonce)
&& tx.getNonce() != kernel.getPendingManager().getNonce(tx.getFrom())) {
return badRequest(resp, "Invalid transaction nonce.");
}
Transaction tx = getTransaction(type, from, to, value, fee, nonce, validateNonce, data, gasPrice, gas);

PendingManager.ProcessingResult result = kernel.getPendingManager().addTransactionSync(tx);
if (result.error != null) {
Oops, something went wrong.

0 comments on commit 021d510

Please sign in to comment.
You can’t perform that action at this time.