Merge branch 'master' of https://github.com/romanman/ethereumj
This commit is contained in:
commit
991d9770cb
|
@ -19,13 +19,20 @@ public class SystemProperties {
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(SystemProperties.class);
|
private static Logger logger = LoggerFactory.getLogger(SystemProperties.class);
|
||||||
|
|
||||||
|
private static int DEFAULT_TX_APPROVE_TIMEOUT = 10;
|
||||||
|
private static String DEFAULT_DISCOVERY_PEER = "54.201.28.117";
|
||||||
|
private static int DEFAULT_DISCOVERY_PORT = 30303;
|
||||||
|
private static String DEFAULT_ACTIVE_PEER_IP = "54.201.28.117";
|
||||||
|
private static int DEFAULT_ACTIVE_PORT = 30303;
|
||||||
|
private static String DEFAULT_SAMPLES_DIR = "samples";
|
||||||
|
|
||||||
public static SystemProperties CONFIG = new SystemProperties();
|
public static SystemProperties CONFIG = new SystemProperties();
|
||||||
private Properties prop = new Properties();
|
private Properties prop = new Properties();
|
||||||
private InputStream input = null;
|
private InputStream input = null;
|
||||||
|
|
||||||
public SystemProperties() {
|
public SystemProperties() {
|
||||||
try {
|
|
||||||
|
try {
|
||||||
File file = null;
|
File file = null;
|
||||||
String dir = System.getProperty("user.dir");
|
String dir = System.getProperty("user.dir");
|
||||||
String fileName = dir + "/config/system.properties";
|
String fileName = dir + "/config/system.properties";
|
||||||
|
@ -41,7 +48,6 @@ public class SystemProperties {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//load a properties file from class path, inside static method
|
//load a properties file from class path, inside static method
|
||||||
prop.load(input);
|
prop.load(input);
|
||||||
|
|
||||||
|
@ -77,18 +83,17 @@ public class SystemProperties {
|
||||||
|
|
||||||
public int transactionApproveTimeout(){
|
public int transactionApproveTimeout(){
|
||||||
if (prop.isEmpty())
|
if (prop.isEmpty())
|
||||||
return 10;
|
return DEFAULT_TX_APPROVE_TIMEOUT;
|
||||||
return Integer.parseInt(prop.getProperty("transaction.approve.timeout"));
|
return Integer.parseInt(prop.getProperty("transaction.approve.timeout"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String peerDiscoveryIP(){
|
public String peerDiscoveryIP(){
|
||||||
if(prop.isEmpty()) return "54.201.28.117";
|
if(prop.isEmpty()) return DEFAULT_DISCOVERY_PEER;
|
||||||
return prop.getProperty("peer.discovery.ip");
|
return prop.getProperty("peer.discovery.ip");
|
||||||
}
|
}
|
||||||
|
|
||||||
public int peerDiscoveryPort(){
|
public int peerDiscoveryPort(){
|
||||||
if(prop.isEmpty()) return 30303;
|
if(prop.isEmpty()) return DEFAULT_DISCOVERY_PORT;
|
||||||
return Integer.parseInt(prop.getProperty("peer.discovery.port"));
|
return Integer.parseInt(prop.getProperty("peer.discovery.port"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,21 +103,21 @@ public class SystemProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String activePeerIP(){
|
public String activePeerIP(){
|
||||||
if(prop.isEmpty()) return "54.201.28.117";
|
if(prop.isEmpty()) return DEFAULT_ACTIVE_PEER_IP;
|
||||||
return prop.getProperty("peer.active.ip");
|
return prop.getProperty("peer.active.ip");
|
||||||
}
|
}
|
||||||
|
|
||||||
public int activePeerPort(){
|
public int activePeerPort(){
|
||||||
if(prop.isEmpty()) return 30303;
|
if(prop.isEmpty()) return DEFAULT_ACTIVE_PORT;
|
||||||
return Integer.parseInt(prop.getProperty("peer.active.port"));
|
return Integer.parseInt(prop.getProperty("peer.active.port"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String samplesDir(){
|
public String samplesDir(){
|
||||||
if(prop.isEmpty()) return "samples";
|
if(prop.isEmpty()) return DEFAULT_SAMPLES_DIR;
|
||||||
return prop.getProperty("samples.dir");
|
return prop.getProperty("samples.dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public void print() {
|
||||||
Enumeration<?> e = prop.propertyNames();
|
Enumeration<?> e = prop.propertyNames();
|
||||||
while (e.hasMoreElements()) {
|
while (e.hasMoreElements()) {
|
||||||
String key = (String) e.nextElement();
|
String key = (String) e.nextElement();
|
||||||
|
@ -120,11 +125,10 @@ public class SystemProperties {
|
||||||
if (!key.equals("null"))
|
if (!key.equals("null"))
|
||||||
logger.info("Key: " + key + ", Value: " + value);
|
logger.info("Key: " + key + ", Value: " + value);
|
||||||
}
|
}
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String args[]){
|
public static void main(String args[]){
|
||||||
SystemProperties systemProperties = new SystemProperties();
|
SystemProperties systemProperties = new SystemProperties();
|
||||||
logger.info(systemProperties.toString());
|
systemProperties.print();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ public class AccountState {
|
||||||
*
|
*
|
||||||
* Since I typically wish to refer not to the trie’s root hash
|
* Since I typically wish to refer not to the trie’s root hash
|
||||||
* but to the underlying set of key/value pairs stored within,
|
* but to the underlying set of key/value pairs stored within,
|
||||||
* I define a convenient equi valence TRIE (σ[a] s ) ≡ σ[a] s .
|
* I define a convenient equivalence TRIE (σ[a] s ) ≡ σ[a] s .
|
||||||
* It shall be understood that σ[a] s is not a ‘physical’ member
|
* It shall be understood that σ[a] s is not a ‘physical’ member
|
||||||
* of the account and does not contribute to its later serialisation */
|
* of the account and does not contribute to its later serialisation */
|
||||||
private byte[] stateRoot = new byte[0];
|
private byte[] stateRoot = new byte[0];
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.ethereum.core;
|
package org.ethereum.core;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -20,31 +19,22 @@ import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
public class Blockchain extends ArrayList<Block> {
|
public class Blockchain extends ArrayList<Block> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -143590724563460486L;
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(Blockchain.class);
|
private static Logger logger = LoggerFactory.getLogger(Blockchain.class);
|
||||||
|
|
||||||
private Database db;
|
private Database db;
|
||||||
private Wallet wallet;
|
private Wallet wallet;
|
||||||
private long gasPrice = 1000;
|
private long gasPrice = 1000;
|
||||||
private Block lastBlock = new Genesis();
|
private Block lastBlock;
|
||||||
|
|
||||||
private Map<BigInteger, PendingTransaction> pendingTransactions =
|
private Map<String, PendingTransaction> pendingTransactions =
|
||||||
Collections.synchronizedMap(new HashMap<BigInteger, PendingTransaction>());
|
Collections.synchronizedMap(new HashMap<String, PendingTransaction>());
|
||||||
|
|
||||||
public Blockchain(Wallet wallet) {
|
public Blockchain(Wallet wallet) {
|
||||||
this.db = Config.CHAIN_DB;
|
this.db = Config.CHAIN_DB;
|
||||||
this.wallet = wallet;
|
this.wallet = wallet;
|
||||||
|
this.loadChain();
|
||||||
// Redesign fetch all to get the chain ordered
|
|
||||||
byte[] payload = db.get(Genesis.PARENT_HASH);
|
|
||||||
|
|
||||||
while (payload != null) {
|
|
||||||
|
|
||||||
Block block = new Block(payload);
|
|
||||||
this.add(block);
|
|
||||||
lastBlock = block;
|
|
||||||
wallet.processBlock(block);
|
|
||||||
payload = db.get(block.getHash());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block getLastBlock() {
|
public Block getLastBlock() {
|
||||||
|
@ -55,59 +45,65 @@ public class Blockchain extends ArrayList<Block> {
|
||||||
|
|
||||||
// TODO: redesign this part when the state part and the genesis block is ready
|
// TODO: redesign this part when the state part and the genesis block is ready
|
||||||
|
|
||||||
if (blocks.isEmpty()) return;
|
if (blocks.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
Block firstBlockToAdd = blocks.get(blocks.size() - 1);
|
Block firstBlockToAdd = blocks.get(blocks.size() - 1);
|
||||||
|
|
||||||
// if it is the first block to add
|
// if it is the first block to add
|
||||||
// check that the parent is the genesis
|
// check that the parent is the genesis
|
||||||
if (this.isEmpty() &&
|
if (this.isEmpty()
|
||||||
!Arrays.equals(StaticMessages.GENESIS_HASH, firstBlockToAdd.getParentHash())){
|
&& !Arrays.equals(StaticMessages.GENESIS_HASH,
|
||||||
return;
|
firstBlockToAdd.getParentHash())) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
// if there is some blocks already keep chain continuity
|
// if there is some blocks already keep chain continuity
|
||||||
if (!this.isEmpty() ){
|
if (!this.isEmpty()) {
|
||||||
Block lastBlock = this.get(this.size() - 1);
|
Block lastBlock = this.get(this.size() - 1);
|
||||||
String hashLast = Hex.toHexString(lastBlock.getHash());
|
String hashLast = Hex.toHexString(lastBlock.getHash());
|
||||||
String blockParentHash = Hex.toHexString(firstBlockToAdd.getParentHash());
|
String blockParentHash = Hex.toHexString(firstBlockToAdd.getParentHash());
|
||||||
if (!hashLast.equals(blockParentHash)) return;
|
if (!hashLast.equals(blockParentHash)) return;
|
||||||
}
|
}
|
||||||
for (int i = blocks.size() - 1; i >= 0 ; --i){
|
for (int i = blocks.size() - 1; i >= 0 ; --i){
|
||||||
Block block = blocks.get(i);
|
Block block = blocks.get(i);
|
||||||
this.add(block);
|
this.addBlock(block);
|
||||||
if(block.getNumber() > lastBlock.getNumber()) lastBlock = block;
|
|
||||||
|
|
||||||
db.put(block.getParentHash(), block.getEncoded());
|
db.put(block.getParentHash(), block.getEncoded());
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
logger.debug("block added to the chain with hash: {}", Hex.toHexString(block.getHash()));
|
logger.debug("block added to the chain with hash: {}", Hex.toHexString(block.getHash()));
|
||||||
this.gasPrice = block.getMinGasPrice();
|
|
||||||
|
|
||||||
wallet.processBlock(block);
|
|
||||||
}
|
}
|
||||||
// Remove all pending transactions as they already approved by the net
|
// Remove all pending transactions as they already approved by the net
|
||||||
for (Block block : blocks){
|
for (Block block : blocks) {
|
||||||
for (Transaction tx : block.getTransactionsList()){
|
for (Transaction tx : block.getTransactionsList()) {
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash()));
|
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash()));
|
||||||
removePendingTransaction(tx);
|
removePendingTransaction(tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("*** Block chain size: [ {} ]", this.size());
|
logger.info("*** Block chain size: [ {} ]", this.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
private void addBlock(Block block) {
|
||||||
* 1) the dialog put a pending transaction on the list
|
this.wallet.processBlock(block);
|
||||||
* 2) the dialog send the transaction to a net
|
this.gasPrice = block.getMinGasPrice();
|
||||||
* 3) wherever the transaction got in from the wire it will change to approve state
|
if(lastBlock == null || block.getNumber() > lastBlock.getNumber())
|
||||||
* 4) only after the approve a) Wallet state changes
|
this.lastBlock = block;
|
||||||
* 5) After the block is received with that tx the pending been clean up
|
this.add(block);
|
||||||
*/
|
}
|
||||||
|
|
||||||
|
public long getGasPrice() {
|
||||||
|
return gasPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 1) the dialog put a pending transaction on the list
|
||||||
|
* 2) the dialog send the transaction to a net
|
||||||
|
* 3) wherever the transaction got in from the wire it will change to approve state
|
||||||
|
* 4) only after the approve a) Wallet state changes
|
||||||
|
* 5) After the block is received with that tx the pending been clean up
|
||||||
|
*/
|
||||||
public PendingTransaction addPendingTransaction(Transaction transaction) {
|
public PendingTransaction addPendingTransaction(Transaction transaction) {
|
||||||
|
String hash = Hex.toHexString(transaction.getHash());
|
||||||
BigInteger hash = new BigInteger(transaction.getHash());
|
logger.info("pending transaction placed hash: {} ", hash );
|
||||||
logger.info("pending transaction placed hash: {} ", hash.toString(16) );
|
|
||||||
|
|
||||||
PendingTransaction pendingTransaction = pendingTransactions.get(hash);
|
PendingTransaction pendingTransaction = pendingTransactions.get(hash);
|
||||||
if (pendingTransaction != null)
|
if (pendingTransaction != null)
|
||||||
|
@ -120,24 +116,44 @@ public class Blockchain extends ArrayList<Block> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removePendingTransaction(Transaction transaction){
|
public void removePendingTransaction(Transaction transaction){
|
||||||
|
String hash = Hex.toHexString(transaction.getHash());
|
||||||
BigInteger hash = new BigInteger(transaction.getHash());
|
logger.info("pending transaction removed with hash: {} ", hash );
|
||||||
logger.info("pending transaction removed with hash: {} ", hash.toString(16) );
|
|
||||||
pendingTransactions.remove(hash);
|
pendingTransactions.remove(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getGasPrice() {
|
|
||||||
return gasPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getLatestBlockHash(){
|
public byte[] getLatestBlockHash(){
|
||||||
|
if (this.isEmpty())
|
||||||
if (this.isEmpty())
|
return StaticMessages.GENESIS_HASH;
|
||||||
return StaticMessages.GENESIS_HASH;
|
else
|
||||||
else{
|
return lastBlock.getHash();
|
||||||
|
|
||||||
return lastBlock.getHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void loadChain() {
|
||||||
|
DBIterator iterator = db.iterator();
|
||||||
|
try {
|
||||||
|
if (!iterator.hasNext()) {
|
||||||
|
logger.info("DB is empty - adding Genesis");
|
||||||
|
Block genesis = Genesis.getInstance();
|
||||||
|
this.addBlock(genesis);
|
||||||
|
logger.debug("Block: " + genesis.getNumber() + " ---> " + genesis.toFlatString());
|
||||||
|
db.put(genesis.getParentHash(), genesis.getEncoded());
|
||||||
|
} else {
|
||||||
|
logger.debug("Displaying blocks stored in DB sorted on blocknumber");
|
||||||
|
byte[] parentHash = Genesis.PARENT_HASH; // get Genesis block by parentHash
|
||||||
|
for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) {
|
||||||
|
this.addBlock(new Block(db.get(parentHash)));
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
logger.debug("Block: " + lastBlock.getNumber() + " ---> " + lastBlock.toFlatString());
|
||||||
|
parentHash = lastBlock.getHash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
// Make sure you close the iterator to avoid resource leaks.
|
||||||
|
try {
|
||||||
|
iterator.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,10 @@ public class Genesis extends Block {
|
||||||
public static long TIMESTAMP = 0;
|
public static long TIMESTAMP = 0;
|
||||||
public static byte[] EXTRA_DATA = new byte[0];
|
public static byte[] EXTRA_DATA = new byte[0];
|
||||||
public static byte[] NONCE = HashUtil.sha3(new byte[]{42});
|
public static byte[] NONCE = HashUtil.sha3(new byte[]{42});
|
||||||
|
|
||||||
public Genesis() {
|
private static Block instance;
|
||||||
|
|
||||||
|
private Genesis() {
|
||||||
super(PARENT_HASH, UNCLES_HASH, COINBASE, TX_TRIE_ROOT, DIFFICULTY,
|
super(PARENT_HASH, UNCLES_HASH, COINBASE, TX_TRIE_ROOT, DIFFICULTY,
|
||||||
NUMBER, MIN_GAS_PRICE, GAS_LIMIT, GAS_USED, TIMESTAMP,
|
NUMBER, MIN_GAS_PRICE, GAS_LIMIT, GAS_USED, TIMESTAMP,
|
||||||
EXTRA_DATA, NONCE, null, null);
|
EXTRA_DATA, NONCE, null, null);
|
||||||
|
@ -53,9 +55,16 @@ public class Genesis extends Block {
|
||||||
this.updateState(Hex.decode("6c386a4b26f73c802f34673f7248bb118f97424a"), acct.getEncoded());
|
this.updateState(Hex.decode("6c386a4b26f73c802f34673f7248bb118f97424a"), acct.getEncoded());
|
||||||
// # (R)
|
// # (R)
|
||||||
this.updateState(Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826"), acct.getEncoded());
|
this.updateState(Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826"), acct.getEncoded());
|
||||||
System.out.println(Hex.toHexString(this.getStateRoot()));
|
|
||||||
logger.info("Genesis-hash: " + Hex.toHexString(this.getHash()));
|
logger.info("Genesis-hash: " + Hex.toHexString(this.getHash()));
|
||||||
|
logger.info("Genesis-stateRoot: " + Hex.toHexString(this.getStateRoot()));
|
||||||
|
|
||||||
Config.CHAIN_DB.put(getParentHash(), getEncoded());
|
Config.CHAIN_DB.put(getParentHash(), getEncoded());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Block getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new Genesis();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ public class StateObject {
|
||||||
// Converts an transaction in to a state object
|
// Converts an transaction in to a state object
|
||||||
public static StateObject createContract(Transaction tx, GoState state) {
|
public static StateObject createContract(Transaction tx, GoState state) {
|
||||||
// Create contract if there's no recipient
|
// Create contract if there's no recipient
|
||||||
if (tx.isContract()) {
|
if (tx.isContractCreation()) {
|
||||||
// FIXME
|
// FIXME
|
||||||
byte[] txHash = tx.getHash();
|
byte[] txHash = tx.getHash();
|
||||||
byte[] contractAddress = copyOfRange(txHash, 12, txHash.length);
|
byte[] contractAddress = copyOfRange(txHash, 12, txHash.length);
|
||||||
|
|
|
@ -164,14 +164,14 @@ public class Transaction {
|
||||||
|
|
||||||
public byte[] getContractAddress(){
|
public byte[] getContractAddress(){
|
||||||
|
|
||||||
if (!isContract()) return null;
|
if (!isContractCreation()) return null;
|
||||||
|
|
||||||
byte[] encSender = RLP.encodeElement(getSender());
|
byte[] encSender = RLP.encodeElement(getSender());
|
||||||
byte[] encNonce = RLP.encodeElement(nonce);
|
byte[] encNonce = RLP.encodeElement(nonce);
|
||||||
return HashUtil.sha3omit12(RLP.encodeList(encSender, encNonce));
|
return HashUtil.sha3omit12(RLP.encodeList(encSender, encNonce));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isContract() {
|
public boolean isContractCreation() {
|
||||||
return Arrays.equals(this.receiveAddress, ZERO_ADDRESS);
|
return Arrays.equals(this.receiveAddress, ZERO_ADDRESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ import org.spongycastle.util.encoders.Base64;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
public class ECKey implements Serializable {
|
public class ECKey implements Serializable {
|
||||||
private static final Logger log = LoggerFactory.getLogger(ECKey.class);
|
private static final Logger logger = LoggerFactory.getLogger(ECKey.class);
|
||||||
|
|
||||||
/** The parameters of the secp256k1 curve that Bitcoin uses. */
|
/** The parameters of the secp256k1 curve that Bitcoin uses. */
|
||||||
public static final ECDomainParameters CURVE;
|
public static final ECDomainParameters CURVE;
|
||||||
|
@ -448,11 +448,10 @@ public class ECKey implements Serializable {
|
||||||
signer.init(false, params);
|
signer.init(false, params);
|
||||||
try {
|
try {
|
||||||
return signer.verifySignature(data, signature.r, signature.s);
|
return signer.verifySignature(data, signature.r, signature.s);
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException npe) {
|
||||||
// Bouncy Castle contains a bug that can cause NPEs given specially crafted signatures. Those signatures
|
// Bouncy Castle contains a bug that can cause NPEs given specially crafted signatures.
|
||||||
// are inherently invalid/attack sigs so we just fail them here rather than crash the thread.
|
// Those signatures are inherently invalid/attack sigs so we just fail them here rather than crash the thread.
|
||||||
log.error("Caught NPE inside bouncy castle");
|
logger.error("Caught NPE inside bouncy castle", npe);
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,13 @@ import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.ethereum.config.SystemProperties;
|
import org.ethereum.config.SystemProperties;
|
||||||
import org.ethereum.core.Block;
|
|
||||||
import org.ethereum.core.Genesis;
|
|
||||||
import org.ethereum.net.message.StaticMessages;
|
|
||||||
import org.iq80.leveldb.DB;
|
import org.iq80.leveldb.DB;
|
||||||
import org.iq80.leveldb.DBIterator;
|
import org.iq80.leveldb.DBIterator;
|
||||||
import org.iq80.leveldb.Options;
|
import org.iq80.leveldb.Options;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic interface for Ethereum database
|
* Generic interface for Ethereum database
|
||||||
|
@ -47,8 +41,6 @@ public class Database {
|
||||||
logger.debug("Initializing new or existing DB: '" + name + "'");
|
logger.debug("Initializing new or existing DB: '" + name + "'");
|
||||||
options.createIfMissing(true);
|
options.createIfMissing(true);
|
||||||
db = factory.open(new File(name), options);
|
db = factory.open(new File(name), options);
|
||||||
|
|
||||||
printDB();
|
|
||||||
// logger.debug("Showing database stats");
|
// logger.debug("Showing database stats");
|
||||||
// String stats = DATABASE.getProperty("leveldb.stats");
|
// String stats = DATABASE.getProperty("leveldb.stats");
|
||||||
// logger.debug(stats);
|
// logger.debug(stats);
|
||||||
|
@ -68,34 +60,6 @@ public class Database {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void printDB() {
|
|
||||||
DBIterator iterator = db.iterator();
|
|
||||||
try {
|
|
||||||
Map<Long, Block> blocks = new HashMap<Long, Block>();
|
|
||||||
int count = 0;
|
|
||||||
if (!iterator.hasNext()) {
|
|
||||||
logger.info("DB is empty");
|
|
||||||
} else {
|
|
||||||
logger.info("Displaying blocks stored in DB sorted on key");
|
|
||||||
}
|
|
||||||
for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) {
|
|
||||||
byte[] key = iterator.peekNext().getKey();
|
|
||||||
byte[] value = iterator.peekNext().getValue();
|
|
||||||
Block block = new Block(value);
|
|
||||||
blocks.put(new Long(block.getNumber()), block);
|
|
||||||
logger.info("Block: " + count + " Key: " + Hex.toHexString(key) + " ---> " + block.toFlatString());
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
// Make sure you close the iterator to avoid resource leaks.
|
|
||||||
try {
|
|
||||||
iterator.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Insert object(value) (key = sha3(value)) */
|
/** Insert object(value) (key = sha3(value)) */
|
||||||
public void put(byte[] key, byte[] value) {
|
public void put(byte[] key, byte[] value) {
|
||||||
db.put(key, value);
|
db.put(key, value);
|
||||||
|
|
|
@ -4,6 +4,9 @@ import java.io.File;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.maxmind.geoip.Location;
|
import com.maxmind.geoip.Location;
|
||||||
import com.maxmind.geoip.LookupService;
|
import com.maxmind.geoip.LookupService;
|
||||||
|
|
||||||
|
@ -14,27 +17,30 @@ import com.maxmind.geoip.LookupService;
|
||||||
*/
|
*/
|
||||||
public class IpGeoDB { // change
|
public class IpGeoDB { // change
|
||||||
|
|
||||||
static{
|
private static Logger logger = LoggerFactory.getLogger(IpGeoDB.class);
|
||||||
try {
|
|
||||||
File file = null;
|
static {
|
||||||
try {
|
try {
|
||||||
|
File file = null;
|
||||||
|
try {
|
||||||
|
|
||||||
String dir = System.getProperty("user.dir");
|
String dir = System.getProperty("user.dir");
|
||||||
String fileName = dir + "/config/GeoLiteCity.dat";
|
String fileName = dir + "/config/GeoLiteCity.dat";
|
||||||
file = new File(fileName);
|
file = new File(fileName);
|
||||||
if (!file.exists()){
|
if (!file.exists()) {
|
||||||
URL geiIpDBFile = ClassLoader.getSystemResource("GeoLiteCity.dat");
|
URL geiIpDBFile = ClassLoader
|
||||||
file = new File(geiIpDBFile.toURI());
|
.getSystemResource("GeoLiteCity.dat");
|
||||||
}
|
file = new File(geiIpDBFile.toURI());
|
||||||
} catch (Throwable th) {
|
}
|
||||||
th.printStackTrace();
|
} catch (Throwable th) {
|
||||||
System.exit(-1);
|
logger.error(th.getMessage(), th);
|
||||||
}
|
System.exit(-1);
|
||||||
cl = new LookupService(file);
|
}
|
||||||
} catch (Throwable e) {
|
cl = new LookupService(file);
|
||||||
e.printStackTrace();
|
} catch (Throwable e) {
|
||||||
}
|
logger.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static LookupService cl;
|
private static LookupService cl;
|
||||||
|
|
||||||
|
@ -42,9 +48,8 @@ public class IpGeoDB { // change
|
||||||
try {
|
try {
|
||||||
return cl.getLocation(ip);
|
return cl.getLocation(ip);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// todo: think about this exception, maybe you can do something more reasonable
|
// TODO: think about this exception, maybe you can do something more reasonable
|
||||||
System.out.println(e.getMessage());
|
logger.error(e.getMessage(), e);
|
||||||
// e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,17 +22,16 @@ import java.math.BigInteger;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* www.ethereumJ.com
|
* www.ethereumJ.com
|
||||||
* User: Roman Mandeleil
|
* User: Roman Mandeleil
|
||||||
* Created on: 18/05/14 22:21
|
* Created on: 18/05/14 22:21
|
||||||
*/
|
*/
|
||||||
class ContractSubmitDialog extends JDialog implements MessageAwareDialog{
|
class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -3622984456084608996L;
|
||||||
ContractSubmitDialog dialog;
|
|
||||||
|
ContractSubmitDialog dialog;
|
||||||
JComboBox<AddressStateWraper> creatorAddressCombo;
|
JComboBox<AddressStateWraper> creatorAddressCombo;
|
||||||
final JTextField gasInput;
|
final JTextField gasInput;
|
||||||
final JTextField contractAddrInput;
|
final JTextField contractAddrInput;
|
||||||
|
@ -101,7 +100,6 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{
|
||||||
}}
|
}}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
JLabel statusMessage = new JLabel("");
|
JLabel statusMessage = new JLabel("");
|
||||||
statusMessage.setBounds(50, 360, 400, 50);
|
statusMessage.setBounds(50, 360, 400, 50);
|
||||||
statusMessage.setHorizontalAlignment(SwingConstants.CENTER);
|
statusMessage.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
@ -291,8 +289,6 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
|
|
||||||
AccountState as = new AccountState();
|
AccountState as = new AccountState();
|
||||||
|
@ -319,8 +315,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{
|
||||||
String valueShort = Utils.getValueShortString(addressState.getBalance());
|
String valueShort = Utils.getValueShortString(addressState.getBalance());
|
||||||
|
|
||||||
String result =
|
String result =
|
||||||
String.format(" By: [%s] %s",
|
String.format(" By: [%s] %s", addressShort, valueShort);
|
||||||
addressShort, valueShort);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,11 @@ import org.ethereum.core.Transaction;
|
||||||
import org.ethereum.manager.MainData;
|
import org.ethereum.manager.MainData;
|
||||||
import org.ethereum.net.submit.TransactionExecutor;
|
import org.ethereum.net.submit.TransactionExecutor;
|
||||||
import org.ethereum.net.submit.TransactionTask;
|
import org.ethereum.net.submit.TransactionTask;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -18,13 +21,14 @@ import static org.ethereum.config.SystemProperties.CONFIG;
|
||||||
* User: Roman Mandeleil
|
* User: Roman Mandeleil
|
||||||
* Created on: 26/05/2014 12:27
|
* Created on: 26/05/2014 12:27
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class DialogWorker extends SwingWorker {
|
public class DialogWorker extends SwingWorker {
|
||||||
|
|
||||||
Transaction tx;
|
private static Logger logger = LoggerFactory.getLogger(DialogWorker.class);
|
||||||
MessageAwareDialog dialog;
|
|
||||||
|
private Transaction tx;
|
||||||
|
private MessageAwareDialog dialog;
|
||||||
|
|
||||||
DialogWorker(Transaction tx, MessageAwareDialog dialog) {
|
public DialogWorker(Transaction tx, MessageAwareDialog dialog) {
|
||||||
this.tx = tx;
|
this.tx = tx;
|
||||||
this.dialog = dialog;
|
this.dialog = dialog;
|
||||||
}
|
}
|
||||||
|
@ -32,21 +36,21 @@ public class DialogWorker extends SwingWorker {
|
||||||
@Override
|
@Override
|
||||||
protected Object doInBackground() throws Exception {
|
protected Object doInBackground() throws Exception {
|
||||||
TransactionTask transactionTask = new TransactionTask(tx);
|
TransactionTask transactionTask = new TransactionTask(tx);
|
||||||
Future future = TransactionExecutor.instance.submitTransaction(transactionTask);
|
Future<Transaction> future = TransactionExecutor.instance.submitTransaction(transactionTask);
|
||||||
dialog.infoStatusMsg("Transaction sent to the network, waiting for approve");
|
dialog.infoStatusMsg("Transaction sent to the network, waiting for approve");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
future.get(CONFIG.transactionApproveTimeout(), TimeUnit.SECONDS);
|
future.get(CONFIG.transactionApproveTimeout(), TimeUnit.SECONDS);
|
||||||
} catch (TimeoutException e1) {
|
} catch (TimeoutException toe) {
|
||||||
e1.printStackTrace();
|
logger.error(toe.getMessage(), toe);
|
||||||
dialog.alertStatusMsg("Transaction wasn't approved, network timeout");
|
dialog.alertStatusMsg("Transaction wasn't approved, network timeout");
|
||||||
return null;
|
return null;
|
||||||
} catch (InterruptedException e1) {
|
} catch (InterruptedException ie) {
|
||||||
e1.printStackTrace();
|
logger.error(ie.getMessage(), ie);
|
||||||
dialog.alertStatusMsg("Transaction wasn't approved");
|
dialog.alertStatusMsg("Transaction wasn't approved");
|
||||||
return null;
|
return null;
|
||||||
} catch (ExecutionException e1) {
|
} catch (ExecutionException ee) {
|
||||||
e1.printStackTrace();
|
logger.error(ee.getMessage(), ee);
|
||||||
dialog.alertStatusMsg("Transaction wasn't approved");
|
dialog.alertStatusMsg("Transaction wasn't approved");
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
package org.ethereum.gui;
|
package org.ethereum.gui;
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* www.ethereumJ.com
|
* This interface describes the methods required
|
||||||
* User: Roman Mandeleil
|
* for any dialog that displays info- and alert status messages.
|
||||||
* Created on: 26/05/2014 12:29
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface MessageAwareDialog {
|
public interface MessageAwareDialog {
|
||||||
public void infoStatusMsg(final String text);
|
|
||||||
public void alertStatusMsg(final String text);
|
|
||||||
|
|
||||||
|
public void infoStatusMsg(final String text);
|
||||||
|
|
||||||
|
public void alertStatusMsg(final String text);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,12 +22,14 @@ import javax.swing.*;
|
||||||
* User: Roman Mandeleil
|
* User: Roman Mandeleil
|
||||||
* Created on: 18/05/14 22:21
|
* Created on: 18/05/14 22:21
|
||||||
*/
|
*/
|
||||||
class PayOutDialog extends JDialog implements MessageAwareDialog{
|
class PayOutDialog extends JDialog implements MessageAwareDialog {
|
||||||
|
|
||||||
PayOutDialog dialog;
|
private static final long serialVersionUID = -2838121935782110981L;
|
||||||
|
|
||||||
AccountState addressState = null;
|
private PayOutDialog dialog;
|
||||||
JLabel statusMsg = null;
|
|
||||||
|
private AccountState addressState = null;
|
||||||
|
private JLabel statusMsg = null;
|
||||||
|
|
||||||
final JTextField receiverInput;
|
final JTextField receiverInput;
|
||||||
final JTextField amountInput;
|
final JTextField amountInput;
|
||||||
|
@ -124,7 +126,6 @@ class PayOutDialog extends JDialog implements MessageAwareDialog{
|
||||||
try {
|
try {
|
||||||
tx.sign(senderPrivKey);
|
tx.sign(senderPrivKey);
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
|
|
||||||
dialog.alertStatusMsg("Failed to sign the transaction");
|
dialog.alertStatusMsg("Failed to sign the transaction");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package org.ethereum.gui;
|
package org.ethereum.gui;
|
||||||
|
|
||||||
import org.ethereum.vm.DataWord;
|
|
||||||
import org.ethereum.vm.Program;
|
import org.ethereum.vm.Program;
|
||||||
import org.ethereum.vm.ProgramInvoke;
|
|
||||||
import org.ethereum.vm.VM;
|
import org.ethereum.vm.VM;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
@ -12,7 +10,6 @@ import javax.swing.event.ChangeListener;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.WindowListener;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -22,7 +19,8 @@ import java.util.List;
|
||||||
* Created on: 02/06/2014 16:58
|
* Created on: 02/06/2014 16:58
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeListener, Program.ProgramListener {
|
public class ProgramPlayDialog extends JPanel implements ActionListener,
|
||||||
|
ChangeListener, Program.ProgramListener {
|
||||||
|
|
||||||
public List<String> outputList;
|
public List<String> outputList;
|
||||||
public JTextArea console;
|
public JTextArea console;
|
||||||
|
@ -95,8 +93,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -111,7 +107,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
||||||
console.setCaretPosition(0);
|
console.setCaretPosition(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the GUI and show it. For thread safety,
|
* Create the GUI and show it. For thread safety,
|
||||||
* this method should be invoked from the
|
* this method should be invoked from the
|
||||||
|
@ -119,8 +114,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
||||||
*/
|
*/
|
||||||
public static void createAndShowGUI() {
|
public static void createAndShowGUI() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ProgramPlayDialog ppd = new ProgramPlayDialog();
|
ProgramPlayDialog ppd = new ProgramPlayDialog();
|
||||||
|
|
||||||
//Create and set up the window.
|
//Create and set up the window.
|
||||||
|
@ -130,7 +123,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
||||||
frame.setPreferredSize(new Dimension(580, 500));
|
frame.setPreferredSize(new Dimension(580, 500));
|
||||||
frame.setLocation(400, 200);
|
frame.setLocation(400, 200);
|
||||||
|
|
||||||
|
|
||||||
//Add content to the window.
|
//Add content to the window.
|
||||||
frame.add(ppd, BorderLayout.CENTER);
|
frame.add(ppd, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
@ -138,7 +130,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
||||||
frame.pack();
|
frame.pack();
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
ppd.setFocus();
|
ppd.setFocus();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -151,10 +142,9 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
||||||
/* Turn off metal's use of bold fonts */
|
/* Turn off metal's use of bold fonts */
|
||||||
UIManager.put("swing.boldMetal", Boolean.FALSE);
|
UIManager.put("swing.boldMetal", Boolean.FALSE);
|
||||||
|
|
||||||
|
|
||||||
//Schedule a job for the event-dispatching thread:
|
//Schedule a job for the event-dispatching thread:
|
||||||
//creating and showing this application's GUI.
|
//creating and showing this application's GUI.
|
||||||
javax.swing.SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
createAndShowGUI();
|
createAndShowGUI();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class StaticMessages {
|
||||||
public static final byte[] GET_TRANSACTIONS = Hex.decode("2240089100000002C116");
|
public static final byte[] GET_TRANSACTIONS = Hex.decode("2240089100000002C116");
|
||||||
|
|
||||||
public static final byte[] DISCONNECT_08 = Hex.decode("2240089100000003C20108");
|
public static final byte[] DISCONNECT_08 = Hex.decode("2240089100000003C20108");
|
||||||
public static final byte[] GENESIS_HASH = Hex.decode("77ef4fdaf389dca53236bcf7f72698e154eab2828f86fbc4fc6cd9225d285c89"); // (new Genesis()).getHash();
|
public static final byte[] GENESIS_HASH = Hex.decode("77ef4fdaf389dca53236bcf7f72698e154eab2828f86fbc4fc6cd9225d285c89");
|
||||||
public static final byte[] MAGIC_PACKET = Hex.decode("22400891");
|
public static final byte[] MAGIC_PACKET = Hex.decode("22400891");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
|
@ -10,14 +10,16 @@ import org.ethereum.core.Transaction;
|
||||||
|
|
||||||
public class PendingTransaction {
|
public class PendingTransaction {
|
||||||
|
|
||||||
Transaction tx;
|
private Transaction tx;
|
||||||
int approved = 0; // each time the tx got from the wire this value increased
|
int approved = 0; // each time the tx got from the wire this value increased
|
||||||
|
|
||||||
public PendingTransaction(Transaction tx) {
|
public PendingTransaction(Transaction tx) {
|
||||||
this.tx = tx;
|
this.tx = tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void incApproved(){++this.approved;}
|
public void incApproved() {
|
||||||
|
++this.approved;
|
||||||
|
}
|
||||||
|
|
||||||
public int getApproved() {
|
public int getApproved() {
|
||||||
return approved;
|
return approved;
|
||||||
|
|
|
@ -7,12 +7,12 @@ import static org.ethereum.util.CompactEncoder.unpackToNibbles;
|
||||||
|
|
||||||
public class TrieIterator {
|
public class TrieIterator {
|
||||||
|
|
||||||
Trie trie;
|
private Trie trie;
|
||||||
String key;
|
private String key;
|
||||||
String value;
|
private String value;
|
||||||
|
|
||||||
List<byte[]> shas;
|
private List<byte[]> shas;
|
||||||
List<String> values;
|
private List<String> values;
|
||||||
|
|
||||||
public TrieIterator(Trie t) {
|
public TrieIterator(Trie t) {
|
||||||
this.trie = t;
|
this.trie = t;
|
||||||
|
|
|
@ -7,34 +7,31 @@ import java.math.BigInteger;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* www.ethereumJ.com
|
* DataWord is the 32-byte array representation of a 256-bit number
|
||||||
* User: Roman Mandeleil
|
* Calculations can be done on this word with other DataWords
|
||||||
* Created on: 01/06/2014 19:47
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class DataWord {
|
public class DataWord {
|
||||||
|
|
||||||
static DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack
|
static DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack
|
||||||
|
|
||||||
byte[] data = new byte[32];
|
byte[] data = new byte[32];
|
||||||
|
|
||||||
public DataWord(){
|
public DataWord() {
|
||||||
data = new byte[32];
|
data = new byte[32];
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataWord(int num){
|
public DataWord(int num) {
|
||||||
ByteBuffer bInt = ByteBuffer.allocate(4).putInt(num);
|
ByteBuffer bInt = ByteBuffer.allocate(4).putInt(num);
|
||||||
ByteBuffer data = ByteBuffer.allocate(32);
|
ByteBuffer data = ByteBuffer.allocate(32);
|
||||||
System.arraycopy(bInt.array(), 0, data.array(), 28, 4);
|
System.arraycopy(bInt.array(), 0, data.array(), 28, 4);
|
||||||
this.data = data.array();
|
this.data = data.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataWord(byte[] data){
|
public DataWord(byte[] data) {
|
||||||
if (data == null || data.length > 32)
|
if (data == null || data.length > 32)
|
||||||
throw new RuntimeException("bad push data: " + data);
|
throw new RuntimeException("bad push data: " + data);
|
||||||
|
System.arraycopy(data, 0, this.data, 32 - data.length, data.length);
|
||||||
System.arraycopy(data, 0, this.data, 32 - data.length, data.length);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getData() {
|
public byte[] getData() {
|
||||||
return data;
|
return data;
|
||||||
|
@ -95,9 +92,20 @@ public class DataWord {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: add can be done in more efficient way
|
// By : Holger
|
||||||
// todo without BigInteger quick hack
|
// From : http://stackoverflow.com/a/24023466/459349
|
||||||
public void add(DataWord word){
|
public void add(DataWord word) {
|
||||||
|
byte[] result = new byte[32];
|
||||||
|
for (int i = 31, overflow = 0; i >= 0; i--) {
|
||||||
|
int v = (this.data[i] & 0xff) + (word.data[i] & 0xff) + overflow;
|
||||||
|
result[i] = (byte) v;
|
||||||
|
overflow = v >>> 8;
|
||||||
|
}
|
||||||
|
this.data = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// old add-method with BigInteger quick hack
|
||||||
|
public void add2(DataWord word){
|
||||||
|
|
||||||
BigInteger result = value().add( word.value() );
|
BigInteger result = value().add( word.value() );
|
||||||
byte[] bytes = result.toByteArray();
|
byte[] bytes = result.toByteArray();
|
||||||
|
@ -106,11 +114,11 @@ public class DataWord {
|
||||||
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
|
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
|
||||||
this.data = data.array();
|
this.data = data.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: mull can be done in more efficient way
|
// todo: mul can be done in more efficient way
|
||||||
// todo: with shift left shift right trick
|
// todo: with shift left shift right trick
|
||||||
// todo without BigInteger quick hack
|
// todo without BigInteger quick hack
|
||||||
public void mull(DataWord word){
|
public void mul(DataWord word){
|
||||||
|
|
||||||
BigInteger result = value().multiply( word.value() );
|
BigInteger result = value().multiply( word.value() );
|
||||||
byte[] bytes = result.toByteArray();
|
byte[] bytes = result.toByteArray();
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class VM {
|
||||||
|
|
||||||
DataWord word1 = program.stackPop();
|
DataWord word1 = program.stackPop();
|
||||||
DataWord word2 = program.stackPop();
|
DataWord word2 = program.stackPop();
|
||||||
word1.mull(word2);
|
word1.mul(word2);
|
||||||
program.stackPush(word1);
|
program.stackPush(word1);
|
||||||
program.step();
|
program.step();
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,4 +69,4 @@ samples.dir = samples
|
||||||
# the existing database will be
|
# the existing database will be
|
||||||
# destroyed and all the data will be
|
# destroyed and all the data will be
|
||||||
# downloaded from peers again
|
# downloaded from peers again
|
||||||
database.reset = true
|
database.reset = false
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class BlockTest {
|
||||||
// from RLP encoding
|
// from RLP encoding
|
||||||
byte[] genesisBytes = Hex.decode(CPP_PoC5_GENESIS_HEX_RLP_ENCODED);
|
byte[] genesisBytes = Hex.decode(CPP_PoC5_GENESIS_HEX_RLP_ENCODED);
|
||||||
Block genesisFromRLP = new Block(genesisBytes);
|
Block genesisFromRLP = new Block(genesisBytes);
|
||||||
Genesis genesis = new Genesis();
|
Block genesis = Genesis.getInstance();
|
||||||
assertEquals(Hex.toHexString(genesis.getHash()), Hex.toHexString(genesisFromRLP.getHash()));
|
assertEquals(Hex.toHexString(genesis.getHash()), Hex.toHexString(genesisFromRLP.getHash()));
|
||||||
assertEquals(Hex.toHexString(genesis.getParentHash()), Hex.toHexString(genesisFromRLP.getParentHash()));
|
assertEquals(Hex.toHexString(genesis.getParentHash()), Hex.toHexString(genesisFromRLP.getParentHash()));
|
||||||
assertEquals(Hex.toHexString(genesis.getStateRoot()), Hex.toHexString(genesisFromRLP.getStateRoot()));
|
assertEquals(Hex.toHexString(genesis.getStateRoot()), Hex.toHexString(genesisFromRLP.getStateRoot()));
|
||||||
|
@ -48,7 +48,7 @@ public class BlockTest {
|
||||||
B32(sha3(B(42)))
|
B32(sha3(B(42)))
|
||||||
)
|
)
|
||||||
*/
|
*/
|
||||||
Block genesis = new Genesis();
|
Block genesis = Genesis.getInstance();
|
||||||
assertEquals(CPP_PoC5_GENESIS_HEX_RLP_ENCODED, Hex.toHexString(genesis.getEncoded()));
|
assertEquals(CPP_PoC5_GENESIS_HEX_RLP_ENCODED, Hex.toHexString(genesis.getEncoded()));
|
||||||
|
|
||||||
// Not really a good test because this compares Genesis.getHash() to itself
|
// Not really a good test because this compares Genesis.getHash() to itself
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package org.ethereum.vm;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
public class DataWordTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddPerformance() {
|
||||||
|
boolean enabled = true;
|
||||||
|
|
||||||
|
if(enabled) {
|
||||||
|
byte[] one = new byte[] { 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54,
|
||||||
|
0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01,
|
||||||
|
0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54,
|
||||||
|
0x41, 0x01, 0x31, 0x54, 0x41 }; // Random value
|
||||||
|
|
||||||
|
int ITERATIONS = 10000000;
|
||||||
|
|
||||||
|
long now1 = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
DataWord x = new DataWord(one);
|
||||||
|
x.add(x);
|
||||||
|
}
|
||||||
|
System.out.println("Add1: " + (System.currentTimeMillis() - now1) + "ms");
|
||||||
|
|
||||||
|
long now2 = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
DataWord x = new DataWord(one);
|
||||||
|
x.add2(x);
|
||||||
|
}
|
||||||
|
System.out.println("Add2: " + (System.currentTimeMillis() - now2) + "ms");
|
||||||
|
} else {
|
||||||
|
System.out.println("ADD performance test is disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdd2() {
|
||||||
|
byte[] two = new byte[32];
|
||||||
|
two[31] = (byte) 0xff; // 0x000000000000000000000000000000000000000000000000000000000000ff
|
||||||
|
|
||||||
|
DataWord x = new DataWord(two);
|
||||||
|
x.add(new DataWord(two));
|
||||||
|
System.out.println(Hex.toHexString(x.data));
|
||||||
|
|
||||||
|
DataWord y = new DataWord(two);
|
||||||
|
y.add2(new DataWord(two));
|
||||||
|
System.out.println(Hex.toHexString(y.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdd3() {
|
||||||
|
byte[] three = new byte[32];
|
||||||
|
for (int i = 0; i < three.length; i++) {
|
||||||
|
three[i] = (byte) 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataWord x = new DataWord(three);
|
||||||
|
x.add(new DataWord(three));
|
||||||
|
assertEquals(32, x.data.length);
|
||||||
|
System.out.println(Hex.toHexString(x.data));
|
||||||
|
|
||||||
|
// FAIL
|
||||||
|
// DataWord y = new DataWord(three);
|
||||||
|
// y.add2(new DataWord(three));
|
||||||
|
// System.out.println(Hex.toHexString(y.data));
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,8 +4,6 @@ import org.ethereum.crypto.ECKey;
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* www.ethereumJ.com
|
* www.ethereumJ.com
|
||||||
* User: Roman Mandeleil
|
* User: Roman Mandeleil
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.ethereum.vm;
|
package org.ethereum.vm;
|
||||||
|
|
||||||
import org.ethereum.crypto.HashUtil;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue