From 3fa9e6874c44aaaf134272d0f65e30341bda9b23 Mon Sep 17 00:00:00 2001 From: semux Date: Tue, 2 Jul 2019 17:09:11 +0100 Subject: [PATCH 01/11] VM: block gas limit should not be Long.MAX_VALUE --- src/main/java/org/semux/api/v2/SemuxApiImpl.java | 3 ++- src/main/java/org/semux/consensus/SemuxBft.java | 4 ++-- src/main/java/org/semux/core/PendingManager.java | 2 +- src/test/java/org/semux/core/TransactionExecutorTest.java | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/semux/api/v2/SemuxApiImpl.java b/src/main/java/org/semux/api/v2/SemuxApiImpl.java index 5f235d698..6559783d4 100644 --- a/src/main/java/org/semux/api/v2/SemuxApiImpl.java +++ b/src/main/java/org/semux/api/v2/SemuxApiImpl.java @@ -779,7 +779,8 @@ public Response call(String from, String to, String value, String gasPrice, Stri gasPrice, gas); SemuxTransaction transaction = new SemuxTransaction(tx); - SemuxBlock block = new SemuxBlock(kernel.getBlockchain().getLatestBlock().getHeader(), 0); + SemuxBlock block = new SemuxBlock(kernel.getBlockchain().getLatestBlock().getHeader(), + kernel.getConfig().vmMaxBlockGasLimit()); Repository repository = new SemuxRepository(kernel.getBlockchain().getAccountState()); ProgramInvokeFactory invokeFactory = new ProgramInvokeFactoryImpl(); BlockStore blockStore = new SemuxBlockStore(kernel.getBlockchain()); diff --git a/src/main/java/org/semux/consensus/SemuxBft.java b/src/main/java/org/semux/consensus/SemuxBft.java index 508ee9d82..97273d56e 100644 --- a/src/main/java/org/semux/consensus/SemuxBft.java +++ b/src/main/java/org/semux/consensus/SemuxBft.java @@ -906,7 +906,7 @@ protected boolean validateBlockProposal(Block block) { // against our own local limit, only // when proposing List results = exec.execute(transactions, as, ds, - new SemuxBlock(header, Long.MAX_VALUE), chain); + new SemuxBlock(header, config.vmMaxBlockGasLimit()), chain); block.setResults(results); if (!block.validateResults(header, results)) { @@ -973,7 +973,7 @@ protected void applyBlock(Block block) { // [3] evaluate all transactions List results = exec.execute(transactions, as, ds, - new SemuxBlock(block.getHeader(), Long.MAX_VALUE), chain); + new SemuxBlock(block.getHeader(), config.vmMaxBlockGasLimit()), chain); if (!block.validateResults(header, results)) { logger.debug("Invalid transactions"); return; diff --git a/src/main/java/org/semux/core/PendingManager.java b/src/main/java/org/semux/core/PendingManager.java index f9d49ad49..ffdf86b4d 100644 --- a/src/main/java/org/semux/core/PendingManager.java +++ b/src/main/java/org/semux/core/PendingManager.java @@ -347,7 +347,7 @@ protected ProcessingResult processTransaction(Transaction tx, boolean relay) { prevBlock.getNumber() + 1, new Key().toAddress(), prevBlock.getHash(), System.currentTimeMillis(), new byte[0], new byte[0], new byte[0], new byte[0]); - SemuxBlock block = new SemuxBlock(blockHeader, kernel.getConfig().vmBlockGasLimit()); + SemuxBlock block = new SemuxBlock(blockHeader, kernel.getConfig().vmMaxBlockGasLimit()); // execute transactions AccountState as = pendingAS.track(); diff --git a/src/test/java/org/semux/core/TransactionExecutorTest.java b/src/test/java/org/semux/core/TransactionExecutorTest.java index 58538006c..27442e3cd 100644 --- a/src/test/java/org/semux/core/TransactionExecutorTest.java +++ b/src/test/java/org/semux/core/TransactionExecutorTest.java @@ -56,7 +56,7 @@ public void prepare() { ds = chain.getDelegateState(); exec = new TransactionExecutor(config, new SemuxBlockStore(chain)); network = config.network(); - block = new SemuxBlock(mock(BlockHeader.class), 5_000_000); + block = new SemuxBlock(mock(BlockHeader.class), config.vmMaxBlockGasLimit()); } private TransactionResult executeAndCommit(TransactionExecutor exec, Transaction tx, AccountState as, From f1322f7a52e2cf3fa1944078ef0c45d2caaa5e14 Mon Sep 17 00:00:00 2001 From: semux Date: Tue, 2 Jul 2019 17:53:21 +0100 Subject: [PATCH 02/11] Config: move blockchain parameters into ChainSpec --- config/semux.properties | 9 +- .../semux/api/util/TransactionBuilder.java | 4 +- .../java/org/semux/api/v2/SemuxApiImpl.java | 2 +- .../java/org/semux/api/v2/TypeFactory.java | 6 +- src/main/java/org/semux/cli/SemuxCli.java | 2 +- .../java/org/semux/config/AbstractConfig.java | 191 +++++++++--------- src/main/java/org/semux/config/ChainSpec.java | 90 +++++++++ src/main/java/org/semux/config/Config.java | 116 ++--------- .../java/org/semux/consensus/SemuxBft.java | 22 +- .../java/org/semux/consensus/SemuxSync.java | 12 +- src/main/java/org/semux/core/Block.java | 2 +- .../java/org/semux/core/BlockchainImpl.java | 9 +- .../java/org/semux/core/PendingManager.java | 6 +- .../org/semux/core/TransactionExecutor.java | 8 +- src/main/java/org/semux/gui/SemuxGui.java | 4 +- src/main/java/org/semux/gui/SwingUtil.java | 1 - .../java/org/semux/gui/model/WalletModel.java | 8 +- .../org/semux/gui/panel/DelegatesPanel.java | 21 +- .../java/org/semux/gui/panel/SendPanel.java | 10 +- src/test/java/org/semux/TestUtils.java | 2 +- .../org/semux/api/http/HttpHandlerTest.java | 1 - .../java/org/semux/api/v2/SemuxApiTest.java | 30 +-- .../semux/bench/BlockchainPerformance.java | 8 +- .../org/semux/bench/SemuxPerformance.java | 2 +- .../org/semux/config/MainnetConfigTest.java | 4 +- .../org/semux/consensus/SemuxBftTest.java | 2 +- .../consensus/SemuxBftValidateBlockTest.java | 2 +- .../org/semux/consensus/SemuxSyncTest.java | 10 +- src/test/java/org/semux/core/BlockTest.java | 2 +- .../org/semux/core/CorePerformanceTest.java | 4 +- .../org/semux/core/PendingManagerTest.java | 2 +- .../semux/core/TransactionExecutorTest.java | 18 +- .../java/org/semux/core/TransactionTest.java | 2 +- src/test/java/org/semux/core/VmTest.java | 4 +- src/test/java/org/semux/core/WalletTest.java | 1 - .../org/semux/gui/model/WalletModelTest.java | 6 +- .../semux/gui/panel/DelegatesPanelTest.java | 4 +- .../org/semux/gui/panel/SendPanelTest.java | 2 +- .../org/semux/integration/SyncingTest.java | 1 - .../org/semux/integration/TransactTest.java | 11 +- src/test/java/org/semux/util/IOUtilTest.java | 1 - 41 files changed, 322 insertions(+), 320 deletions(-) create mode 100644 src/main/java/org/semux/config/ChainSpec.java diff --git a/config/semux.properties b/config/semux.properties index 38c3abd84..2b58fb506 100644 --- a/config/semux.properties +++ b/config/semux.properties @@ -81,9 +81,10 @@ ui.fractionDigits = 9 #================ # Set the maximum gas this client can process in one block proposal -# for RC3 we raise default block gas limit to 20 million for tuning. -# This should be removed for mainnet! -vm.blockGasLimit = 20000000 +vm.blockGasLimit = 10000000 # The minimum price this client will accept for gas -vm.minGasPrice = 1 \ No newline at end of file +vm.minGasPrice = 1 + +# The max transaction time drift in milliseconds +pool.maxTransactionTimeDrift = 7300000 \ No newline at end of file diff --git a/src/main/java/org/semux/api/util/TransactionBuilder.java b/src/main/java/org/semux/api/util/TransactionBuilder.java index 70aba2c09..8054cf50f 100644 --- a/src/main/java/org/semux/api/util/TransactionBuilder.java +++ b/src/main/java/org/semux/api/util/TransactionBuilder.java @@ -186,7 +186,7 @@ public TransactionBuilder withValue(String value) { public TransactionBuilder withFee(String fee, boolean optional) { if (optional && (fee == null || fee.isEmpty())) { - this.fee = kernel.getConfig().minTransactionFee(); + this.fee = kernel.getConfig().spec().minTransactionFee(); return this; } @@ -259,7 +259,7 @@ public Transaction buildUnsigned() { // DELEGATE transaction has fixed receiver and value if (type == TransactionType.DELEGATE) { to = Bytes.EMPTY_ADDRESS; - value = kernel.getConfig().minDelegateBurnAmount(); + value = kernel.getConfig().spec().minDelegateBurnAmount(); } if (type == TransactionType.CREATE) { to = Bytes.EMPTY_ADDRESS; diff --git a/src/main/java/org/semux/api/v2/SemuxApiImpl.java b/src/main/java/org/semux/api/v2/SemuxApiImpl.java index 6559783d4..f4e9e584c 100644 --- a/src/main/java/org/semux/api/v2/SemuxApiImpl.java +++ b/src/main/java/org/semux/api/v2/SemuxApiImpl.java @@ -780,7 +780,7 @@ public Response call(String from, String to, String value, String gasPrice, Stri SemuxTransaction transaction = new SemuxTransaction(tx); SemuxBlock block = new SemuxBlock(kernel.getBlockchain().getLatestBlock().getHeader(), - kernel.getConfig().vmMaxBlockGasLimit()); + kernel.getConfig().spec().maxBlockGasLimit()); Repository repository = new SemuxRepository(kernel.getBlockchain().getAccountState()); ProgramInvokeFactory invokeFactory = new ProgramInvokeFactoryImpl(); BlockStore blockStore = new SemuxBlockStore(kernel.getBlockchain()); diff --git a/src/main/java/org/semux/api/v2/TypeFactory.java b/src/main/java/org/semux/api/v2/TypeFactory.java index e17b3ca25..493403b31 100644 --- a/src/main/java/org/semux/api/v2/TypeFactory.java +++ b/src/main/java/org/semux/api/v2/TypeFactory.java @@ -131,10 +131,10 @@ public static PeerType peerType(Peer peer) { public static TransactionLimitsType transactionLimitsType(Kernel kernel, org.semux.core.TransactionType transactionType) { return new TransactionLimitsType() - .maxTransactionDataSize(kernel.getConfig().maxTransactionDataSize(transactionType)) - .minTransactionFee(encodeAmount(kernel.getConfig().minTransactionFee())) + .maxTransactionDataSize(kernel.getConfig().spec().maxTransactionDataSize(transactionType)) + .minTransactionFee(encodeAmount(kernel.getConfig().spec().minTransactionFee())) .minDelegateBurnAmount(encodeAmount( - transactionType.equals(DELEGATE) ? kernel.getConfig().minDelegateBurnAmount() : null)); + transactionType.equals(DELEGATE) ? kernel.getConfig().spec().minDelegateBurnAmount() : null)); } public static TransactionType transactionType(Transaction tx) { diff --git a/src/main/java/org/semux/cli/SemuxCli.java b/src/main/java/org/semux/cli/SemuxCli.java index 348daf681..3bdf5ddc7 100644 --- a/src/main/java/org/semux/cli/SemuxCli.java +++ b/src/main/java/org/semux/cli/SemuxCli.java @@ -75,7 +75,7 @@ public static void main(String[] args) { * Creates a new Semux CLI instance. */ public SemuxCli() { - SystemUtil.setLocale(getConfig().locale()); + SystemUtil.setLocale(getConfig().uiLocale()); Option helpOption = Option.builder() .longOpt(SemuxOption.HELP.toString()) diff --git a/src/main/java/org/semux/config/AbstractConfig.java b/src/main/java/org/semux/config/AbstractConfig.java index d08bf68e3..30111f38d 100644 --- a/src/main/java/org/semux/config/AbstractConfig.java +++ b/src/main/java/org/semux/config/AbstractConfig.java @@ -39,12 +39,20 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public abstract class AbstractConfig implements Config { +public abstract class AbstractConfig implements Config, ChainSpec { private static final Logger logger = LoggerFactory.getLogger(AbstractConfig.class); private static final String CONFIG_FILE = "semux.properties"; + // ========================= + // Chain spec + // ========================= + protected long maxBlockGasLimit = 10_000_000L; // 10m gas + protected int maxBlockTransactionsSize = 1024 * 1024; + protected Amount minTransactionFee = MILLI_SEM.of(5); + protected Amount minDelegateBurnAmount = SEM.of(1000); + // ========================= // General // ========================= @@ -52,11 +60,6 @@ public abstract class AbstractConfig implements Config { protected Network network; protected short networkVersion; - protected int maxBlockTransactionsSize = 1024 * 1024; - protected Amount minTransactionFee = MILLI_SEM.of(5); - protected long maxTransactionTimeDrift = TimeUnit.HOURS.toMillis(2); - protected Amount minDelegateBurnAmount = SEM.of(1000); - // ========================= // P2P // ========================= @@ -112,21 +115,19 @@ public abstract class AbstractConfig implements Config { protected long bftPreCommitTimeout = 6000L; protected long bftCommitTimeout = 3000L; protected long bftFinalizeTimeout = 3000L; - protected long maxBlockTimeDrift = TimeUnit.SECONDS.toMillis(30); + protected long bftMaxBlockTimeDrift = TimeUnit.SECONDS.toMillis(30); // ========================= - // Virtual machine + // Transaction pool // ========================= - protected int vmMaxStackSize = 1024; - protected int vmInitHeapSize = 128; - protected int vmBlockGasLimit = 999_999; - protected int vmMaxBlockGasLimit = 9_999_999; - protected int vmMinGasPrice = 1; + protected int poolBlockGasLimit = 5_000_000; + protected int poolMinGasPrice = 10; // 10 NanoSEM = 10 Gwei + protected long poolMaxTransactionTimeDrift = TimeUnit.HOURS.toMillis(2); // ========================= // UI // ========================= - protected Locale locale = Locale.getDefault(); + protected Locale uiLocale = Locale.getDefault(); protected String uiUnit = "SEM"; protected int uiFractionDigits = 9; @@ -136,13 +137,11 @@ public abstract class AbstractConfig implements Config { protected boolean forkUniformDistributionEnabled = false; protected boolean forkVirtualMachineEnabled = false; - /** - * Create an {@link AbstractConfig} instance. - * - * @param dataDir - * @param network - * @param networkVersion - */ + @Override + public ChainSpec spec() { + return this; + } + protected AbstractConfig(String dataDir, Network network, short networkVersion) { this.dataDir = new File(dataDir); this.network = network; @@ -153,8 +152,48 @@ protected AbstractConfig(String dataDir, Network network, short networkVersion) } @Override - public File getFile() { - return new File(configDir(), CONFIG_FILE); + public long maxBlockGasLimit() { + return maxBlockGasLimit; + } + + @Override + public int maxBlockTransactionsSize() { + return maxBlockTransactionsSize; + } + + @Override + public int maxTransactionDataSize(TransactionType type) { + switch (type) { + case COINBASE: + return 0; // not required + + case TRANSFER: + return 128; // for memo + + case DELEGATE: + return 16; // for name + + case UNVOTE: + case VOTE: + return 0; // not required + + case CREATE: + case CALL: + return 64 * 1024; // for dapps + + default: + throw new UnreachableException(); + } + } + + @Override + public Amount minTransactionFee() { + return minTransactionFee; + } + + @Override + public Amount minDelegateBurnAmount() { + return minDelegateBurnAmount; } @Override @@ -223,18 +262,8 @@ private int getUniformDistPrimaryValidatorNumber(int size, long height, long vie } @Override - public String getClientId() { - return String.format("%s/v%s-%s/%s/%s", - Constants.CLIENT_NAME, - Constants.CLIENT_VERSION, - SystemUtil.getImplementationVersion(), - SystemUtil.getOsName().toString(), - SystemUtil.getOsArch()); - } - - @Override - public CapabilitySet getClientCapabilities() { - return Constants.CLIENT_CAPABILITIES; + public File getFile() { + return new File(configDir(), CONFIG_FILE); } @Override @@ -268,48 +297,18 @@ public short networkVersion() { } @Override - public int maxBlockTransactionsSize() { - return maxBlockTransactionsSize; - } - - @Override - public int maxTransactionDataSize(TransactionType type) { - switch (type) { - case COINBASE: - return 0; // not required - - case TRANSFER: - return 128; // for memo - - case DELEGATE: - return 16; // for name - - case UNVOTE: - case VOTE: - return 0; // not required - - case CREATE: - case CALL: - return 64 * 1024; // for dapps - - default: - throw new UnreachableException(); - } - } - - @Override - public Amount minTransactionFee() { - return minTransactionFee; - } - - @Override - public long maxTransactionTimeDrift() { - return maxTransactionTimeDrift; + public String getClientId() { + return String.format("%s/v%s-%s/%s/%s", + Constants.CLIENT_NAME, + Constants.CLIENT_VERSION, + SystemUtil.getImplementationVersion(), + SystemUtil.getOsName().toString(), + SystemUtil.getOsArch()); } @Override - public Amount minDelegateBurnAmount() { - return minDelegateBurnAmount; + public CapabilitySet getClientCapabilities() { + return Constants.CLIENT_CAPABILITIES; } @Override @@ -468,38 +467,28 @@ public long bftFinalizeTimeout() { } @Override - public long maxBlockTimeDrift() { - return maxBlockTimeDrift; + public long bftMaxBlockTimeDrift() { + return bftMaxBlockTimeDrift; } @Override - public int vmMaxStackSize() { - return vmMaxStackSize; + public int poolBlockGasLimit() { + return poolBlockGasLimit; } @Override - public int vmInitialHeapSize() { - return vmInitHeapSize; + public int poolMinGasPrice() { + return poolMinGasPrice; } @Override - public int vmBlockGasLimit() { - return vmBlockGasLimit; + public long poolMaxTransactionTimeDrift() { + return poolMaxTransactionTimeDrift; } @Override - public int vmMaxBlockGasLimit() { - return vmMaxBlockGasLimit; - } - - @Override - public int vmMinGasPrice() { - return vmMinGasPrice; - } - - @Override - public Locale locale() { - return locale; + public Locale uiLocale() { + return uiLocale; } @Override @@ -618,7 +607,7 @@ protected void init() { // ui.locale must be in format of en_US ([language]_[country]) String[] localeComponents = props.getProperty(name).trim().split("_"); if (localeComponents.length == 2) { - locale = new Locale(localeComponents[0], localeComponents[1]); + uiLocale = new Locale(localeComponents[0], localeComponents[1]); } break; } @@ -630,12 +619,16 @@ protected void init() { uiFractionDigits = Integer.parseInt(props.getProperty(name).trim()); break; } - case "vm.blockGasLimit": { - vmBlockGasLimit = Integer.parseInt(props.getProperty(name).trim()); + case "pool.blockGasLimit": { + poolBlockGasLimit = Integer.parseInt(props.getProperty(name).trim()); + break; + } + case "pool.minGasPrice": { + poolMinGasPrice = Integer.parseInt(props.getProperty(name).trim()); break; } - case "vm.minGasPrice": { - vmMinGasPrice = Integer.parseInt(props.getProperty(name).trim()); + case "pool.maxTransactionTimeDrift": { + poolMaxTransactionTimeDrift = Integer.parseInt(props.getProperty(name).trim()); break; } default: diff --git a/src/main/java/org/semux/config/ChainSpec.java b/src/main/java/org/semux/config/ChainSpec.java new file mode 100644 index 000000000..ef4175a8f --- /dev/null +++ b/src/main/java/org/semux/config/ChainSpec.java @@ -0,0 +1,90 @@ +/** + * 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.config; + +import java.util.List; + +import org.semux.core.Amount; +import org.semux.core.TransactionType; + +/** + * Chain specifications define the parameters that are agreed by the network and + * enforced as part of the consensus. + */ +public interface ChainSpec { + + /** + * Returns the maximum gas limit for any block + * + * @return + */ + long maxBlockGasLimit(); + + /** + * Returns the max total size of all transactions in a block, encoding overhead + * not counted. + * + * @return + */ + int maxBlockTransactionsSize(); + + /** + * Returns the max data size for the given transaction type. + * + * @return + */ + int maxTransactionDataSize(TransactionType type); + + /** + * Returns the min transaction fee. + * + * @return + */ + Amount minTransactionFee(); + + /** + * Returns the min amount of value burned when registering as a delegate. + * + * @return + */ + Amount minDelegateBurnAmount(); + + /** + * Returns the block reward for a specific block. + * + * @param number + * block number + * @return the block reward + */ + Amount getBlockReward(long number); + + /** + * Returns the validator update rate. + * + * @return + */ + long getValidatorUpdateInterval(); + + /** + * Returns the number of validators. + * + * @param number + * @return + */ + int getNumberOfValidators(long number); + + /** + * Returns the primary validator for a specific [height, view]. + * + * @param validators + * @param height + * @param view + * @param uniformDist + * @return + */ + String getPrimaryValidator(List validators, long height, int view, boolean uniformDist); +} diff --git a/src/main/java/org/semux/config/Config.java b/src/main/java/org/semux/config/Config.java index 401376cae..848f4fa10 100644 --- a/src/main/java/org/semux/config/Config.java +++ b/src/main/java/org/semux/config/Config.java @@ -14,9 +14,7 @@ import java.util.Set; import org.semux.Network; -import org.semux.core.Amount; import org.semux.core.Fork; -import org.semux.core.TransactionType; import org.semux.net.CapabilitySet; import org.semux.net.NodeManager.Node; import org.semux.net.msg.MessageCode; @@ -26,6 +24,13 @@ */ public interface Config { + /** + * Returns the chain specification. + * + * @return + */ + ChainSpec spec(); + // ========================= // General // ========================= @@ -77,78 +82,6 @@ public interface Config { */ short networkVersion(); - /** - * Returns the max total size of all transactions in a block, encoding overhead - * not counted. - * - * @return - */ - int maxBlockTransactionsSize(); - - /** - * Returns the max data size for the given transaction type. - * - * @return - */ - int maxTransactionDataSize(TransactionType type); - - /** - * Returns the min transaction fee. - * - * @return - */ - Amount minTransactionFee(); - - /** - * Returns the maximum allowed time drift between transaction timestamp and - * local clock. - * - * @return - */ - long maxTransactionTimeDrift(); - - /** - * Returns the min amount of value burned when registering as a delegate. - * - * @return - */ - Amount minDelegateBurnAmount(); - - /** - * Returns the block reward for a specific block. - * - * @param number - * block number - * @return the block reward - */ - Amount getBlockReward(long number); - - /** - * Returns the validator update rate. - * - * @return - */ - long getValidatorUpdateInterval(); - - /** - * Returns the number of validators. - * - * @param number - * @return - */ - int getNumberOfValidators(long number); - - /** - * Returns the primary validator for a specific [height, view]. - * - * @param validators - * @param height - * @param view - * @param uniformDist - * @return - */ - String getPrimaryValidator(List validators, long height, int view, boolean uniformDist); - /** * Returns the client id. * @@ -403,46 +336,33 @@ public interface Config { * * @return */ - long maxBlockTimeDrift(); + long bftMaxBlockTimeDrift(); // ========================= - // Virtual machine + // Transaction pool // ========================= /** - * Returns the max size of process stack in words. - * - * @return - */ - int vmMaxStackSize(); - - /** - * Returns the initial size of process heap in bytes. - * - * @return - */ - int vmInitialHeapSize(); - - /** - * Returns the maximum gas limit for a block proposal + * Returns the maximum gas limit for a block proposal, local setting * * @return */ - int vmBlockGasLimit(); + int poolBlockGasLimit(); /** - * Returns the maximum gas limit for any block + * Returns the minimum gas price for any transaction proposed, local setting * * @return */ - int vmMaxBlockGasLimit(); + int poolMinGasPrice(); /** - * Returns the minimum gas price for any transaction proposed - * + * Returns the maximum allowed time drift between transaction timestamp and + * local clock. + * * @return */ - int vmMinGasPrice(); + long poolMaxTransactionTimeDrift(); // ========================= // UI @@ -453,7 +373,7 @@ public interface Config { * * @return */ - Locale locale(); + Locale uiLocale(); /** * Returns the unit of displayed values. diff --git a/src/main/java/org/semux/consensus/SemuxBft.java b/src/main/java/org/semux/consensus/SemuxBft.java index 97273d56e..ca9593330 100644 --- a/src/main/java/org/semux/consensus/SemuxBft.java +++ b/src/main/java/org/semux/consensus/SemuxBft.java @@ -682,7 +682,7 @@ public void onMessage(Channel channel, Message msg) { * Update the validator sets. */ protected void updateValidators() { - int maxValidators = config.getNumberOfValidators(height); + int maxValidators = config.spec().getNumberOfValidators(height); validators = chain.getValidators(); // if the chain is reporting a larger number of validators @@ -731,7 +731,7 @@ protected boolean isPrimary() { * @return */ protected boolean isPrimary(long height, int view, String peerId) { - return config + return config.spec() .getPrimaryValidator(validators, height, view, chain.isForkActivated(UNIFORM_DISTRIBUTION, height)) .equals(peerId); } @@ -788,7 +788,7 @@ protected Block proposeBlock() { // fetch pending transactions final List pending = pendingMgr - .getPendingTransactions(config.maxBlockTransactionsSize()); + .getPendingTransactions(config.spec().maxBlockTransactionsSize()); final List pendingTxs = new ArrayList<>(); final List pendingResults = new ArrayList<>(); @@ -800,7 +800,7 @@ protected Block proposeBlock() { new byte[0], new byte[0], data); // only propose gas used up to configured block gas limit - SemuxBlock semuxBlock = new SemuxBlock(tempHeader, config.vmBlockGasLimit()); + SemuxBlock semuxBlock = new SemuxBlock(tempHeader, config.poolBlockGasLimit()); long gasUsed = 0; @@ -809,12 +809,12 @@ protected Block proposeBlock() { || tx.transaction.getType() == TransactionType.CREATE) { long pendingGasForBlock = tx.transaction.getGas() + gasUsed; - if (tx.transaction.getGasPrice() >= config.vmMinGasPrice() - && pendingGasForBlock < config.vmBlockGasLimit()) { + if (tx.transaction.getGasPrice() >= config.poolMinGasPrice() + && pendingGasForBlock < config.poolBlockGasLimit()) { TransactionResult result = exec.execute(tx.transaction, as, ds, semuxBlock, chain); gasUsed += result.getGasUsed(); - if (result.getCode().isAcceptable() && gasUsed < config.vmBlockGasLimit()) { + if (result.getCode().isAcceptable() && gasUsed < config.poolBlockGasLimit()) { pendingResults.add(result); pendingTxs.add(tx.transaction); } else { @@ -864,7 +864,7 @@ protected boolean validateBlockProposal(Block block) { return false; } - if (header.getTimestamp() - TimeUtil.currentTimeMillis() > config.maxBlockTimeDrift()) { + if (header.getTimestamp() - TimeUtil.currentTimeMillis() > config.bftMaxBlockTimeDrift()) { logger.warn("A block in the future is not allowed"); return false; } @@ -887,7 +887,7 @@ protected boolean validateBlockProposal(Block block) { return false; } - if (transactions.stream().mapToInt(Transaction::size).sum() > config.maxBlockTransactionsSize()) { + if (transactions.stream().mapToInt(Transaction::size).sum() > config.spec().maxBlockTransactionsSize()) { logger.warn("Block transactions size exceeds maximum"); return false; } @@ -906,7 +906,7 @@ protected boolean validateBlockProposal(Block block) { // against our own local limit, only // when proposing List results = exec.execute(transactions, as, ds, - new SemuxBlock(header, config.vmMaxBlockGasLimit()), chain); + new SemuxBlock(header, config.spec().maxBlockGasLimit()), chain); block.setResults(results); if (!block.validateResults(header, results)) { @@ -973,7 +973,7 @@ protected void applyBlock(Block block) { // [3] evaluate all transactions List results = exec.execute(transactions, as, ds, - new SemuxBlock(block.getHeader(), config.vmMaxBlockGasLimit()), chain); + new SemuxBlock(block.getHeader(), config.spec().maxBlockGasLimit()), chain); if (!block.validateResults(header, results)) { logger.debug("Invalid transactions"); return; diff --git a/src/main/java/org/semux/consensus/SemuxSync.java b/src/main/java/org/semux/consensus/SemuxSync.java index b59eae063..73b568f45 100644 --- a/src/main/java/org/semux/consensus/SemuxSync.java +++ b/src/main/java/org/semux/consensus/SemuxSync.java @@ -368,11 +368,11 @@ protected void process() { synchronized (lock) { if (!fastSync) { // fastSync value is updated at the beginning of each set - if (latest % config.getValidatorUpdateInterval() == 0) { - if (target.get() >= latest + config.getValidatorUpdateInterval()) { + if (latest % config.spec().getValidatorUpdateInterval() == 0) { + if (target.get() >= latest + config.spec().getValidatorUpdateInterval()) { toFinalize.clear(); currentSet.clear(); - lastBlockInSet = latest + config.getValidatorUpdateInterval(); + lastBlockInSet = latest + config.spec().getValidatorUpdateInterval(); fastSync = true; } } @@ -562,7 +562,7 @@ protected boolean validateBlock(Block block, AccountState asSnapshot, DelegateSt // [2] check transactions and results if (!block.validateTransactions(header, transactions, config.network()) - || transactions.stream().mapToInt(Transaction::size).sum() > config.maxBlockTransactionsSize()) { + || transactions.stream().mapToInt(Transaction::size).sum() > config.spec().maxBlockTransactionsSize()) { logger.error("Invalid block transactions"); return false; } @@ -579,7 +579,7 @@ protected boolean validateBlock(Block block, AccountState asSnapshot, DelegateSt // [3] evaluate transactions TransactionExecutor transactionExecutor = new TransactionExecutor(config, blockStore); List results = transactionExecutor.execute(transactions, asSnapshot, dsSnapshot, - new SemuxBlock(block.getHeader(), config.vmMaxBlockGasLimit()), chain); + new SemuxBlock(block.getHeader(), config.spec().maxBlockGasLimit()), chain); block.setResults(results); if (!block.validateResults(header, results)) { @@ -599,7 +599,7 @@ protected boolean validateBlock(Block block, AccountState asSnapshot, DelegateSt } protected boolean validateBlockVotes(Block block) { - int maxValidators = config.getNumberOfValidators(block.getNumber()); + int maxValidators = config.spec().getNumberOfValidators(block.getNumber()); List validatorList = chain.getValidators(); diff --git a/src/main/java/org/semux/core/Block.java b/src/main/java/org/semux/core/Block.java index ddf7f5b8d..138091432 100644 --- a/src/main/java/org/semux/core/Block.java +++ b/src/main/java/org/semux/core/Block.java @@ -251,7 +251,7 @@ public static Amount getBlockReward(Block block, Config config) { Amount txsReward = block.getTransactions().stream().map(Transaction::getFee).reduce(ZERO, Amount::sum); Amount gasReward = getGasReward(block); - Amount reward = sum(sum(config.getBlockReward(block.getNumber()), txsReward), gasReward); + Amount reward = sum(sum(config.spec().getBlockReward(block.getNumber()), txsReward), gasReward); return reward; } diff --git a/src/main/java/org/semux/core/BlockchainImpl.java b/src/main/java/org/semux/core/BlockchainImpl.java index 3652c70c7..8436bb7cf 100644 --- a/src/main/java/org/semux/core/BlockchainImpl.java +++ b/src/main/java/org/semux/core/BlockchainImpl.java @@ -371,7 +371,8 @@ public synchronized void addBlock(Block block) { // [5] update validator statistics List validators = getValidators(); - String primary = config.getPrimaryValidator(validators, number, 0, forks.isActivated(UNIFORM_DISTRIBUTION)); + String primary = config.spec().getPrimaryValidator(validators, number, 0, + forks.isActivated(UNIFORM_DISTRIBUTION)); adjustValidatorStats(block.getCoinbase(), StatsType.FORGED, 1); if (primary.equals(Hex.encode(block.getCoinbase()))) { adjustValidatorStats(Hex.decode0x(primary), StatsType.HIT, 1); @@ -381,7 +382,7 @@ public synchronized void addBlock(Block block) { } // [6] update validator set - if (number % config.getValidatorUpdateInterval() == 0) { + if (number % config.spec().getValidatorUpdateInterval() == 0) { updateValidators(block.getNumber()); } @@ -459,7 +460,7 @@ public void updateValidators(long number) { List validators = new ArrayList<>(); List delegates = delegateState.getDelegates(); - int max = Math.min(delegates.size(), config.getNumberOfValidators(number)); + int max = Math.min(delegates.size(), config.spec().getNumberOfValidators(number)); for (int i = 0; i < max; i++) { Delegate d = delegates.get(i); validators.add(Hex.encode(d.getAddress())); @@ -722,7 +723,7 @@ public void applyBlock(Block block) { // [0] execute transactions against local state TransactionExecutor transactionExecutor = new TransactionExecutor(config, blockStore); transactionExecutor.execute(block.getTransactions(), getAccountState(), getDelegateState(), - new SemuxBlock(block.getHeader(), config.vmMaxBlockGasLimit()), this); + new SemuxBlock(block.getHeader(), config.spec().maxBlockGasLimit()), this); // [1] apply block reward and tx fees Amount reward = Block.getBlockReward(block, config); diff --git a/src/main/java/org/semux/core/PendingManager.java b/src/main/java/org/semux/core/PendingManager.java index ffdf86b4d..f8815e115 100644 --- a/src/main/java/org/semux/core/PendingManager.java +++ b/src/main/java/org/semux/core/PendingManager.java @@ -323,8 +323,8 @@ protected ProcessingResult processTransaction(Transaction tx, boolean relay) { // check transaction timestamp if this is a fresh transaction: // a time drift of 2 hours is allowed by default - if (tx.getTimestamp() < now - kernel.getConfig().maxTransactionTimeDrift() - || tx.getTimestamp() > now + kernel.getConfig().maxTransactionTimeDrift()) { + if (tx.getTimestamp() < now - kernel.getConfig().poolMaxTransactionTimeDrift() + || tx.getTimestamp() > now + kernel.getConfig().poolMaxTransactionTimeDrift()) { return new ProcessingResult(0, TransactionResult.Code.INVALID_TIMESTAMP); } @@ -347,7 +347,7 @@ protected ProcessingResult processTransaction(Transaction tx, boolean relay) { prevBlock.getNumber() + 1, new Key().toAddress(), prevBlock.getHash(), System.currentTimeMillis(), new byte[0], new byte[0], new byte[0], new byte[0]); - SemuxBlock block = new SemuxBlock(blockHeader, kernel.getConfig().vmMaxBlockGasLimit()); + SemuxBlock block = new SemuxBlock(blockHeader, kernel.getConfig().spec().maxBlockGasLimit()); // execute transactions AccountState as = pendingAS.track(); diff --git a/src/main/java/org/semux/core/TransactionExecutor.java b/src/main/java/org/semux/core/TransactionExecutor.java index 997bbb12f..18967eed5 100644 --- a/src/main/java/org/semux/core/TransactionExecutor.java +++ b/src/main/java/org/semux/core/TransactionExecutor.java @@ -127,14 +127,14 @@ public List execute(List txs, AccountState as, D continue; } } else { - if (fee.lt(config.minTransactionFee())) { + if (fee.lt(config.spec().minTransactionFee())) { result.setCode(Code.INVALID_FEE); continue; } } // check data length - if (data.length > config.maxTransactionDataSize(type)) { + if (data.length > config.spec().maxTransactionDataSize(type)) { result.setCode(Code.INVALID_DATA); continue; } @@ -154,7 +154,7 @@ public List execute(List txs, AccountState as, D result.setCode(Code.INVALID_DELEGATE_NAME); break; } - if (value.lt(config.minDelegateBurnAmount())) { + if (value.lt(config.spec().minDelegateBurnAmount())) { result.setCode(Code.INVALID_DELEGATE_BURN_AMOUNT); break; } @@ -228,7 +228,7 @@ public List execute(List txs, AccountState as, D // VM calls can have fees/values set. as.adjustAvailable(from, neg(sum(value, fee))); - if (tx.getGas() > config.vmMaxBlockGasLimit()) { + if (tx.getGas() > config.spec().maxBlockGasLimit()) { result.setCode(Code.INVALID_GAS); } else { executeVmTransaction(result, tx, as, block, gasUsedInBlock); diff --git a/src/main/java/org/semux/gui/SemuxGui.java b/src/main/java/org/semux/gui/SemuxGui.java index 37b93dfc9..146d4bb67 100644 --- a/src/main/java/org/semux/gui/SemuxGui.java +++ b/src/main/java/org/semux/gui/SemuxGui.java @@ -132,7 +132,7 @@ public static void main(String[] args) { * Creates a new Semux GUI instance. */ public SemuxGui() { - SystemUtil.setLocale(getConfig().locale()); + SystemUtil.setLocale(getConfig().uiLocale()); SwingUtil.setDefaultFractionDigits(getConfig().uiFractionDigits()); SwingUtil.setDefaultUnit(getConfig().uiUnit()); @@ -147,7 +147,7 @@ public SemuxGui() { * @param kernel */ public SemuxGui(WalletModel model, Kernel kernel) { - SystemUtil.setLocale(getConfig().locale()); + SystemUtil.setLocale(getConfig().uiLocale()); this.model = model; this.kernel = kernel; diff --git a/src/main/java/org/semux/gui/SwingUtil.java b/src/main/java/org/semux/gui/SwingUtil.java index 93abd1d3b..f81bf4005 100644 --- a/src/main/java/org/semux/gui/SwingUtil.java +++ b/src/main/java/org/semux/gui/SwingUtil.java @@ -7,7 +7,6 @@ package org.semux.gui; import static java.util.Arrays.stream; - import static org.semux.core.Amount.Unit.SEM; import static org.semux.gui.TextContextMenuItem.COPY; import static org.semux.gui.TextContextMenuItem.CUT; diff --git a/src/main/java/org/semux/gui/model/WalletModel.java b/src/main/java/org/semux/gui/model/WalletModel.java index d8cce3765..df99c638b 100644 --- a/src/main/java/org/semux/gui/model/WalletModel.java +++ b/src/main/java/org/semux/gui/model/WalletModel.java @@ -251,7 +251,7 @@ public Optional getValidator(int view) { return Optional.empty(); } - return Optional.ofNullable(config.getPrimaryValidator(validators, + return Optional.ofNullable(config.spec().getPrimaryValidator(validators, latestBlock.getNumber() + 1, view, isUniformDistributionEnabled())); @@ -286,7 +286,7 @@ public Optional getNextPrimaryValidatorDelegate() { // the next validator can't be predicted if the validator set is going to be // updated in the next round - if ((latestBlock.getNumber() + 2) % config.getValidatorUpdateInterval() == 0) { + if ((latestBlock.getNumber() + 2) % config.spec().getValidatorUpdateInterval() == 0) { return Optional.empty(); } @@ -308,8 +308,8 @@ public Optional getNextValidatorSetUpdate() { } return Optional.of( - ((latestBlock.getNumber() + 1) / config.getValidatorUpdateInterval() + 1) - * config.getValidatorUpdateInterval()); + ((latestBlock.getNumber() + 1) / config.spec().getValidatorUpdateInterval() + 1) + * config.spec().getValidatorUpdateInterval()); } public void setUniformDistributionEnabled(boolean enabled) { diff --git a/src/main/java/org/semux/gui/panel/DelegatesPanel.java b/src/main/java/org/semux/gui/panel/DelegatesPanel.java index 47b1e2577..1b5abf723 100644 --- a/src/main/java/org/semux/gui/panel/DelegatesPanel.java +++ b/src/main/java/org/semux/gui/panel/DelegatesPanel.java @@ -142,8 +142,8 @@ public void mousePressed(MouseEvent me) { delegateRegistrationPanel.setBorder(new LineBorder(Color.LIGHT_GRAY)); JLabel label = new JLabel(GuiMessages - .get("DelegateRegistrationNoteHtml", SwingUtil.formatAmount(config.minDelegateBurnAmount()), - SwingUtil.formatAmount(config.minTransactionFee()))); + .get("DelegateRegistrationNoteHtml", SwingUtil.formatAmount(config.spec().minDelegateBurnAmount()), + SwingUtil.formatAmount(config.spec().minTransactionFee()))); label.setForeground(Color.DARK_GRAY); selectFrom = new JComboBox<>(); @@ -248,7 +248,8 @@ public void mousePressed(MouseEvent me) { .createDefaultButton(GuiMessages.get("RegisterAsDelegate"), this, Action.DELEGATE); btnDelegate.setName("btnDelegate"); btnDelegate.setToolTipText( - GuiMessages.get("RegisterAsDelegateToolTip", SwingUtil.formatAmount(config.minDelegateBurnAmount()))); + GuiMessages.get("RegisterAsDelegateToolTip", + SwingUtil.formatAmount(config.spec().minDelegateBurnAmount()))); textName = SwingUtil.textFieldWithCopyPastePopup(); @@ -468,7 +469,7 @@ protected void voteOrUnvote(Action action) { JOptionPane.showMessageDialog(this, GuiMessages.get("EnterValidNumberOfVotes")); return; } - Amount fee = config.minTransactionFee(); + Amount fee = config.spec().minTransactionFee(); if (a == null) { JOptionPane.showMessageDialog(this, GuiMessages.get("SelectAccount")); @@ -538,9 +539,10 @@ protected void delegate() { JOptionPane.showMessageDialog(this, GuiMessages.get("SelectAccount")); } else if (!name.matches("[_a-z0-9]{3,16}")) { JOptionPane.showMessageDialog(this, GuiMessages.get("AccountNameError")); - } else if (a.getAvailable().lt(sum(config.minDelegateBurnAmount(), config.minTransactionFee()))) { + } else if (a.getAvailable().lt(sum(config.spec().minDelegateBurnAmount(), config.spec().minTransactionFee()))) { JOptionPane.showMessageDialog(this, GuiMessages.get("InsufficientFunds", - SwingUtil.formatAmount(sum(config.minDelegateBurnAmount(), config.minTransactionFee())))); + SwingUtil.formatAmount( + sum(config.spec().minDelegateBurnAmount(), config.spec().minTransactionFee())))); } else { // validate delegate address DelegateState delegateState = kernel.getBlockchain().getDelegateState(); @@ -573,7 +575,8 @@ protected void delegate() { // confirm burning amount if (JOptionPane.showConfirmDialog(this, - GuiMessages.get("DelegateRegistrationInfo", SwingUtil.formatAmount(config.minDelegateBurnAmount())), + GuiMessages.get("DelegateRegistrationInfo", + SwingUtil.formatAmount(config.spec().minDelegateBurnAmount())), GuiMessages.get("ConfirmDelegateRegistration"), JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { return; @@ -584,8 +587,8 @@ protected void delegate() { Network network = kernel.getConfig().network(); TransactionType type = TransactionType.DELEGATE; byte[] to = Bytes.EMPTY_ADDRESS; - Amount value = config.minDelegateBurnAmount(); - Amount fee = config.minTransactionFee(); + Amount value = config.spec().minDelegateBurnAmount(); + Amount fee = config.spec().minTransactionFee(); long nonce = pendingMgr.getNonce(a.getAddress()); long timestamp = TimeUtil.currentTimeMillis(); byte[] data = Bytes.of(name); diff --git a/src/main/java/org/semux/gui/panel/SendPanel.java b/src/main/java/org/semux/gui/panel/SendPanel.java index bd56bf240..d30087237 100644 --- a/src/main/java/org/semux/gui/panel/SendPanel.java +++ b/src/main/java/org/semux/gui/panel/SendPanel.java @@ -106,7 +106,7 @@ public SendPanel(SemuxGui gui, JFrame frame) { JLabel lblFee = new JLabel(GuiMessages.get("Fee") + ":"); lblFee.setHorizontalAlignment(SwingConstants.RIGHT); - lblFee.setToolTipText(GuiMessages.get("FeeTip", SwingUtil.formatAmount(config.minTransactionFee()))); + lblFee.setToolTipText(GuiMessages.get("FeeTip", SwingUtil.formatAmount(config.spec().minTransactionFee()))); txtFee = SwingUtil.textFieldWithCopyPastePopup(); txtFee.setName("txtFee"); @@ -375,15 +375,15 @@ protected void send() { showErrorDialog(GuiMessages.get("SelectAccount")); } else if (value.lte0()) { showErrorDialog(GuiMessages.get("EnterValidValue")); - } else if (fee.lt(config.minTransactionFee())) { + } else if (fee.lt(config.spec().minTransactionFee())) { showErrorDialog(GuiMessages.get("TransactionFeeTooLow")); } else if (sum(value, fee).gt(acc.getAvailable())) { showErrorDialog(GuiMessages.get("InsufficientFunds", SwingUtil.formatAmount(sum(value, fee)))); } else if (to.length != Key.ADDRESS_LEN) { showErrorDialog(GuiMessages.get("InvalidReceivingAddress")); - } else if (Bytes.of(data).length > config.maxTransactionDataSize(TransactionType.TRANSFER)) { + } else if (Bytes.of(data).length > config.spec().maxTransactionDataSize(TransactionType.TRANSFER)) { showErrorDialog( - GuiMessages.get("InvalidData", config.maxTransactionDataSize(TransactionType.TRANSFER))); + GuiMessages.get("InvalidData", config.spec().maxTransactionDataSize(TransactionType.TRANSFER))); } else { int ret = JOptionPane.showConfirmDialog(this, GuiMessages.get("TransferInfo", SwingUtil.formatAmountFull(value), Hex.encode0x(to)), @@ -415,7 +415,7 @@ protected void send() { protected void clear() { setToText(Bytes.EMPTY_BYTES); setAmountText(Amount.ZERO); - setFeeText(config.minTransactionFee()); + setFeeText(config.spec().minTransactionFee()); setDataText(""); } diff --git a/src/test/java/org/semux/TestUtils.java b/src/test/java/org/semux/TestUtils.java index 21f33ee44..462294ceb 100644 --- a/src/test/java/org/semux/TestUtils.java +++ b/src/test/java/org/semux/TestUtils.java @@ -61,7 +61,7 @@ public static Transaction createTransaction(Config config, Key from, Key to, Amo public static Transaction createTransaction(Config config, Key from, Key to, Amount value, long nonce) { Network network = config.network(); TransactionType type = TransactionType.TRANSFER; - Amount fee = config.minTransactionFee(); + Amount fee = config.spec().minTransactionFee(); long timestamp = TimeUtil.currentTimeMillis(); byte[] data = {}; diff --git a/src/test/java/org/semux/api/http/HttpHandlerTest.java b/src/test/java/org/semux/api/http/HttpHandlerTest.java index 073e63625..e44e4ecd5 100644 --- a/src/test/java/org/semux/api/http/HttpHandlerTest.java +++ b/src/test/java/org/semux/api/http/HttpHandlerTest.java @@ -8,7 +8,6 @@ import static java.net.HttpURLConnection.HTTP_NOT_FOUND; import static java.net.HttpURLConnection.HTTP_OK; - import static junit.framework.TestCase.assertTrue; import static org.awaitility.Awaitility.await; import static org.junit.Assert.assertEquals; diff --git a/src/test/java/org/semux/api/v2/SemuxApiTest.java b/src/test/java/org/semux/api/v2/SemuxApiTest.java index b2e2cac3d..34ad4535a 100644 --- a/src/test/java/org/semux/api/v2/SemuxApiTest.java +++ b/src/test/java/org/semux/api/v2/SemuxApiTest.java @@ -234,9 +234,9 @@ public void getAccountPendingTransactionsTest() { Transaction tx0 = createTransaction(config); Transaction tx1 = createTransaction(config, from, to, Amount.ZERO); Transaction tx2 = createTransaction(config, to, from, Amount.ZERO); - chain.getAccountState().adjustAvailable(tx0.getFrom(), config.minTransactionFee()); - chain.getAccountState().adjustAvailable(from.toAddress(), config.minTransactionFee()); - chain.getAccountState().adjustAvailable(to.toAddress(), config.minTransactionFee()); + chain.getAccountState().adjustAvailable(tx0.getFrom(), config.spec().minTransactionFee()); + chain.getAccountState().adjustAvailable(from.toAddress(), config.spec().minTransactionFee()); + chain.getAccountState().adjustAvailable(to.toAddress(), config.spec().minTransactionFee()); assert (pendingMgr.addTransactionSync(tx0).accepted == 1); assert (pendingMgr.addTransactionSync(tx1).accepted == 1); assert (pendingMgr.addTransactionSync(tx2).accepted == 1); @@ -473,13 +473,13 @@ public void getTransactionLimitsTest() { GetTransactionLimitsResponse response = api.getTransactionLimits(type.toString()); assertNotNull(response); assertTrue(response.isSuccess()); - assertEquals(config.maxTransactionDataSize(type), + assertEquals(config.spec().maxTransactionDataSize(type), response.getResult().getMaxTransactionDataSize().intValue()); - assertEquals(config.minTransactionFee().getNano(), + assertEquals(config.spec().minTransactionFee().getNano(), Long.parseLong(response.getResult().getMinTransactionFee())); if (type.equals(org.semux.core.TransactionType.DELEGATE)) { - assertEquals(config.minDelegateBurnAmount().getNano(), + assertEquals(config.spec().minDelegateBurnAmount().getNano(), Long.parseLong(response.getResult().getMinDelegateBurnAmount())); } else { assertNull(response.getResult().getMinDelegateBurnAmount()); @@ -540,7 +540,7 @@ public void listAccountsTest() { @Test public void registerDelegateTest() throws InterruptedException { String from = wallet.getAccount(0).toAddressString(); - String fee = String.valueOf(config.minTransactionFee().getNano()); + String fee = String.valueOf(config.spec().minTransactionFee().getNano()); String data = Hex.encode(Bytes.of("test_delegate")); DoTransactionResponse response = api.registerDelegate(from, data, fee, null, null); assertNotNull(response); @@ -561,7 +561,7 @@ public void broadcastRawTransactionTest() throws InterruptedException { Key to = new Key(); Amount value = Amount.ZERO; kernelRule.getKernel().getBlockchain().getAccountState().adjustAvailable(from.toAddress(), - config.minTransactionFee()); + config.spec().minTransactionFee()); Transaction tx = createTransaction(config, from, to, value); DoTransactionResponse response = api.broadcastRawTransaction(Hex.encode(tx.toBytes()), null); @@ -581,7 +581,7 @@ public void broadcastRawTransactionValidateNonceTest() { // mock state kernelRule.getKernel().getBlockchain().getAccountState().adjustAvailable(from.toAddress(), - config.minTransactionFee()); + config.spec().minTransactionFee()); PendingManager pendingManager = spy(pendingMgr); when(pendingManager.getNonce(from.toAddress())).thenReturn(100L); kernelRule.getKernel().setPendingManager(pendingManager); @@ -598,7 +598,7 @@ public void broadcastRawTransactionNoValidateNonceTest() { // mock state kernelRule.getKernel().getBlockchain().getAccountState().adjustAvailable(from.toAddress(), - config.minTransactionFee()); + config.spec().minTransactionFee()); PendingManager pendingManager = spy(pendingMgr); when(pendingManager.getNonce(from.toAddress())).thenReturn(100L); kernelRule.getKernel().setPendingManager(pendingManager); @@ -707,7 +707,7 @@ public void transferDefaultFeeTest() throws InterruptedException { Transaction tx = list.get(list.size() - 1).transaction; assertArrayEquals(tx.getHash(), Hex.decode0x(response.getResult())); assertEquals(TRANSFER, tx.getType()); - assertEquals(config.minTransactionFee(), tx.getFee()); + assertEquals(config.spec().minTransactionFee(), tx.getFee()); } @Test @@ -752,7 +752,7 @@ public void voteTest() throws InterruptedException { String from = wallet.getAccount(0).toAddressString(); String to = delegate.toAddressString(); String value = String.valueOf(amount.getNano()); - String fee = String.valueOf(config.minTransactionFee().getNano()); + String fee = String.valueOf(config.spec().minTransactionFee().getNano()); DoTransactionResponse response = api.vote(from, to, value, fee, null, null); assertTrue(response.isSuccess()); @@ -772,7 +772,7 @@ public void composeRawTransactionTransferTest() { String type = "TRANSFER"; String to = "0xdb7cadb25fdcdd546fb0268524107582c3f8999c"; String value = "123456789"; - String fee = String.valueOf(config.minTransactionFee().getNano()); + String fee = String.valueOf(config.spec().minTransactionFee().getNano()); String nonce = "123"; String timestamp = "1523028482000"; String data = Hex.encode0x("test data".getBytes()); @@ -799,7 +799,7 @@ public void composeRawTransactionDelegateTest() { String type = "DELEGATE"; String to = ""; String value = ""; - String fee = String.valueOf(config.minTransactionFee().getNano()); + String fee = String.valueOf(config.spec().minTransactionFee().getNano()); String nonce = "123"; String timestamp = "1523028482000"; String data = Hex.encode0x("semux1".getBytes()); @@ -826,7 +826,7 @@ public void composeRawTransactionVoteTest() { String type = "VOTE"; String to = "0xdb7cadb25fdcdd546fb0268524107582c3f8999c"; String value = "123"; - String fee = String.valueOf(config.minTransactionFee().getNano()); + String fee = String.valueOf(config.spec().minTransactionFee().getNano()); String nonce = "123"; String timestamp = "1523028482000"; String data = Hex.encode0x("semux1".getBytes()); diff --git a/src/test/java/org/semux/bench/BlockchainPerformance.java b/src/test/java/org/semux/bench/BlockchainPerformance.java index 46636a57b..59184e619 100644 --- a/src/test/java/org/semux/bench/BlockchainPerformance.java +++ b/src/test/java/org/semux/bench/BlockchainPerformance.java @@ -52,13 +52,13 @@ public static Block testBlockCreation() { TransactionType type = TransactionType.TRANSFER; byte[] to = Bytes.random(20); Amount value = NANO_SEM.of(1); - Amount fee = config.minTransactionFee(); + Amount fee = config.spec().minTransactionFee(); 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); - if (total + tx.size() > config.maxBlockTransactionsSize()) { + if (total + tx.size() > config.spec().maxBlockTransactionsSize()) { break; } @@ -81,7 +81,7 @@ public static Block testBlockCreation() { Block block = new Block(header, txs, res); List votes = new ArrayList<>(); - for (int i = 0; i < config.getNumberOfValidators(1000000L); i++) { + for (int i = 0; i < config.spec().getNumberOfValidators(1000000L); i++) { votes.add(new Key().sign(Bytes.EMPTY_BYTES)); } block.setView(1); @@ -118,7 +118,7 @@ public static void testTransactionValidation() { TransactionType type = TransactionType.TRANSFER; byte[] to = Bytes.random(20); Amount value = NANO_SEM.of(1); - Amount fee = config.minTransactionFee(); + Amount fee = config.spec().minTransactionFee(); long nonce = 1; long timestamp = TimeUtil.currentTimeMillis(); byte[] data = {}; diff --git a/src/test/java/org/semux/bench/SemuxPerformance.java b/src/test/java/org/semux/bench/SemuxPerformance.java index b9686f56c..5e786aa8b 100644 --- a/src/test/java/org/semux/bench/SemuxPerformance.java +++ b/src/test/java/org/semux/bench/SemuxPerformance.java @@ -39,7 +39,7 @@ public static void testTransfer(int n) throws IOException, InterruptedException params.put("from", address); params.put("to", address); params.put("value", MILLI_SEM.of(1).getNano()); - params.put("fee", config.minTransactionFee().getNano()); + params.put("fee", config.spec().minTransactionFee().getNano()); params.put("data", Bytes.EMPTY_BYTES); params.put("password", password); diff --git a/src/test/java/org/semux/config/MainnetConfigTest.java b/src/test/java/org/semux/config/MainnetConfigTest.java index 0ef27c9c3..38c22b8a9 100644 --- a/src/test/java/org/semux/config/MainnetConfigTest.java +++ b/src/test/java/org/semux/config/MainnetConfigTest.java @@ -59,7 +59,7 @@ public void testBlockReward() { public void testNumberOfValidators() { int last = 0; for (int i = 0; i < 60 * Constants.BLOCKS_PER_DAY; i++) { - int n = config.getNumberOfValidators(i); + int n = config.spec().getNumberOfValidators(i); if (n != last) { assertTrue(n > last && (n - last == 1 || last == 0)); logger.info("block # = {}, validators = {}", i, n); @@ -84,7 +84,7 @@ public void testPrimaryUniformDistDeterminism() throws IOException { StringBuilder validatorsCSV = new StringBuilder(); for (long i = 0; i < blocks; i++) { for (int view = 0; view < views; view++) { - String primary = config.getPrimaryValidator(validators, i, view, true); + String primary = config.spec().getPrimaryValidator(validators, i, view, true); primaryValidators[(int) i][view] = primary; if (view > 0 && primaryValidators[(int) i][view].equals(primaryValidators[(int) i][view - 1])) { diff --git a/src/test/java/org/semux/consensus/SemuxBftTest.java b/src/test/java/org/semux/consensus/SemuxBftTest.java index 726568ff0..e2070cd58 100644 --- a/src/test/java/org/semux/consensus/SemuxBftTest.java +++ b/src/test/java/org/semux/consensus/SemuxBftTest.java @@ -264,7 +264,7 @@ private Transaction createTransaction(Key to, Key from, long time, long nonce) { TransactionType.TRANSFER, to.toAddress(), SEM.of(10), - kernelRule.getKernel().getConfig().minTransactionFee(), + kernelRule.getKernel().getConfig().spec().minTransactionFee(), nonce, time, Bytes.EMPTY_BYTES).sign(from); diff --git a/src/test/java/org/semux/consensus/SemuxBftValidateBlockTest.java b/src/test/java/org/semux/consensus/SemuxBftValidateBlockTest.java index 0a1896a93..cfc8c69c3 100644 --- a/src/test/java/org/semux/consensus/SemuxBftValidateBlockTest.java +++ b/src/test/java/org/semux/consensus/SemuxBftValidateBlockTest.java @@ -50,7 +50,7 @@ public static Collection data() { }, (Supplier) () -> { Config config = mock(Config.class); - when(config.maxBlockTimeDrift()).thenReturn(TimeUnit.MINUTES.toMillis(15)); + when(config.bftMaxBlockTimeDrift()).thenReturn(TimeUnit.MINUTES.toMillis(15)); return config; }, (Supplier) () -> { diff --git a/src/test/java/org/semux/consensus/SemuxSyncTest.java b/src/test/java/org/semux/consensus/SemuxSyncTest.java index 55eeeb1ee..32bcd8914 100644 --- a/src/test/java/org/semux/consensus/SemuxSyncTest.java +++ b/src/test/java/org/semux/consensus/SemuxSyncTest.java @@ -80,7 +80,7 @@ public void testDuplicatedTransaction() { TransactionType.TRANSFER, to.toAddress(), SEM.of(10), - kernelRule.getKernel().getConfig().minTransactionFee(), + kernelRule.getKernel().getConfig().spec().minTransactionFee(), 0, time, Bytes.EMPTY_BYTES).sign(from1); @@ -100,7 +100,7 @@ public void testDuplicatedTransaction() { TransactionType.TRANSFER, to.toAddress(), SEM.of(10), - kernelRule.getKernel().getConfig().minTransactionFee(), + kernelRule.getKernel().getConfig().spec().minTransactionFee(), 0, time, Bytes.EMPTY_BYTES).sign(from2); @@ -236,7 +236,7 @@ public void testFastSync() throws Exception { doNothing().when(chain).updateValidators(anyLong()); kernelRule.getKernel().setBlockchain(chain); - validatorInterval = kernelRule.getKernel().getConfig().getValidatorUpdateInterval(); + validatorInterval = kernelRule.getKernel().getConfig().spec().getValidatorUpdateInterval(); SemuxSync sync = spy(new SemuxSync(kernelRule.getKernel())); MessageQueue msgQueue = mock(MessageQueue.class); @@ -311,7 +311,7 @@ public void testNormalSync() throws Exception { doReturn(validators).when(chain).getValidators(); kernelRule.getKernel().setBlockchain(chain); - validatorInterval = kernelRule.getKernel().getConfig().getValidatorUpdateInterval(); + validatorInterval = kernelRule.getKernel().getConfig().spec().getValidatorUpdateInterval(); SemuxSync sync = spy(new SemuxSync(kernelRule.getKernel())); MessageQueue msgQueue = mock(MessageQueue.class); @@ -385,7 +385,7 @@ public void testValidateSetHashes() throws Exception { doReturn(validators).when(chain).getValidators(); kernelRule.getKernel().setBlockchain(chain); - validatorInterval = kernelRule.getKernel().getConfig().getValidatorUpdateInterval(); + validatorInterval = kernelRule.getKernel().getConfig().spec().getValidatorUpdateInterval(); SemuxSync sync = spy(new SemuxSync(kernelRule.getKernel())); TestUtils.setInternalState(sync, "lastBlockInSet", validatorInterval, SemuxSync.class); diff --git a/src/test/java/org/semux/core/BlockTest.java b/src/test/java/org/semux/core/BlockTest.java index 73c3e762e..13e0e2b23 100644 --- a/src/test/java/org/semux/core/BlockTest.java +++ b/src/test/java/org/semux/core/BlockTest.java @@ -39,7 +39,7 @@ public class BlockTest { private byte[] data = Bytes.of("data"); private Transaction tx = new Transaction(Network.DEVNET, TransactionType.TRANSFER, Bytes.random(20), ZERO, - config.minTransactionFee(), + config.spec().minTransactionFee(), 1, TimeUtil.currentTimeMillis(), Bytes.EMPTY_BYTES).sign(new Key()); private TransactionResult res = new TransactionResult(); private List transactions = Collections.singletonList(tx); diff --git a/src/test/java/org/semux/core/CorePerformanceTest.java b/src/test/java/org/semux/core/CorePerformanceTest.java index 531856855..9d4ace243 100644 --- a/src/test/java/org/semux/core/CorePerformanceTest.java +++ b/src/test/java/org/semux/core/CorePerformanceTest.java @@ -66,7 +66,7 @@ public void testTransactionProcessing() { TransactionType type = TransactionType.TRANSFER; byte[] to = Bytes.random(20); Amount value = NANO_SEM.of(5); - Amount fee = config.minTransactionFee(); + Amount fee = config.spec().minTransactionFee(); long nonce = 1; long timestamp = TimeUtil.currentTimeMillis(); byte[] data = Bytes.random(16); @@ -88,7 +88,7 @@ public void testTransactionProcessing() { t1 = System.nanoTime(); exec.execute(txs, chain.getAccountState().track(), chain.getDelegateState().track(), - new SemuxBlock(chain.getLatestBlock().getHeader(), config.vmMaxBlockGasLimit()), null); + new SemuxBlock(chain.getLatestBlock().getHeader(), config.spec().maxBlockGasLimit()), null); t2 = System.nanoTime(); logger.info("Perf_transaction_2: {} μs/tx", (t2 - t1) / 1_000 / repeat); } diff --git a/src/test/java/org/semux/core/PendingManagerTest.java b/src/test/java/org/semux/core/PendingManagerTest.java index 93fbfc572..54ab7230a 100644 --- a/src/test/java/org/semux/core/PendingManagerTest.java +++ b/src/test/java/org/semux/core/PendingManagerTest.java @@ -68,7 +68,7 @@ public static void setUp() { accountState.adjustAvailable(from, SEM.of(10000)); network = kernel.getConfig().network(); - fee = kernel.getConfig().minTransactionFee(); + fee = kernel.getConfig().spec().minTransactionFee(); } @Before diff --git a/src/test/java/org/semux/core/TransactionExecutorTest.java b/src/test/java/org/semux/core/TransactionExecutorTest.java index 27442e3cd..64e066525 100644 --- a/src/test/java/org/semux/core/TransactionExecutorTest.java +++ b/src/test/java/org/semux/core/TransactionExecutorTest.java @@ -56,7 +56,7 @@ public void prepare() { ds = chain.getDelegateState(); exec = new TransactionExecutor(config, new SemuxBlockStore(chain)); network = config.network(); - block = new SemuxBlock(mock(BlockHeader.class), config.vmMaxBlockGasLimit()); + block = new SemuxBlock(mock(BlockHeader.class), config.spec().maxBlockGasLimit()); } private TransactionResult executeAndCommit(TransactionExecutor exec, Transaction tx, AccountState as, @@ -76,7 +76,7 @@ public void testTransfer() { byte[] from = key.toAddress(); byte[] to = Bytes.random(20); Amount value = NANO_SEM.of(5); - Amount fee = config.minTransactionFee(); + Amount fee = config.spec().minTransactionFee(); long nonce = as.getAccount(from).getNonce(); long timestamp = TimeUtil.currentTimeMillis(); byte[] data = Bytes.random(16); @@ -115,8 +115,8 @@ public void testDelegate() { TransactionType type = TransactionType.DELEGATE; byte[] from = delegate.toAddress(); byte[] to = Bytes.random(20); - Amount value = config.minDelegateBurnAmount(); - Amount fee = config.minTransactionFee(); + Amount value = config.spec().minDelegateBurnAmount(); + Amount fee = config.spec().minTransactionFee(); long nonce = as.getAccount(from).getNonce(); long timestamp = TimeUtil.currentTimeMillis(); byte[] data = Bytes.random(16); @@ -137,7 +137,7 @@ public void testDelegate() { result = executeAndCommit(exec, tx, as.track(), ds.track(), block); assertTrue(result.getCode().isSuccess()); - assertEquals(sub(available, sum(config.minDelegateBurnAmount(), fee)), + assertEquals(sub(available, sum(config.spec().minDelegateBurnAmount(), fee)), as.getAccount(delegate.toAddress()).getAvailable()); assertArrayEquals(delegate.toAddress(), ds.getDelegateByName(data).getAddress()); assertArrayEquals(data, ds.getDelegateByAddress(delegate.toAddress()).getName()); @@ -155,7 +155,7 @@ public void testVote() { byte[] from = voter.toAddress(); byte[] to = delegate.toAddress(); Amount value = SEM.of(33); - Amount fee = config.minTransactionFee(); + Amount fee = config.spec().minTransactionFee(); long nonce = as.getAccount(from).getNonce(); long timestamp = TimeUtil.currentTimeMillis(); byte[] data = {}; @@ -189,7 +189,7 @@ public void testUnvote() { byte[] from = voter.toAddress(); byte[] to = delegate.toAddress(); Amount value = SEM.of(33); - Amount fee = config.minTransactionFee(); + Amount fee = config.spec().minTransactionFee(); long nonce = as.getAccount(from).getNonce(); long timestamp = TimeUtil.currentTimeMillis(); byte[] data = {}; @@ -221,14 +221,14 @@ public void testUnvoteInsufficientFee() { Key voter = new Key(); Key delegate = new Key(); - as.adjustAvailable(voter.toAddress(), sub(config.minTransactionFee(), NANO_SEM.of(1))); + as.adjustAvailable(voter.toAddress(), sub(config.spec().minTransactionFee(), NANO_SEM.of(1))); ds.register(delegate.toAddress(), Bytes.of("delegate")); TransactionType type = TransactionType.UNVOTE; byte[] from = voter.toAddress(); byte[] to = delegate.toAddress(); Amount value = SEM.of(100); - Amount fee = config.minTransactionFee(); + Amount fee = config.spec().minTransactionFee(); long nonce = as.getAccount(from).getNonce(); long timestamp = TimeUtil.currentTimeMillis(); byte[] data = {}; diff --git a/src/test/java/org/semux/core/TransactionTest.java b/src/test/java/org/semux/core/TransactionTest.java index 66dc92f77..e4916396f 100644 --- a/src/test/java/org/semux/core/TransactionTest.java +++ b/src/test/java/org/semux/core/TransactionTest.java @@ -35,7 +35,7 @@ public class TransactionTest { private TransactionType type = TransactionType.TRANSFER; private byte[] to = Hex.decode0x("0xdb7cadb25fdcdd546fb0268524107582c3f8999c"); private Amount value = NANO_SEM.of(2); - private Amount fee = config.minTransactionFee(); + private Amount fee = config.spec().minTransactionFee(); private long nonce = 1; private long timestamp = 1523028482000L; private byte[] data = Bytes.of("data"); diff --git a/src/test/java/org/semux/core/VmTest.java b/src/test/java/org/semux/core/VmTest.java index 5a60129cf..ea56c221d 100644 --- a/src/test/java/org/semux/core/VmTest.java +++ b/src/test/java/org/semux/core/VmTest.java @@ -86,7 +86,7 @@ public void testCall() { SemuxBlock bh = new SemuxBlock( new BlockHeader(123l, Bytes.random(20), Bytes.random(20), System.currentTimeMillis(), Bytes.random(20), Bytes.random(20), Bytes.random(20), Bytes.random(20)), - config.vmMaxBlockGasLimit()); + config.spec().maxBlockGasLimit()); byte[] data = Bytes.random(16); long gas = 30000; @@ -136,7 +136,7 @@ public void testCreate() { SemuxBlock bh = new SemuxBlock( new BlockHeader(1l, Bytes.random(20), Bytes.random(32), System.currentTimeMillis(), Bytes.random(20), Bytes.random(20), Bytes.random(20), Bytes.random(20)), - config.vmMaxBlockGasLimit()); + config.spec().maxBlockGasLimit()); long gas = 1000000; long gasPrice = 1; diff --git a/src/test/java/org/semux/core/WalletTest.java b/src/test/java/org/semux/core/WalletTest.java index fbdabd8d1..5c05aeffb 100644 --- a/src/test/java/org/semux/core/WalletTest.java +++ b/src/test/java/org/semux/core/WalletTest.java @@ -7,7 +7,6 @@ package org.semux.core; import static java.nio.file.attribute.PosixFilePermission.OTHERS_READ; - import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; diff --git a/src/test/java/org/semux/gui/model/WalletModelTest.java b/src/test/java/org/semux/gui/model/WalletModelTest.java index a83d19681..571b8eff2 100644 --- a/src/test/java/org/semux/gui/model/WalletModelTest.java +++ b/src/test/java/org/semux/gui/model/WalletModelTest.java @@ -151,7 +151,7 @@ public void testTotalLocked() { @Test public void testGetPrimaryValidatorDelegate() { - when(config.getPrimaryValidator(any(), anyLong(), anyInt(), anyBoolean())).thenCallRealMethod(); + when(config.spec().getPrimaryValidator(any(), anyLong(), anyInt(), anyBoolean())).thenCallRealMethod(); model = new WalletModel(config); List delegates = Arrays.asList( new WalletDelegate(new Delegate(new Key().toAddress(), "delegate1".getBytes(), 0, Amount.ZERO)), @@ -170,7 +170,7 @@ public void testGetPrimaryValidatorDelegate() { @Test public void testGetNextPrimaryValidatorDelegate() { - when(config.getValidatorUpdateInterval()).thenCallRealMethod(); + when(config.spec().getValidatorUpdateInterval()).thenCallRealMethod(); model = new WalletModel(config); List delegates = Arrays.asList( new WalletDelegate(new Delegate(new Key().toAddress(), "delegate1".getBytes(), 0, Amount.ZERO)), @@ -202,7 +202,7 @@ public void testGetNextPrimaryValidatorDelegate() { @Test public void testGetNextValidatorSetUpdate() { - when(config.getValidatorUpdateInterval()).thenCallRealMethod(); + when(config.spec().getValidatorUpdateInterval()).thenCallRealMethod(); model = new WalletModel(config); Map testCases = new HashMap<>(); diff --git a/src/test/java/org/semux/gui/panel/DelegatesPanelTest.java b/src/test/java/org/semux/gui/panel/DelegatesPanelTest.java index 7d3cebd5a..4379b2477 100644 --- a/src/test/java/org/semux/gui/panel/DelegatesPanelTest.java +++ b/src/test/java/org/semux/gui/panel/DelegatesPanelTest.java @@ -240,8 +240,8 @@ public void testDelegateSuccess() { Transaction tx = transactionArgumentCaptor.getValue(); assertEquals(TransactionType.DELEGATE, tx.getType()); assertArrayEquals(Bytes.EMPTY_ADDRESS, tx.getTo()); - assertEquals(kernelMock.getConfig().minDelegateBurnAmount(), tx.getValue()); - assertEquals(kernelMock.getConfig().minTransactionFee(), tx.getFee()); + assertEquals(kernelMock.getConfig().spec().minDelegateBurnAmount(), tx.getValue()); + assertEquals(kernelMock.getConfig().spec().minTransactionFee(), tx.getFee()); } @Test diff --git a/src/test/java/org/semux/gui/panel/SendPanelTest.java b/src/test/java/org/semux/gui/panel/SendPanelTest.java index b54f8acb2..587a93b57 100644 --- a/src/test/java/org/semux/gui/panel/SendPanelTest.java +++ b/src/test/java/org/semux/gui/panel/SendPanelTest.java @@ -90,7 +90,7 @@ public void testSendSuccessfully() { assertEquals(TransactionType.TRANSFER, tx.getType()); assertArrayEquals(recipient.toAddress(), tx.getTo()); assertEquals(SEM.of(100), tx.getValue()); - assertEquals(kernelMock.getConfig().minTransactionFee(), tx.getFee()); + assertEquals(kernelMock.getConfig().spec().minTransactionFee(), tx.getFee()); } @Test diff --git a/src/test/java/org/semux/integration/SyncingTest.java b/src/test/java/org/semux/integration/SyncingTest.java index c472a4ece..720fc0f0c 100644 --- a/src/test/java/org/semux/integration/SyncingTest.java +++ b/src/test/java/org/semux/integration/SyncingTest.java @@ -7,7 +7,6 @@ package org.semux.integration; import static java.util.concurrent.TimeUnit.SECONDS; - import static org.awaitility.Awaitility.await; import static org.junit.Assert.assertTrue; import static org.semux.core.Amount.Unit.SEM; diff --git a/src/test/java/org/semux/integration/TransactTest.java b/src/test/java/org/semux/integration/TransactTest.java index a9a4fa3a9..4d78a32e1 100644 --- a/src/test/java/org/semux/integration/TransactTest.java +++ b/src/test/java/org/semux/integration/TransactTest.java @@ -7,7 +7,6 @@ package org.semux.integration; import static java.util.concurrent.TimeUnit.SECONDS; - import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; import static org.hamcrest.Matchers.equalTo; @@ -147,7 +146,7 @@ public void tearDown() { @Test public void testTransfer() throws IOException { final Amount value = SEM.of(1000); - final Amount fee = kernelPremine.getConfig().minTransactionFee(); + final Amount fee = kernelPremine.getConfig().spec().minTransactionFee(); // prepare transaction HashMap params = new HashMap<>(); @@ -185,7 +184,7 @@ TransactionType.TRANSFER, coinbaseOf(kernelPremine), coinbaseOf(kernelReceiver), @Test public void testDelegate() throws IOException { - final Amount fee = kernelPremine.getConfig().minTransactionFee(); + final Amount fee = kernelPremine.getConfig().spec().minTransactionFee(); // prepare transaction HashMap params = new HashMap<>(); @@ -203,12 +202,12 @@ public void testDelegate() throws IOException { // wait for transaction processing logger.info("Waiting for the transaction to be processed..."); await().atMost(20, SECONDS).until(availableOf(kernelPremine, coinbaseOf(kernelPremine)), - equalTo(sub(PREMINE, sum(kernelPremine.getConfig().minDelegateBurnAmount(), fee)))); + equalTo(sub(PREMINE, sum(kernelPremine.getConfig().spec().minDelegateBurnAmount(), fee)))); // assert that the transaction has been recorded across nodes assertLatestTransaction(kernelPremine, coinbaseOf(kernelPremine), TransactionType.DELEGATE, coinbaseOf(kernelPremine), Bytes.EMPTY_ADDRESS, - kernelPremine.getConfig().minDelegateBurnAmount(), fee, Bytes.of("test")); + kernelPremine.getConfig().spec().minDelegateBurnAmount(), fee, Bytes.of("test")); // assert that the number of votes has been recorded into delegate state assertDelegate(kernelPremine, kernelPremine.getCoinbase().toAddress(), ZERO); @@ -216,7 +215,7 @@ TransactionType.DELEGATE, coinbaseOf(kernelPremine), Bytes.EMPTY_ADDRESS, @Test public void testVote() throws IOException { - final Amount fee = kernelPremine.getConfig().minTransactionFee(); + final Amount fee = kernelPremine.getConfig().spec().minTransactionFee(); final Amount votes = SEM.of(100); final Amount votesWithFee = sum(votes, fee); diff --git a/src/test/java/org/semux/util/IOUtilTest.java b/src/test/java/org/semux/util/IOUtilTest.java index 5dfb8bff1..98d8890e2 100644 --- a/src/test/java/org/semux/util/IOUtilTest.java +++ b/src/test/java/org/semux/util/IOUtilTest.java @@ -7,7 +7,6 @@ package org.semux.util; import static java.nio.charset.StandardCharsets.UTF_8; - import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertEquals; From c9d67fa34492c419508baf66bee644ab94e9afd1 Mon Sep 17 00:00:00 2001 From: semux Date: Tue, 2 Jul 2019 18:03:25 +0100 Subject: [PATCH 03/11] Config: rename properties --- config/semux.properties | 6 +++--- src/main/java/org/semux/config/AbstractConfig.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config/semux.properties b/config/semux.properties index 2b58fb506..c2ab2b8d8 100644 --- a/config/semux.properties +++ b/config/semux.properties @@ -81,10 +81,10 @@ ui.fractionDigits = 9 #================ # Set the maximum gas this client can process in one block proposal -vm.blockGasLimit = 10000000 +txpool.blockGasLimit = 10000000 # The minimum price this client will accept for gas -vm.minGasPrice = 1 +txpool.minGasPrice = 1 # The max transaction time drift in milliseconds -pool.maxTransactionTimeDrift = 7300000 \ No newline at end of file +txpool.maxTransactionTimeDrift = 7200000 \ No newline at end of file diff --git a/src/main/java/org/semux/config/AbstractConfig.java b/src/main/java/org/semux/config/AbstractConfig.java index 30111f38d..c7fef4f6b 100644 --- a/src/main/java/org/semux/config/AbstractConfig.java +++ b/src/main/java/org/semux/config/AbstractConfig.java @@ -619,15 +619,15 @@ protected void init() { uiFractionDigits = Integer.parseInt(props.getProperty(name).trim()); break; } - case "pool.blockGasLimit": { + case "txpool.blockGasLimit": { poolBlockGasLimit = Integer.parseInt(props.getProperty(name).trim()); break; } - case "pool.minGasPrice": { + case "txpool.minGasPrice": { poolMinGasPrice = Integer.parseInt(props.getProperty(name).trim()); break; } - case "pool.maxTransactionTimeDrift": { + case "txpool.maxTransactionTimeDrift": { poolMaxTransactionTimeDrift = Integer.parseInt(props.getProperty(name).trim()); break; } From 05f2cac16d62ca19a049b2cbdc74e630896472da Mon Sep 17 00:00:00 2001 From: semux Date: Tue, 2 Jul 2019 19:56:30 +0100 Subject: [PATCH 04/11] Tests: fix unit tests --- .../java/org/semux/gui/model/WalletModelTest.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/test/java/org/semux/gui/model/WalletModelTest.java b/src/test/java/org/semux/gui/model/WalletModelTest.java index 571b8eff2..c2a08e0ba 100644 --- a/src/test/java/org/semux/gui/model/WalletModelTest.java +++ b/src/test/java/org/semux/gui/model/WalletModelTest.java @@ -13,9 +13,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -24,7 +21,6 @@ import static org.semux.core.Amount.ZERO; import java.awt.event.ActionListener; -import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -37,7 +33,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; -import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.mockito.stubbing.Answer; @@ -51,13 +46,13 @@ @RunWith(MockitoJUnitRunner.class) public class WalletModelTest { - @Mock private MainnetConfig config; private WalletModel model; @Before - public void setUp() throws IOException { + public void setUp() { + config = spy(new MainnetConfig("data")); model = spy(new WalletModel(config)); } @@ -151,7 +146,6 @@ public void testTotalLocked() { @Test public void testGetPrimaryValidatorDelegate() { - when(config.spec().getPrimaryValidator(any(), anyLong(), anyInt(), anyBoolean())).thenCallRealMethod(); model = new WalletModel(config); List delegates = Arrays.asList( new WalletDelegate(new Delegate(new Key().toAddress(), "delegate1".getBytes(), 0, Amount.ZERO)), @@ -170,7 +164,6 @@ public void testGetPrimaryValidatorDelegate() { @Test public void testGetNextPrimaryValidatorDelegate() { - when(config.spec().getValidatorUpdateInterval()).thenCallRealMethod(); model = new WalletModel(config); List delegates = Arrays.asList( new WalletDelegate(new Delegate(new Key().toAddress(), "delegate1".getBytes(), 0, Amount.ZERO)), @@ -202,7 +195,6 @@ public void testGetNextPrimaryValidatorDelegate() { @Test public void testGetNextValidatorSetUpdate() { - when(config.spec().getValidatorUpdateInterval()).thenCallRealMethod(); model = new WalletModel(config); Map testCases = new HashMap<>(); From 00edcf7e909f2444d9bc6696dc8d6b0974f297fe Mon Sep 17 00:00:00 2001 From: semux Date: Tue, 2 Jul 2019 20:03:01 +0100 Subject: [PATCH 05/11] Spec: increase transaction data size limit for CREATE and CALL --- src/main/java/org/semux/config/AbstractConfig.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/semux/config/AbstractConfig.java b/src/main/java/org/semux/config/AbstractConfig.java index c7fef4f6b..93c4e214a 100644 --- a/src/main/java/org/semux/config/AbstractConfig.java +++ b/src/main/java/org/semux/config/AbstractConfig.java @@ -165,6 +165,8 @@ public int maxBlockTransactionsSize() { public int maxTransactionDataSize(TransactionType type) { switch (type) { case COINBASE: + case UNVOTE: + case VOTE: return 0; // not required case TRANSFER: @@ -173,13 +175,9 @@ public int maxTransactionDataSize(TransactionType type) { case DELEGATE: return 16; // for name - case UNVOTE: - case VOTE: - return 0; // not required - case CREATE: case CALL: - return 64 * 1024; // for dapps + return 512 * 1024; // for dapps default: throw new UnreachableException(); From fc15db9ffe32589f909969576b7c6288a469f365 Mon Sep 17 00:00:00 2001 From: semux Date: Tue, 2 Jul 2019 20:16:17 +0100 Subject: [PATCH 06/11] Core: fix gas and gasPrice range --- .../java/org/semux/core/PendingManager.java | 2 ++ .../org/semux/core/TransactionExecutor.java | 23 ++++++++----------- .../org/semux/core/TransactionResult.java | 7 +----- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/semux/core/PendingManager.java b/src/main/java/org/semux/core/PendingManager.java index f8815e115..558360e97 100644 --- a/src/main/java/org/semux/core/PendingManager.java +++ b/src/main/java/org/semux/core/PendingManager.java @@ -340,6 +340,8 @@ protected ProcessingResult processTransaction(Transaction tx, boolean relay) { // delayed for the next event loop of PendingManager. while (tx != null && tx.getNonce() == getNonce(tx.getFrom())) { + // TODO: introduce block state (open, closed, signed, imported) + // create a dummy block (Note: VM transaction results may depends on the block) Blockchain chain = kernel.getBlockchain(); Block prevBlock = chain.getLatestBlock(); diff --git a/src/main/java/org/semux/core/TransactionExecutor.java b/src/main/java/org/semux/core/TransactionExecutor.java index 18967eed5..ca8055445 100644 --- a/src/main/java/org/semux/core/TransactionExecutor.java +++ b/src/main/java/org/semux/core/TransactionExecutor.java @@ -122,7 +122,11 @@ public List execute(List txs, AccountState as, D // check fee (call and create use gas instead) if (isVmCall) { - if (fee.lt(Amount.ZERO)) { + // applying a very strict check to avoid mistakes + boolean valid = fee.equals(Amount.ZERO) + && tx.getGas() >= 21_000 && tx.getGas() <= config.spec().maxBlockGasLimit() + && tx.getGasPrice() >= 1 && tx.getGasPrice() <= Integer.MAX_VALUE; // a theoretical limit + if (!valid) { result.setCode(Code.INVALID_FEE); continue; } @@ -205,7 +209,6 @@ public List execute(List txs, AccountState as, D } break; } - case CALL: case CREATE: // Note: the second parameter should be height = block number + 1; here we're @@ -215,9 +218,8 @@ public List execute(List txs, AccountState as, D break; } - // FIXME: overflow + // no overflow shall occur long maxGasFee = tx.getGas() * tx.getGasPrice(); - Amount maxCost = sum(sum(value, fee), Unit.NANO_SEM.of(maxGasFee)); if (available.lt(maxCost)) { @@ -227,18 +229,11 @@ public List execute(List txs, AccountState as, D // VM calls can have fees/values set. as.adjustAvailable(from, neg(sum(value, fee))); - - if (tx.getGas() > config.spec().maxBlockGasLimit()) { - result.setCode(Code.INVALID_GAS); - } else { - executeVmTransaction(result, tx, as, block, gasUsedInBlock); - if (result.getCode().isAcceptable()) { - gasUsedInBlock += result.getGasUsed(); - } + executeVmTransaction(result, tx, as, block, gasUsedInBlock); + if (result.getCode().isAcceptable()) { + gasUsedInBlock += result.getGasUsed(); } - break; - default: // unsupported transaction type result.setCode(Code.INVALID_TYPE); diff --git a/src/main/java/org/semux/core/TransactionResult.java b/src/main/java/org/semux/core/TransactionResult.java index 5ae391317..7d0b71f17 100644 --- a/src/main/java/org/semux/core/TransactionResult.java +++ b/src/main/java/org/semux/core/TransactionResult.java @@ -64,15 +64,10 @@ public enum Code { INVALID_NONCE(0x24), /** - * The transaction fee doesn't meet the minimum. + * The transaction fee (or gas * gasPrice) doesn't meet the minimum. */ INVALID_FEE(0x25), - /** - * The specified gas amount is larger than any gas limit - */ - INVALID_GAS(0x26), - /** * The transaction data is invalid, typically too large. */ From 3f0d54278601bfa2aaef0711384b300010b03114 Mon Sep 17 00:00:00 2001 From: semux Date: Tue, 2 Jul 2019 20:45:53 +0100 Subject: [PATCH 07/11] Core: refine the block proposing logic --- .../java/org/semux/consensus/SemuxBft.java | 33 +++++++++---------- .../java/org/semux/core/PendingManager.java | 8 +++-- .../org/semux/core/PendingManagerTest.java | 4 +-- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/semux/consensus/SemuxBft.java b/src/main/java/org/semux/consensus/SemuxBft.java index ca9593330..a524b7f20 100644 --- a/src/main/java/org/semux/consensus/SemuxBft.java +++ b/src/main/java/org/semux/consensus/SemuxBft.java @@ -800,30 +800,29 @@ protected Block proposeBlock() { new byte[0], new byte[0], data); // only propose gas used up to configured block gas limit - SemuxBlock semuxBlock = new SemuxBlock(tempHeader, config.poolBlockGasLimit()); + long blockGasLimit = config.poolBlockGasLimit(); + SemuxBlock semuxBlock = new SemuxBlock(tempHeader, blockGasLimit); - long gasUsed = 0; + for (PendingManager.PendingTransaction pendingTx : pending) { + Transaction tx = pendingTx.transaction; + boolean isVMTransaction = tx.getType() == TransactionType.CALL || tx.getType() == TransactionType.CREATE; - for (PendingManager.PendingTransaction tx : pending) { - if (tx.transaction.getType() == TransactionType.CALL - || tx.transaction.getType() == TransactionType.CREATE) { - long pendingGasForBlock = tx.transaction.getGas() + gasUsed; + if (isVMTransaction) { + // transactions that exceed the remaining block gas limit are ignores + if (tx.getGasPrice() <= blockGasLimit) { + TransactionResult result = exec.execute(tx, as, ds, semuxBlock, chain); - if (tx.transaction.getGasPrice() >= config.poolMinGasPrice() - && pendingGasForBlock < config.poolBlockGasLimit()) { - TransactionResult result = exec.execute(tx.transaction, as, ds, semuxBlock, chain); - gasUsed += result.getGasUsed(); - - if (result.getCode().isAcceptable() && gasUsed < config.poolBlockGasLimit()) { + // only include transaction that's acceptable + if (result.getCode().isAcceptable()) { pendingResults.add(result); - pendingTxs.add(tx.transaction); - } else { - gasUsed -= result.getGasUsed(); + pendingTxs.add(tx); + + blockGasLimit -= result.getGasUsed(); } } } else { - pendingResults.add(tx.result); - pendingTxs.add(tx.transaction); + pendingResults.add(pendingTx.result); + pendingTxs.add(pendingTx.transaction); } } diff --git a/src/main/java/org/semux/core/PendingManager.java b/src/main/java/org/semux/core/PendingManager.java index 558360e97..9ccfa4ccb 100644 --- a/src/main/java/org/semux/core/PendingManager.java +++ b/src/main/java/org/semux/core/PendingManager.java @@ -309,12 +309,16 @@ protected ProcessingResult processTransaction(Transaction tx, boolean relay) { int cnt = 0; long now = TimeUtil.currentTimeMillis(); + boolean isVMTransaction = tx.getType() == TransactionType.CALL || tx.getType() == TransactionType.CREATE; // reject VM transactions that come in before fork - if (!kernel.getBlockchain().isForkActivated(Fork.VIRTUAL_MACHINE) - && (tx.getType() == TransactionType.CALL || tx.getType() == TransactionType.CREATE)) { + if (isVMTransaction && !kernel.getBlockchain().isForkActivated(Fork.VIRTUAL_MACHINE)) { return new ProcessingResult(0, TransactionResult.Code.INVALID_TYPE); } + // reject VM transaction with low gas price + if (isVMTransaction && tx.getGasPrice() < kernel.getConfig().poolMinGasPrice()) { + return new ProcessingResult(0, TransactionResult.Code.INVALID_FEE); + } // reject transactions with a duplicated tx hash if (kernel.getBlockchain().hasTransaction(tx.getHash())) { diff --git a/src/test/java/org/semux/core/PendingManagerTest.java b/src/test/java/org/semux/core/PendingManagerTest.java index 54ab7230a..33ff2d994 100644 --- a/src/test/java/org/semux/core/PendingManagerTest.java +++ b/src/test/java/org/semux/core/PendingManagerTest.java @@ -6,6 +6,7 @@ */ package org.semux.core; +import static org.awaitility.Awaitility.await; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -208,8 +209,7 @@ public void testHighVolumeTransaction() throws InterruptedException { pendingMgr.addTransaction(tx); } - Thread.sleep(8000); - assertEquals(perm.length, pendingMgr.getPendingTransactions().size()); + await().until(() -> pendingMgr.getPendingTransactions().size() == perm.length); } @Test From 4366710f8b65f33ba39b46c25b8c99446dccc5df Mon Sep 17 00:00:00 2001 From: semux Date: Tue, 2 Jul 2019 20:57:07 +0100 Subject: [PATCH 08/11] Core: assign a gas cost for non-VM transactions We current have two measures, size and gas, to limit transaction throughput. A comprise is reached in this commit. Eventually, we should consider remove the size limit. --- .../java/org/semux/config/AbstractConfig.java | 6 +++++ src/main/java/org/semux/config/ChainSpec.java | 7 ++++++ .../java/org/semux/consensus/SemuxBft.java | 8 +++++-- .../org/semux/core/TransactionExecutor.java | 22 +++++++++++-------- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/semux/config/AbstractConfig.java b/src/main/java/org/semux/config/AbstractConfig.java index 93c4e214a..ff26aa25d 100644 --- a/src/main/java/org/semux/config/AbstractConfig.java +++ b/src/main/java/org/semux/config/AbstractConfig.java @@ -52,6 +52,7 @@ public abstract class AbstractConfig implements Config, ChainSpec { protected int maxBlockTransactionsSize = 1024 * 1024; protected Amount minTransactionFee = MILLI_SEM.of(5); protected Amount minDelegateBurnAmount = SEM.of(1000); + protected long nonVMTransactionGasCost = 21_000L; // ========================= // General @@ -194,6 +195,11 @@ public Amount minDelegateBurnAmount() { return minDelegateBurnAmount; } + @Override + public long nonVMTransactionGasCost() { + return nonVMTransactionGasCost; + } + @Override public Amount getBlockReward(long number) { if (number <= 2_000_000L) { // ~2 years diff --git a/src/main/java/org/semux/config/ChainSpec.java b/src/main/java/org/semux/config/ChainSpec.java index ef4175a8f..1a4cfe223 100644 --- a/src/main/java/org/semux/config/ChainSpec.java +++ b/src/main/java/org/semux/config/ChainSpec.java @@ -53,6 +53,13 @@ public interface ChainSpec { */ Amount minDelegateBurnAmount(); + /** + * Returns the gas cost for non-VM transactions. + * + * @return + */ + long nonVMTransactionGasCost(); + /** * Returns the block reward for a specific block. * diff --git a/src/main/java/org/semux/consensus/SemuxBft.java b/src/main/java/org/semux/consensus/SemuxBft.java index a524b7f20..bddd2bfba 100644 --- a/src/main/java/org/semux/consensus/SemuxBft.java +++ b/src/main/java/org/semux/consensus/SemuxBft.java @@ -821,8 +821,12 @@ protected Block proposeBlock() { } } } else { - pendingResults.add(pendingTx.result); - pendingTxs.add(pendingTx.transaction); + if (config.spec().nonVMTransactionGasCost() <= blockGasLimit + && pendingTx.result.getCode().isAcceptable()) { + pendingResults.add(pendingTx.result); + pendingTxs.add(pendingTx.transaction); + blockGasLimit -= config.spec().nonVMTransactionGasCost(); + } } } diff --git a/src/main/java/org/semux/core/TransactionExecutor.java b/src/main/java/org/semux/core/TransactionExecutor.java index ca8055445..51efe88af 100644 --- a/src/main/java/org/semux/core/TransactionExecutor.java +++ b/src/main/java/org/semux/core/TransactionExecutor.java @@ -118,10 +118,10 @@ public List execute(List txs, AccountState as, D continue; } - boolean isVmCall = type == TransactionType.CREATE || type == TransactionType.CALL; + boolean isVMTransaction = type == TransactionType.CREATE || type == TransactionType.CALL; // check fee (call and create use gas instead) - if (isVmCall) { + if (isVMTransaction) { // applying a very strict check to avoid mistakes boolean valid = fee.equals(Amount.ZERO) && tx.getGas() >= 21_000 && tx.getGas() <= config.spec().maxBlockGasLimit() @@ -230,9 +230,6 @@ public List execute(List txs, AccountState as, D // VM calls can have fees/values set. as.adjustAvailable(from, neg(sum(value, fee))); executeVmTransaction(result, tx, as, block, gasUsedInBlock); - if (result.getCode().isAcceptable()) { - gasUsedInBlock += result.getGasUsed(); - } break; default: // unsupported transaction type @@ -240,10 +237,17 @@ public List execute(List txs, AccountState as, D break; } - // increase nonce if success - // creates and calls increase their own nonces internal to VM - if (result.getCode().isAcceptable() && !isVmCall) { - as.increaseNonce(from); + if (result.getCode().isAcceptable()) { + if (!isVMTransaction) { + // CREATEs and CALLs manages the nonce inside the VM + as.increaseNonce(from); + } + + if (isVMTransaction) { + gasUsedInBlock += result.getGasUsed(); + } else { + gasUsedInBlock += config.spec().nonVMTransactionGasCost(); + } } result.setBlockNumber(block.getNumber()); From 163bef7d6bff1106bda86c4aa6ffb885c427d8c2 Mon Sep 17 00:00:00 2001 From: semux Date: Tue, 2 Jul 2019 21:05:18 +0100 Subject: [PATCH 09/11] Core: fix a bug --- src/main/java/org/semux/consensus/SemuxBft.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/semux/consensus/SemuxBft.java b/src/main/java/org/semux/consensus/SemuxBft.java index bddd2bfba..5fa7e442d 100644 --- a/src/main/java/org/semux/consensus/SemuxBft.java +++ b/src/main/java/org/semux/consensus/SemuxBft.java @@ -800,16 +800,16 @@ protected Block proposeBlock() { new byte[0], new byte[0], data); // only propose gas used up to configured block gas limit - long blockGasLimit = config.poolBlockGasLimit(); - SemuxBlock semuxBlock = new SemuxBlock(tempHeader, blockGasLimit); + long remainingBlockGas = config.poolBlockGasLimit(); + SemuxBlock semuxBlock = new SemuxBlock(tempHeader, config.spec().maxBlockGasLimit()); for (PendingManager.PendingTransaction pendingTx : pending) { Transaction tx = pendingTx.transaction; boolean isVMTransaction = tx.getType() == TransactionType.CALL || tx.getType() == TransactionType.CREATE; if (isVMTransaction) { - // transactions that exceed the remaining block gas limit are ignores - if (tx.getGasPrice() <= blockGasLimit) { + // transactions that exceed the remaining block gas limit are ignored + if (tx.getGasPrice() <= remainingBlockGas) { TransactionResult result = exec.execute(tx, as, ds, semuxBlock, chain); // only include transaction that's acceptable @@ -817,15 +817,15 @@ protected Block proposeBlock() { pendingResults.add(result); pendingTxs.add(tx); - blockGasLimit -= result.getGasUsed(); + remainingBlockGas -= result.getGasUsed(); } } } else { - if (config.spec().nonVMTransactionGasCost() <= blockGasLimit + if (config.spec().nonVMTransactionGasCost() <= remainingBlockGas && pendingTx.result.getCode().isAcceptable()) { pendingResults.add(pendingTx.result); pendingTxs.add(pendingTx.transaction); - blockGasLimit -= config.spec().nonVMTransactionGasCost(); + remainingBlockGas -= config.spec().nonVMTransactionGasCost(); } } } From 64cd97d427785c3baf3592ddec803e97ea8a31c1 Mon Sep 17 00:00:00 2001 From: semux Date: Tue, 2 Jul 2019 21:19:36 +0100 Subject: [PATCH 10/11] VM: add unit conversion between SEM and ETH --- .../java/org/semux/vm/client/Conversion.java | 33 +++++++++++++++++++ .../org/semux/vm/client/SemuxRepository.java | 3 +- .../org/semux/vm/client/SemuxTransaction.java | 6 ++-- 3 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/semux/vm/client/Conversion.java diff --git a/src/main/java/org/semux/vm/client/Conversion.java b/src/main/java/org/semux/vm/client/Conversion.java new file mode 100644 index 000000000..b2f8d2885 --- /dev/null +++ b/src/main/java/org/semux/vm/client/Conversion.java @@ -0,0 +1,33 @@ +/** + * 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.math.BigInteger; + +import org.semux.core.Amount; + +/** + * Conversion between ETH and SEM. The idea is to make 1 SEM = 1 ETH from a + * smart contract viewpoint. + */ +public class Conversion { + + private static final BigInteger TEN_POW_NINE = BigInteger.TEN.pow(9); + + public static Amount weiToAmount(BigInteger value) { + BigInteger nanoSEM = value.divide(TEN_POW_NINE); + return Amount.Unit.NANO_SEM.of(nanoSEM.longValue()); + } + + public static BigInteger amountToWei(Amount value) { + return value.getBigInteger().multiply(TEN_POW_NINE); + } + + public static BigInteger amountToWei(long nanoSEM) { + return BigInteger.valueOf(nanoSEM).multiply(TEN_POW_NINE); + } +} diff --git a/src/main/java/org/semux/vm/client/SemuxRepository.java b/src/main/java/org/semux/vm/client/SemuxRepository.java index 9d57bbdcb..dff371d46 100644 --- a/src/main/java/org/semux/vm/client/SemuxRepository.java +++ b/src/main/java/org/semux/vm/client/SemuxRepository.java @@ -11,7 +11,6 @@ import org.ethereum.vm.DataWord; import org.ethereum.vm.chainspec.PrecompiledContractContext; import org.ethereum.vm.client.Repository; -import org.semux.core.Amount; import org.semux.core.state.AccountState; /** @@ -100,7 +99,7 @@ public BigInteger getBalance(byte[] address) { @Override public BigInteger addBalance(byte[] address, BigInteger value) { - accountState.adjustAvailable(address, Amount.Unit.NANO_SEM.of(value.longValue())); + accountState.adjustAvailable(address, Conversion.weiToAmount(value)); return value; } diff --git a/src/main/java/org/semux/vm/client/SemuxTransaction.java b/src/main/java/org/semux/vm/client/SemuxTransaction.java index 893895768..a32e34ae9 100644 --- a/src/main/java/org/semux/vm/client/SemuxTransaction.java +++ b/src/main/java/org/semux/vm/client/SemuxTransaction.java @@ -6,6 +6,8 @@ */ package org.semux.vm.client; +import static org.semux.vm.client.Conversion.amountToWei; + import java.math.BigInteger; import org.ethereum.vm.client.Transaction; @@ -44,7 +46,7 @@ public long getNonce() { @Override public BigInteger getValue() { - return transaction.getValue().getBigInteger(); + return amountToWei(transaction.getValue()); } @Override @@ -59,6 +61,6 @@ public long getGas() { @Override public BigInteger getGasPrice() { - return BigInteger.valueOf(transaction.getGasPrice()); + return amountToWei(transaction.getGasPrice()); } } From 01685ade76970cface181fde14dcb9d8b368c0bc Mon Sep 17 00:00:00 2001 From: semux Date: Tue, 2 Jul 2019 23:29:50 +0100 Subject: [PATCH 11/11] Tests: fix unit tests --- src/main/java/org/semux/vm/client/SemuxRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/semux/vm/client/SemuxRepository.java b/src/main/java/org/semux/vm/client/SemuxRepository.java index dff371d46..9555507a7 100644 --- a/src/main/java/org/semux/vm/client/SemuxRepository.java +++ b/src/main/java/org/semux/vm/client/SemuxRepository.java @@ -94,7 +94,7 @@ public DataWord getStorageRow(byte[] address, DataWord key) { @Override public BigInteger getBalance(byte[] address) { - return accountState.getAccount(address).getAvailable().getBigInteger(); + return Conversion.amountToWei(accountState.getAccount(address).getAvailable()); } @Override