Merge pull request #25 from nicksavers/master
Add failing Block calc tests and update Denomination enum
This commit is contained in:
commit
90e7ab6a33
|
@ -22,7 +22,7 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class Block {
|
public class Block {
|
||||||
|
|
||||||
/* A scalar longValue equal to the mininum limit of gas expenditure per block */
|
/* A scalar value equal to the mininum limit of gas expenditure per block */
|
||||||
private static long MIN_GAS_LIMIT = BigInteger.valueOf(10).pow(4).longValue();
|
private static long MIN_GAS_LIMIT = BigInteger.valueOf(10).pow(4).longValue();
|
||||||
|
|
||||||
private BlockHeader header;
|
private BlockHeader header;
|
||||||
|
@ -38,7 +38,6 @@ public class Block {
|
||||||
|
|
||||||
private byte[] rlpEncoded;
|
private byte[] rlpEncoded;
|
||||||
private boolean parsed = false;
|
private boolean parsed = false;
|
||||||
private byte[] hash;
|
|
||||||
|
|
||||||
private Trie txsState;
|
private Trie txsState;
|
||||||
|
|
||||||
|
@ -64,9 +63,6 @@ public class Block {
|
||||||
this.parsed = true;
|
this.parsed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [parent_hash, uncles_hash, coinbase, state_root, tx_trie_root,
|
|
||||||
// difficulty, number, minGasPrice, gasLimit, gasUsed, timestamp,
|
|
||||||
// extradata, nonce]
|
|
||||||
private void parseRLP() {
|
private void parseRLP() {
|
||||||
|
|
||||||
RLPList params = (RLPList) RLP.decode2(rlpEncoded);
|
RLPList params = (RLPList) RLP.decode2(rlpEncoded);
|
||||||
|
@ -87,7 +83,6 @@ public class Block {
|
||||||
this.uncleList.add(blockData);
|
this.uncleList.add(blockData);
|
||||||
}
|
}
|
||||||
this.parsed = true;
|
this.parsed = true;
|
||||||
this.hash = this.getHash();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getHash(){
|
public byte[] getHash(){
|
||||||
|
@ -145,6 +140,10 @@ public class Block {
|
||||||
return this.header.getMinGasPrice();
|
return this.header.getMinGasPrice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isGenesis() {
|
||||||
|
return this.header.getNumber() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
public long getGasLimit() {
|
public long getGasLimit() {
|
||||||
if (!parsed) parseRLP();
|
if (!parsed) parseRLP();
|
||||||
return this.header.getGasLimit();
|
return this.header.getGasLimit();
|
||||||
|
@ -204,7 +203,7 @@ public class Block {
|
||||||
|
|
||||||
toStringBuff.setLength(0);
|
toStringBuff.setLength(0);
|
||||||
toStringBuff.append("BlockData [\n");
|
toStringBuff.append("BlockData [\n");
|
||||||
toStringBuff.append(" hash=" + ByteUtil.toHexString(hash)).append("\n");
|
toStringBuff.append(" hash=" + ByteUtil.toHexString(this.getHash())).append("\n");
|
||||||
toStringBuff.append(header.toString());
|
toStringBuff.append(header.toString());
|
||||||
|
|
||||||
for (TransactionReceipt txReceipt : getTxReceiptList()) {
|
for (TransactionReceipt txReceipt : getTxReceiptList()) {
|
||||||
|
@ -221,7 +220,7 @@ public class Block {
|
||||||
|
|
||||||
toStringBuff.setLength(0);
|
toStringBuff.setLength(0);
|
||||||
toStringBuff.append("BlockData [");
|
toStringBuff.append("BlockData [");
|
||||||
toStringBuff.append(" hash=" + ByteUtil.toHexString(hash)).append("");
|
toStringBuff.append(" hash=" + ByteUtil.toHexString(this.getHash())).append("");
|
||||||
toStringBuff.append(header.toFlatString());
|
toStringBuff.append(header.toFlatString());
|
||||||
|
|
||||||
for (Transaction tx : getTransactionsList()){
|
for (Transaction tx : getTransactionsList()){
|
||||||
|
@ -289,36 +288,40 @@ public class Block {
|
||||||
* likely next period. Conversely, if the period is too large, the difficulty,
|
* likely next period. Conversely, if the period is too large, the difficulty,
|
||||||
* and expected time to the next block, is reduced.
|
* and expected time to the next block, is reduced.
|
||||||
*/
|
*/
|
||||||
private boolean isValid() {
|
public boolean isValid() {
|
||||||
boolean isValid = false;
|
boolean isValid = true;
|
||||||
|
|
||||||
// verify difficulty meets requirements
|
// verify difficulty meets requirements
|
||||||
isValid = this.getDifficulty() == this.calcDifficulty();
|
//isValid = this.getDifficulty() == this.calcDifficulty();
|
||||||
// verify gasLimit meets requirements
|
// verify gasLimit meets requirements
|
||||||
isValid = this.getGasLimit() == this.calcGasLimit();
|
//isValid = this.getGasLimit() == this.calcGasLimit();
|
||||||
// verify timestamp meets requirements
|
// verify timestamp meets requirements
|
||||||
isValid = this.getTimestamp() > this.getParent().getTimestamp();
|
//isValid = this.getTimestamp() > this.getParent().getTimestamp();
|
||||||
|
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate GasLimit
|
* Calculate GasLimit
|
||||||
* max(10000, (parent gas limit * (1024 - 1) + (parent gas used * 6 / 5)) / 1024)
|
* See Yellow Paper: http://www.gavwood.com/Paper.pdf - page 5, 4.3.4 (25)
|
||||||
*
|
* @return long value of the gasLimit
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public long calcGasLimit() {
|
public long calcGasLimit() {
|
||||||
if (this.header.getParentHash() == null)
|
if (this.isGenesis())
|
||||||
return 1000000L;
|
return Genesis.GAS_LIMIT;
|
||||||
else {
|
else {
|
||||||
Block parent = this.getParent();
|
Block parent = this.getParent();
|
||||||
return Math.max(MIN_GAS_LIMIT, (parent.header.getGasLimit() * (1024 - 1) + (parent.header.getGasUsed() * 6 / 5)) / 1024);
|
return Math.max(MIN_GAS_LIMIT, (parent.header.getGasLimit() * (1024 - 1) + (parent.header.getGasUsed() * 6 / 5)) / 1024);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate Difficulty
|
||||||
|
* See Yellow Paper: http://www.gavwood.com/Paper.pdf - page 5, 4.3.4 (24)
|
||||||
|
* @return byte array value of the difficulty
|
||||||
|
*/
|
||||||
public byte[] calcDifficulty() {
|
public byte[] calcDifficulty() {
|
||||||
if (this.header.getParentHash() == null)
|
if (this.isGenesis())
|
||||||
return Genesis.DIFFICULTY;
|
return Genesis.DIFFICULTY;
|
||||||
else {
|
else {
|
||||||
Block parent = this.getParent();
|
Block parent = this.getParent();
|
||||||
|
|
|
@ -20,19 +20,20 @@ public class Blockchain extends ArrayList<Block> {
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(Blockchain.class);
|
private static Logger logger = LoggerFactory.getLogger(Blockchain.class);
|
||||||
|
|
||||||
|
// to avoid using minGasPrice=0 from Genesis for the wallet
|
||||||
|
private static long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue();
|
||||||
|
|
||||||
private Database db;
|
private Database db;
|
||||||
private Wallet wallet;
|
private Wallet wallet;
|
||||||
|
|
||||||
private long gasPrice = 1000;
|
private long gasPrice = 1000;
|
||||||
private Block lastBlock;
|
private Block lastBlock;
|
||||||
|
|
||||||
|
|
||||||
// This map of transaction designed
|
// This map of transaction designed
|
||||||
// to approve the tx by external trusted peer
|
// to approve the tx by external trusted peer
|
||||||
private Map<String, WalletTransaction> walletTransactions =
|
private Map<String, WalletTransaction> walletTransactions =
|
||||||
Collections.synchronizedMap(new HashMap<String, WalletTransaction>());
|
Collections.synchronizedMap(new HashMap<String, WalletTransaction>());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Blockchain(Wallet wallet) {
|
public Blockchain(Wallet wallet) {
|
||||||
this.db = WorldManager.instance.chainDB;
|
this.db = WorldManager.instance.chainDB;
|
||||||
this.wallet = wallet;
|
this.wallet = wallet;
|
||||||
|
@ -83,27 +84,22 @@ public class Blockchain extends ArrayList<Block> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addBlock(Block block) {
|
private void addBlock(Block block) {
|
||||||
|
if(block.isValid()) {
|
||||||
this.wallet.processBlock(block);
|
this.wallet.processBlock(block);
|
||||||
|
|
||||||
// that is the genesis case , we don't want to rely
|
// that is the genesis case , we don't want to rely
|
||||||
// on this price will use default 10000000000000
|
// on this price will use default 10000000000000
|
||||||
// todo: refactor this longValue some constant defaults class 10000000000000L
|
// todo: refactor this longValue some constant defaults class 10000000000000L
|
||||||
this.gasPrice = (block.getMinGasPrice() == 0) ? 10 * SZABO.longValue() : block.getMinGasPrice();
|
this.gasPrice = block.isGenesis() ? INITIAL_MIN_GAS_PRICE : block.getMinGasPrice();
|
||||||
|
|
||||||
if(lastBlock == null || block.getNumber() > lastBlock.getNumber())
|
if(lastBlock == null || block.getNumber() > lastBlock.getNumber())
|
||||||
this.lastBlock = block;
|
this.lastBlock = block;
|
||||||
this.add(block);
|
this.add(block);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public long getGasPrice() {
|
public long getGasPrice() {
|
||||||
return gasPrice;
|
return gasPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* 1) the dialog put a pending transaction on the list
|
* 1) the dialog put a pending transaction on the list
|
||||||
* 2) the dialog send the transaction to a net
|
* 2) the dialog send the transaction to a net
|
||||||
|
|
|
@ -10,7 +10,9 @@ public enum Denomination {
|
||||||
SHANNON(newBigInt(9)),
|
SHANNON(newBigInt(9)),
|
||||||
SZABO(newBigInt(12)),
|
SZABO(newBigInt(12)),
|
||||||
FINNY(newBigInt(15)),
|
FINNY(newBigInt(15)),
|
||||||
ETHER(newBigInt(18));
|
ETHER(newBigInt(18)),
|
||||||
|
EINSTEIN(newBigInt(21)),
|
||||||
|
DOUGLAS(newBigInt(42));
|
||||||
|
|
||||||
private BigInteger amount;
|
private BigInteger amount;
|
||||||
|
|
||||||
|
@ -18,10 +20,13 @@ public enum Denomination {
|
||||||
this.amount = value;
|
this.amount = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigInteger getDenomination() {
|
public BigInteger value() {
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
public long longValue() {return getDenomination().longValue();}
|
|
||||||
|
public long longValue() {
|
||||||
|
return value().longValue();
|
||||||
|
}
|
||||||
|
|
||||||
private static BigInteger newBigInt(int value) {
|
private static BigInteger newBigInt(int value) {
|
||||||
return BigInteger.valueOf(10).pow(value);
|
return BigInteger.valueOf(10).pow(value);
|
||||||
|
|
|
@ -1,18 +1,36 @@
|
||||||
package org.ethereum.core;
|
package org.ethereum.core;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.ethereum.manager.WorldManager;
|
|
||||||
import org.ethereum.util.RLP;
|
import org.ethereum.util.RLP;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
/**
|
||||||
|
* The genesis block is the first block in the chain and has fixed values according to
|
||||||
|
* the protocol specification. The genesis block is 13 items, and is specified thus:
|
||||||
|
*
|
||||||
|
* ( zerohash_256 , SHA3 RLP () , zerohash_160 , stateRoot, 0, 2^22 , 0, 0, 1000000, 0, 0, 0, SHA3 (42) , (), () )
|
||||||
|
*
|
||||||
|
* - Where zerohash_256 refers to the parent hash, a 256-bit hash which is all zeroes;
|
||||||
|
* - zerohash_160 refers to the coinbase address, a 160-bit hash which is all zeroes;
|
||||||
|
* - 2^22 refers to the difficulty;
|
||||||
|
* - 0 refers to the timestamp (the Unix epoch);
|
||||||
|
* - the transaction trie root and extradata are both 0, being equivalent to the empty byte array.
|
||||||
|
* - The sequences of both uncles and transactions are empty and represented by ().
|
||||||
|
* - SHA3 (42) refers to the SHA3 hash of a byte array of length one whose first and only byte is of value 42.
|
||||||
|
* - SHA3 RLP () value refers to the hash of the uncle lists in RLP, both empty lists.
|
||||||
|
*
|
||||||
|
* See Yellow Paper: http://www.gavwood.com/Paper.pdf (Appendix I. Genesis Block)
|
||||||
|
*/
|
||||||
public class Genesis extends Block {
|
public class Genesis extends Block {
|
||||||
|
|
||||||
Logger logger = LoggerFactory.getLogger(this.getClass());
|
Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
// The proof-of-concept series include a development premine, making the state root hash
|
||||||
|
// some value stateRoot. The latest documentation should be consulted for the value of the state root.
|
||||||
private AccountState acct = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200));
|
private AccountState acct = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200));
|
||||||
private String[] premine = new String[] {
|
private String[] premine = new String[] {
|
||||||
"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // # (M)
|
"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // # (M)
|
||||||
|
@ -53,8 +71,6 @@ public class Genesis extends Block {
|
||||||
}
|
}
|
||||||
logger.info("Genesis-hash: " + Hex.toHexString(this.getHash()));
|
logger.info("Genesis-hash: " + Hex.toHexString(this.getHash()));
|
||||||
logger.info("Genesis-stateRoot: " + Hex.toHexString(this.getStateRoot()));
|
logger.info("Genesis-stateRoot: " + Hex.toHexString(this.getStateRoot()));
|
||||||
|
|
||||||
WorldManager.instance.chainDB.put(getParentHash(), getEncoded());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Block getInstance() {
|
public static Block getInstance() {
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package org.ethereum.vm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fundamental network cost unit. Paid for exclusively by Ether, which is converted
|
||||||
|
* freely to and from Gas as required. Gas does not exist outside of the internal Ethereum
|
||||||
|
* computation engine; its price is set by the Transaction and miners are free to
|
||||||
|
* ignore Transactions whose Gas price is too low.
|
||||||
|
*/
|
||||||
|
public class GasCost {
|
||||||
|
|
||||||
|
public static int STEP = 1;
|
||||||
|
public static int STOP = 0;
|
||||||
|
public static int SUICIDE = 0;
|
||||||
|
public static int SLOAD = 20;
|
||||||
|
public static int SHA3 = 20;
|
||||||
|
public static int SSTORE = 100;
|
||||||
|
public static int BALANCE = 20;
|
||||||
|
public static int CREATE = 100;
|
||||||
|
public static int CALL = 20;
|
||||||
|
public static int MEMORY = 1;
|
||||||
|
public static int TXDATA = 5;
|
||||||
|
public static int TRANSACTION = 500;
|
||||||
|
}
|
|
@ -1,41 +0,0 @@
|
||||||
package org.ethereum.vm;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* www.ethereumJ.com
|
|
||||||
* User: Roman Mandeleil
|
|
||||||
* Created on: 04/06/2014 23:58
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class GasLedger {
|
|
||||||
|
|
||||||
/* YP Appendix B.
|
|
||||||
Gstep 1 Default amount of gas to pay for execution cycle.
|
|
||||||
Gstop 0 Nothing paid for the STOP operation.
|
|
||||||
Gsuicide 0 Nothing paid for the SUICIDE operation.
|
|
||||||
Gsha3 20 Paid for a SHA3 operation.
|
|
||||||
Gsload 20 Paid for a SLOAD operation.
|
|
||||||
Gsstore 100 Paid for a normal SSTORE operation (doubled or waived sometimes).
|
|
||||||
Gbalance 20 Paid for a BALANCE operation.
|
|
||||||
Gcreate 100 Paid for a CREATE operation.
|
|
||||||
Gcall 20 Paid for a CALL operation.
|
|
||||||
Gmemory 1 Paid for every additional word when expanding memory.
|
|
||||||
Gtxdata 5 Paid for every byte of data or code for a transaction.
|
|
||||||
Gtransaction 500 Paid for every transaction.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
public static int G_STEP = 1;
|
|
||||||
public static int G_STOP = 0;
|
|
||||||
public static int G_SUICIDE = 0;
|
|
||||||
public static int G_SLOAD = 20;
|
|
||||||
public static int G_SHA3 = 20;
|
|
||||||
public static int G_SSTORE = 100;
|
|
||||||
public static int G_BALANCE = 20;
|
|
||||||
public static int G_CREATE = 100;
|
|
||||||
public static int G_CALL = 20;
|
|
||||||
public static int G_MEMORY = 1;
|
|
||||||
public static int G_TXDATA = 5;
|
|
||||||
public static int G_TRANSACTION = 500;
|
|
||||||
}
|
|
|
@ -34,23 +34,23 @@ public class VM {
|
||||||
|
|
||||||
switch (OpCode.code(op)) {
|
switch (OpCode.code(op)) {
|
||||||
case SHA3:
|
case SHA3:
|
||||||
program.spendGas( GasLedger.G_SHA3 );
|
program.spendGas(GasCost.SHA3);
|
||||||
break;
|
break;
|
||||||
case SLOAD:
|
case SLOAD:
|
||||||
program.spendGas( GasLedger.G_SLOAD );
|
program.spendGas(GasCost.SLOAD);
|
||||||
break;
|
break;
|
||||||
case SSTORE:
|
case SSTORE:
|
||||||
// todo: calc gas in the execution
|
// todo: calc gas in the execution
|
||||||
// todo: according to the size
|
// todo: according to the size
|
||||||
break;
|
break;
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
program.spendGas( GasLedger.G_BALANCE );
|
program.spendGas(GasCost.BALANCE);
|
||||||
break;
|
break;
|
||||||
case CREATE:
|
case CREATE:
|
||||||
program.spendGas( GasLedger.G_CREATE );
|
program.spendGas(GasCost.CREATE);
|
||||||
break;
|
break;
|
||||||
case CALL:
|
case CALL:
|
||||||
program.spendGas( GasLedger.G_CALL );
|
program.spendGas(GasCost.CALL);
|
||||||
break;
|
break;
|
||||||
case MSTORE8:
|
case MSTORE8:
|
||||||
case MSTORE:
|
case MSTORE:
|
||||||
|
@ -58,7 +58,7 @@ public class VM {
|
||||||
// todo: according to the size
|
// todo: according to the size
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
program.spendGas( GasLedger.G_STEP );
|
program.spendGas(GasCost.STEP);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,11 +472,11 @@ public class VM {
|
||||||
DataWord oldValue = program.storageLoad(addr);
|
DataWord oldValue = program.storageLoad(addr);
|
||||||
program.storageSave(addr, value);
|
program.storageSave(addr, value);
|
||||||
if (oldValue == null && !value.isZero()){
|
if (oldValue == null && !value.isZero()){
|
||||||
program.spendGas(GasLedger.G_SSTORE * 2);
|
program.spendGas(GasCost.SSTORE * 2);
|
||||||
} else if (oldValue != null && value.isZero()){
|
} else if (oldValue != null && value.isZero()){
|
||||||
program.spendGas(GasLedger.G_SSTORE * 0);
|
program.spendGas(GasCost.SSTORE * 0);
|
||||||
} else
|
} else
|
||||||
program.spendGas(GasLedger.G_SSTORE);
|
program.spendGas(GasCost.SSTORE);
|
||||||
|
|
||||||
program.step();
|
program.step();
|
||||||
}
|
}
|
||||||
|
@ -573,7 +573,7 @@ public class VM {
|
||||||
|
|
||||||
// memory gas calc
|
// memory gas calc
|
||||||
int newMemSize = program.getMemSize();
|
int newMemSize = program.getMemSize();
|
||||||
program.spendGas(GasLedger.G_MEMORY * (newMemSize - oldMemSize) /32);
|
program.spendGas(GasCost.MEMORY * (newMemSize - oldMemSize) /32);
|
||||||
}
|
}
|
||||||
program.fullTrace();
|
program.fullTrace();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package org.ethereum.core;
|
package org.ethereum.core;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.ethereum.net.message.BlocksMessage;
|
import org.ethereum.net.message.BlocksMessage;
|
||||||
import org.ethereum.net.message.StaticMessages;
|
import org.ethereum.net.message.StaticMessages;
|
||||||
import org.ethereum.util.RLPList;
|
import org.ethereum.util.RLPList;
|
||||||
|
@ -86,4 +88,21 @@ public class BlockTest {
|
||||||
BlocksMessage blockData = new BlocksMessage(rlpList);
|
BlocksMessage blockData = new BlocksMessage(rlpList);
|
||||||
System.out.println(blockData.toString());
|
System.out.println(blockData.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCalcDifficulty() {
|
||||||
|
Block genesis = Genesis.getInstance();
|
||||||
|
byte[] diffBytes = genesis.calcDifficulty();
|
||||||
|
BigInteger difficulty = new BigInteger(1, diffBytes);
|
||||||
|
System.out.println("Genesis difficulty = " + difficulty.toString());
|
||||||
|
fail("Yet to be implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCalcGasLimit() {
|
||||||
|
Block genesis = Genesis.getInstance();
|
||||||
|
long gasLimit = genesis.calcGasLimit();
|
||||||
|
System.out.println("Genesis gasLimit = " + gasLimit);
|
||||||
|
fail("Yet to be implemented.");
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue