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 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();
|
||||
private Properties prop = new Properties();
|
||||
private InputStream input = null;
|
||||
|
||||
public SystemProperties() {
|
||||
try {
|
||||
|
||||
|
||||
try {
|
||||
File file = null;
|
||||
String dir = System.getProperty("user.dir");
|
||||
String fileName = dir + "/config/system.properties";
|
||||
|
@ -41,7 +48,6 @@ public class SystemProperties {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//load a properties file from class path, inside static method
|
||||
prop.load(input);
|
||||
|
||||
|
@ -77,18 +83,17 @@ public class SystemProperties {
|
|||
|
||||
public int transactionApproveTimeout(){
|
||||
if (prop.isEmpty())
|
||||
return 10;
|
||||
return DEFAULT_TX_APPROVE_TIMEOUT;
|
||||
return Integer.parseInt(prop.getProperty("transaction.approve.timeout"));
|
||||
}
|
||||
|
||||
|
||||
public String peerDiscoveryIP(){
|
||||
if(prop.isEmpty()) return "54.201.28.117";
|
||||
if(prop.isEmpty()) return DEFAULT_DISCOVERY_PEER;
|
||||
return prop.getProperty("peer.discovery.ip");
|
||||
}
|
||||
|
||||
public int peerDiscoveryPort(){
|
||||
if(prop.isEmpty()) return 30303;
|
||||
if(prop.isEmpty()) return DEFAULT_DISCOVERY_PORT;
|
||||
return Integer.parseInt(prop.getProperty("peer.discovery.port"));
|
||||
}
|
||||
|
||||
|
@ -98,21 +103,21 @@ public class SystemProperties {
|
|||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
public int activePeerPort(){
|
||||
if(prop.isEmpty()) return 30303;
|
||||
if(prop.isEmpty()) return DEFAULT_ACTIVE_PORT;
|
||||
return Integer.parseInt(prop.getProperty("peer.active.port"));
|
||||
}
|
||||
|
||||
public String samplesDir(){
|
||||
if(prop.isEmpty()) return "samples";
|
||||
if(prop.isEmpty()) return DEFAULT_SAMPLES_DIR;
|
||||
return prop.getProperty("samples.dir");
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
public void print() {
|
||||
Enumeration<?> e = prop.propertyNames();
|
||||
while (e.hasMoreElements()) {
|
||||
String key = (String) e.nextElement();
|
||||
|
@ -120,11 +125,10 @@ public class SystemProperties {
|
|||
if (!key.equals("null"))
|
||||
logger.info("Key: " + key + ", Value: " + value);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void main(String args[]){
|
||||
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
|
||||
* 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
|
||||
* of the account and does not contribute to its later serialisation */
|
||||
private byte[] stateRoot = new byte[0];
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package org.ethereum.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -20,31 +19,22 @@ import org.spongycastle.util.encoders.Hex;
|
|||
|
||||
public class Blockchain extends ArrayList<Block> {
|
||||
|
||||
private static final long serialVersionUID = -143590724563460486L;
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(Blockchain.class);
|
||||
|
||||
private Database db;
|
||||
private Wallet wallet;
|
||||
private long gasPrice = 1000;
|
||||
private Block lastBlock = new Genesis();
|
||||
private Block lastBlock;
|
||||
|
||||
private Map<BigInteger, PendingTransaction> pendingTransactions =
|
||||
Collections.synchronizedMap(new HashMap<BigInteger, PendingTransaction>());
|
||||
private Map<String, PendingTransaction> pendingTransactions =
|
||||
Collections.synchronizedMap(new HashMap<String, PendingTransaction>());
|
||||
|
||||
public Blockchain(Wallet wallet) {
|
||||
this.db = Config.CHAIN_DB;
|
||||
this.wallet = wallet;
|
||||
|
||||
// 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());
|
||||
}
|
||||
this.loadChain();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
if (blocks.isEmpty()) return;
|
||||
if (blocks.isEmpty())
|
||||
return;
|
||||
|
||||
Block firstBlockToAdd = blocks.get(blocks.size() - 1);
|
||||
|
||||
// if it is the first block to add
|
||||
// check that the parent is the genesis
|
||||
if (this.isEmpty() &&
|
||||
!Arrays.equals(StaticMessages.GENESIS_HASH, firstBlockToAdd.getParentHash())){
|
||||
return;
|
||||
}
|
||||
if (this.isEmpty()
|
||||
&& !Arrays.equals(StaticMessages.GENESIS_HASH,
|
||||
firstBlockToAdd.getParentHash())) {
|
||||
return;
|
||||
}
|
||||
// if there is some blocks already keep chain continuity
|
||||
if (!this.isEmpty() ){
|
||||
if (!this.isEmpty()) {
|
||||
Block lastBlock = this.get(this.size() - 1);
|
||||
String hashLast = Hex.toHexString(lastBlock.getHash());
|
||||
String blockParentHash = Hex.toHexString(firstBlockToAdd.getParentHash());
|
||||
if (!hashLast.equals(blockParentHash)) return;
|
||||
}
|
||||
for (int i = blocks.size() - 1; i >= 0 ; --i){
|
||||
Block block = blocks.get(i);
|
||||
this.add(block);
|
||||
if(block.getNumber() > lastBlock.getNumber()) lastBlock = block;
|
||||
|
||||
Block block = blocks.get(i);
|
||||
this.addBlock(block);
|
||||
db.put(block.getParentHash(), block.getEncoded());
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
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
|
||||
for (Block block : blocks){
|
||||
for (Transaction tx : block.getTransactionsList()){
|
||||
for (Block block : blocks) {
|
||||
for (Transaction tx : block.getTransactionsList()) {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash()));
|
||||
removePendingTransaction(tx);
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("*** Block chain size: [ {} ]", this.size());
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
private void addBlock(Block block) {
|
||||
this.wallet.processBlock(block);
|
||||
this.gasPrice = block.getMinGasPrice();
|
||||
if(lastBlock == null || block.getNumber() > lastBlock.getNumber())
|
||||
this.lastBlock = block;
|
||||
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) {
|
||||
|
||||
BigInteger hash = new BigInteger(transaction.getHash());
|
||||
logger.info("pending transaction placed hash: {} ", hash.toString(16) );
|
||||
String hash = Hex.toHexString(transaction.getHash());
|
||||
logger.info("pending transaction placed hash: {} ", hash );
|
||||
|
||||
PendingTransaction pendingTransaction = pendingTransactions.get(hash);
|
||||
if (pendingTransaction != null)
|
||||
|
@ -120,24 +116,44 @@ public class Blockchain extends ArrayList<Block> {
|
|||
}
|
||||
|
||||
public void removePendingTransaction(Transaction transaction){
|
||||
|
||||
BigInteger hash = new BigInteger(transaction.getHash());
|
||||
logger.info("pending transaction removed with hash: {} ", hash.toString(16) );
|
||||
String hash = Hex.toHexString(transaction.getHash());
|
||||
logger.info("pending transaction removed with hash: {} ", hash );
|
||||
pendingTransactions.remove(hash);
|
||||
}
|
||||
|
||||
public long getGasPrice() {
|
||||
return gasPrice;
|
||||
}
|
||||
|
||||
public byte[] getLatestBlockHash(){
|
||||
|
||||
if (this.isEmpty())
|
||||
return StaticMessages.GENESIS_HASH;
|
||||
else{
|
||||
|
||||
return lastBlock.getHash();
|
||||
}
|
||||
|
||||
if (this.isEmpty())
|
||||
return StaticMessages.GENESIS_HASH;
|
||||
else
|
||||
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 byte[] EXTRA_DATA = new byte[0];
|
||||
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,
|
||||
NUMBER, MIN_GAS_PRICE, GAS_LIMIT, GAS_USED, TIMESTAMP,
|
||||
EXTRA_DATA, NONCE, null, null);
|
||||
|
@ -53,9 +55,16 @@ public class Genesis extends Block {
|
|||
this.updateState(Hex.decode("6c386a4b26f73c802f34673f7248bb118f97424a"), acct.getEncoded());
|
||||
// # (R)
|
||||
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-stateRoot: " + Hex.toHexString(this.getStateRoot()));
|
||||
|
||||
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
|
||||
public static StateObject createContract(Transaction tx, GoState state) {
|
||||
// Create contract if there's no recipient
|
||||
if (tx.isContract()) {
|
||||
if (tx.isContractCreation()) {
|
||||
// FIXME
|
||||
byte[] txHash = tx.getHash();
|
||||
byte[] contractAddress = copyOfRange(txHash, 12, txHash.length);
|
||||
|
|
|
@ -164,14 +164,14 @@ public class Transaction {
|
|||
|
||||
public byte[] getContractAddress(){
|
||||
|
||||
if (!isContract()) return null;
|
||||
if (!isContractCreation()) return null;
|
||||
|
||||
byte[] encSender = RLP.encodeElement(getSender());
|
||||
byte[] encNonce = RLP.encodeElement(nonce);
|
||||
return HashUtil.sha3omit12(RLP.encodeList(encSender, encNonce));
|
||||
}
|
||||
|
||||
public boolean isContract() {
|
||||
public boolean isContractCreation() {
|
||||
return Arrays.equals(this.receiveAddress, ZERO_ADDRESS);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ import org.spongycastle.util.encoders.Base64;
|
|||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
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. */
|
||||
public static final ECDomainParameters CURVE;
|
||||
|
@ -448,11 +448,10 @@ public class ECKey implements Serializable {
|
|||
signer.init(false, params);
|
||||
try {
|
||||
return signer.verifySignature(data, signature.r, signature.s);
|
||||
} catch (NullPointerException e) {
|
||||
// Bouncy Castle contains a bug that can cause NPEs given specially crafted signatures. 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");
|
||||
e.printStackTrace();
|
||||
} catch (NullPointerException npe) {
|
||||
// Bouncy Castle contains a bug that can cause NPEs given specially crafted signatures.
|
||||
// Those signatures are inherently invalid/attack sigs so we just fail them here rather than crash the thread.
|
||||
logger.error("Caught NPE inside bouncy castle", npe);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,13 @@ import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
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.DBIterator;
|
||||
import org.iq80.leveldb.Options;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
* Generic interface for Ethereum database
|
||||
|
@ -47,8 +41,6 @@ public class Database {
|
|||
logger.debug("Initializing new or existing DB: '" + name + "'");
|
||||
options.createIfMissing(true);
|
||||
db = factory.open(new File(name), options);
|
||||
|
||||
printDB();
|
||||
// logger.debug("Showing database stats");
|
||||
// String stats = DATABASE.getProperty("leveldb.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)) */
|
||||
public void put(byte[] key, byte[] value) {
|
||||
db.put(key, value);
|
||||
|
|
|
@ -4,6 +4,9 @@ import java.io.File;
|
|||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.maxmind.geoip.Location;
|
||||
import com.maxmind.geoip.LookupService;
|
||||
|
||||
|
@ -14,27 +17,30 @@ import com.maxmind.geoip.LookupService;
|
|||
*/
|
||||
public class IpGeoDB { // change
|
||||
|
||||
static{
|
||||
try {
|
||||
File file = null;
|
||||
try {
|
||||
private static Logger logger = LoggerFactory.getLogger(IpGeoDB.class);
|
||||
|
||||
static {
|
||||
try {
|
||||
File file = null;
|
||||
try {
|
||||
|
||||
String dir = System.getProperty("user.dir");
|
||||
String fileName = dir + "/config/GeoLiteCity.dat";
|
||||
file = new File(fileName);
|
||||
if (!file.exists()){
|
||||
URL geiIpDBFile = ClassLoader.getSystemResource("GeoLiteCity.dat");
|
||||
file = new File(geiIpDBFile.toURI());
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
th.printStackTrace();
|
||||
System.exit(-1);
|
||||
}
|
||||
cl = new LookupService(file);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
String dir = System.getProperty("user.dir");
|
||||
String fileName = dir + "/config/GeoLiteCity.dat";
|
||||
file = new File(fileName);
|
||||
if (!file.exists()) {
|
||||
URL geiIpDBFile = ClassLoader
|
||||
.getSystemResource("GeoLiteCity.dat");
|
||||
file = new File(geiIpDBFile.toURI());
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
logger.error(th.getMessage(), th);
|
||||
System.exit(-1);
|
||||
}
|
||||
cl = new LookupService(file);
|
||||
} catch (Throwable e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static LookupService cl;
|
||||
|
||||
|
@ -42,9 +48,8 @@ public class IpGeoDB { // change
|
|||
try {
|
||||
return cl.getLocation(ip);
|
||||
} catch (Throwable e) {
|
||||
// todo: think about this exception, maybe you can do something more reasonable
|
||||
System.out.println(e.getMessage());
|
||||
// e.printStackTrace();
|
||||
// TODO: think about this exception, maybe you can do something more reasonable
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -22,17 +22,16 @@ import java.math.BigInteger;
|
|||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* User: Roman Mandeleil
|
||||
* Created on: 18/05/14 22:21
|
||||
*/
|
||||
class ContractSubmitDialog extends JDialog implements MessageAwareDialog{
|
||||
class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
|
||||
|
||||
|
||||
ContractSubmitDialog dialog;
|
||||
private static final long serialVersionUID = -3622984456084608996L;
|
||||
|
||||
ContractSubmitDialog dialog;
|
||||
JComboBox<AddressStateWraper> creatorAddressCombo;
|
||||
final JTextField gasInput;
|
||||
final JTextField contractAddrInput;
|
||||
|
@ -101,7 +100,6 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{
|
|||
}}
|
||||
);
|
||||
|
||||
|
||||
JLabel statusMessage = new JLabel("");
|
||||
statusMessage.setBounds(50, 360, 400, 50);
|
||||
statusMessage.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
|
@ -291,8 +289,6 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void main(String args[]) {
|
||||
|
||||
AccountState as = new AccountState();
|
||||
|
@ -319,8 +315,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{
|
|||
String valueShort = Utils.getValueShortString(addressState.getBalance());
|
||||
|
||||
String result =
|
||||
String.format(" By: [%s] %s",
|
||||
addressShort, valueShort);
|
||||
String.format(" By: [%s] %s", addressShort, valueShort);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,11 @@ import org.ethereum.core.Transaction;
|
|||
import org.ethereum.manager.MainData;
|
||||
import org.ethereum.net.submit.TransactionExecutor;
|
||||
import org.ethereum.net.submit.TransactionTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -18,13 +21,14 @@ import static org.ethereum.config.SystemProperties.CONFIG;
|
|||
* User: Roman Mandeleil
|
||||
* Created on: 26/05/2014 12:27
|
||||
*/
|
||||
|
||||
public class DialogWorker extends SwingWorker {
|
||||
|
||||
Transaction tx;
|
||||
MessageAwareDialog dialog;
|
||||
private static Logger logger = LoggerFactory.getLogger(DialogWorker.class);
|
||||
|
||||
private Transaction tx;
|
||||
private MessageAwareDialog dialog;
|
||||
|
||||
DialogWorker(Transaction tx, MessageAwareDialog dialog) {
|
||||
public DialogWorker(Transaction tx, MessageAwareDialog dialog) {
|
||||
this.tx = tx;
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
@ -32,21 +36,21 @@ public class DialogWorker extends SwingWorker {
|
|||
@Override
|
||||
protected Object doInBackground() throws Exception {
|
||||
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");
|
||||
|
||||
try {
|
||||
future.get(CONFIG.transactionApproveTimeout(), TimeUnit.SECONDS);
|
||||
} catch (TimeoutException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (TimeoutException toe) {
|
||||
logger.error(toe.getMessage(), toe);
|
||||
dialog.alertStatusMsg("Transaction wasn't approved, network timeout");
|
||||
return null;
|
||||
} catch (InterruptedException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (InterruptedException ie) {
|
||||
logger.error(ie.getMessage(), ie);
|
||||
dialog.alertStatusMsg("Transaction wasn't approved");
|
||||
return null;
|
||||
} catch (ExecutionException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (ExecutionException ee) {
|
||||
logger.error(ee.getMessage(), ee);
|
||||
dialog.alertStatusMsg("Transaction wasn't approved");
|
||||
return null;
|
||||
} finally {
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* User: Roman Mandeleil
|
||||
* Created on: 26/05/2014 12:29
|
||||
* This interface describes the methods required
|
||||
* for any dialog that displays info- and alert status messages.
|
||||
*/
|
||||
|
||||
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
|
||||
* 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;
|
||||
JLabel statusMsg = null;
|
||||
private PayOutDialog dialog;
|
||||
|
||||
private AccountState addressState = null;
|
||||
private JLabel statusMsg = null;
|
||||
|
||||
final JTextField receiverInput;
|
||||
final JTextField amountInput;
|
||||
|
@ -124,7 +126,6 @@ class PayOutDialog extends JDialog implements MessageAwareDialog{
|
|||
try {
|
||||
tx.sign(senderPrivKey);
|
||||
} catch (Exception e1) {
|
||||
|
||||
dialog.alertStatusMsg("Failed to sign the transaction");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.ethereum.vm.Program;
|
||||
import org.ethereum.vm.ProgramInvoke;
|
||||
import org.ethereum.vm.VM;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
|
@ -12,7 +10,6 @@ import javax.swing.event.ChangeListener;
|
|||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -22,7 +19,8 @@ import java.util.List;
|
|||
* 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 JTextArea console;
|
||||
|
@ -95,8 +93,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
|||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -111,7 +107,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
|||
console.setCaretPosition(0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the GUI and show it. For thread safety,
|
||||
* this method should be invoked from the
|
||||
|
@ -119,8 +114,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
|||
*/
|
||||
public static void createAndShowGUI() {
|
||||
|
||||
|
||||
|
||||
ProgramPlayDialog ppd = new ProgramPlayDialog();
|
||||
|
||||
//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.setLocation(400, 200);
|
||||
|
||||
|
||||
//Add content to the window.
|
||||
frame.add(ppd, BorderLayout.CENTER);
|
||||
|
||||
|
@ -138,7 +130,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
|||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
ppd.setFocus();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -151,10 +142,9 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
|||
/* Turn off metal's use of bold fonts */
|
||||
UIManager.put("swing.boldMetal", Boolean.FALSE);
|
||||
|
||||
|
||||
//Schedule a job for the event-dispatching thread:
|
||||
//creating and showing this application's GUI.
|
||||
javax.swing.SwingUtilities.invokeLater(new Runnable() {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
createAndShowGUI();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ public class StaticMessages {
|
|||
public static final byte[] GET_TRANSACTIONS = Hex.decode("2240089100000002C116");
|
||||
|
||||
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");
|
||||
|
||||
static {
|
||||
|
|
|
@ -10,14 +10,16 @@ import org.ethereum.core.Transaction;
|
|||
|
||||
public class PendingTransaction {
|
||||
|
||||
Transaction tx;
|
||||
private Transaction tx;
|
||||
int approved = 0; // each time the tx got from the wire this value increased
|
||||
|
||||
public PendingTransaction(Transaction tx) {
|
||||
this.tx = tx;
|
||||
}
|
||||
|
||||
public void incApproved(){++this.approved;}
|
||||
public void incApproved() {
|
||||
++this.approved;
|
||||
}
|
||||
|
||||
public int getApproved() {
|
||||
return approved;
|
||||
|
|
|
@ -7,12 +7,12 @@ import static org.ethereum.util.CompactEncoder.unpackToNibbles;
|
|||
|
||||
public class TrieIterator {
|
||||
|
||||
Trie trie;
|
||||
String key;
|
||||
String value;
|
||||
private Trie trie;
|
||||
private String key;
|
||||
private String value;
|
||||
|
||||
List<byte[]> shas;
|
||||
List<String> values;
|
||||
private List<byte[]> shas;
|
||||
private List<String> values;
|
||||
|
||||
public TrieIterator(Trie t) {
|
||||
this.trie = t;
|
||||
|
|
|
@ -7,34 +7,31 @@ import java.math.BigInteger;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* User: Roman Mandeleil
|
||||
* Created on: 01/06/2014 19:47
|
||||
* DataWord is the 32-byte array representation of a 256-bit number
|
||||
* Calculations can be done on this word with other DataWords
|
||||
*/
|
||||
|
||||
public class DataWord {
|
||||
|
||||
static DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack
|
||||
|
||||
byte[] data = new byte[32];
|
||||
|
||||
public DataWord(){
|
||||
data = new byte[32];
|
||||
}
|
||||
public DataWord() {
|
||||
data = new byte[32];
|
||||
}
|
||||
|
||||
public DataWord(int num){
|
||||
ByteBuffer bInt = ByteBuffer.allocate(4).putInt(num);
|
||||
ByteBuffer data = ByteBuffer.allocate(32);
|
||||
System.arraycopy(bInt.array(), 0, data.array(), 28, 4);
|
||||
this.data = data.array();
|
||||
}
|
||||
public DataWord(int num) {
|
||||
ByteBuffer bInt = ByteBuffer.allocate(4).putInt(num);
|
||||
ByteBuffer data = ByteBuffer.allocate(32);
|
||||
System.arraycopy(bInt.array(), 0, data.array(), 28, 4);
|
||||
this.data = data.array();
|
||||
}
|
||||
|
||||
public DataWord(byte[] data){
|
||||
if (data == null || data.length > 32)
|
||||
throw new RuntimeException("bad push data: " + data);
|
||||
|
||||
System.arraycopy(data, 0, this.data, 32 - data.length, data.length);
|
||||
}
|
||||
public DataWord(byte[] data) {
|
||||
if (data == null || data.length > 32)
|
||||
throw new RuntimeException("bad push data: " + data);
|
||||
System.arraycopy(data, 0, this.data, 32 - data.length, data.length);
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
|
@ -95,9 +92,20 @@ public class DataWord {
|
|||
}
|
||||
}
|
||||
|
||||
// todo: add can be done in more efficient way
|
||||
// todo without BigInteger quick hack
|
||||
public void add(DataWord word){
|
||||
// By : Holger
|
||||
// From : http://stackoverflow.com/a/24023466/459349
|
||||
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() );
|
||||
byte[] bytes = result.toByteArray();
|
||||
|
@ -106,11 +114,11 @@ public class DataWord {
|
|||
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
|
||||
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 without BigInteger quick hack
|
||||
public void mull(DataWord word){
|
||||
public void mul(DataWord word){
|
||||
|
||||
BigInteger result = value().multiply( word.value() );
|
||||
byte[] bytes = result.toByteArray();
|
||||
|
|
|
@ -55,7 +55,7 @@ public class VM {
|
|||
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
word1.mull(word2);
|
||||
word1.mul(word2);
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
}
|
||||
|
|
|
@ -69,4 +69,4 @@ samples.dir = samples
|
|||
# the existing database will be
|
||||
# destroyed and all the data will be
|
||||
# downloaded from peers again
|
||||
database.reset = true
|
||||
database.reset = false
|
||||
|
|
|
@ -22,7 +22,7 @@ public class BlockTest {
|
|||
// from RLP encoding
|
||||
byte[] genesisBytes = Hex.decode(CPP_PoC5_GENESIS_HEX_RLP_ENCODED);
|
||||
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.getParentHash()), Hex.toHexString(genesisFromRLP.getParentHash()));
|
||||
assertEquals(Hex.toHexString(genesis.getStateRoot()), Hex.toHexString(genesisFromRLP.getStateRoot()));
|
||||
|
@ -48,7 +48,7 @@ public class BlockTest {
|
|||
B32(sha3(B(42)))
|
||||
)
|
||||
*/
|
||||
Block genesis = new Genesis();
|
||||
Block genesis = Genesis.getInstance();
|
||||
assertEquals(CPP_PoC5_GENESIS_HEX_RLP_ENCODED, Hex.toHexString(genesis.getEncoded()));
|
||||
|
||||
// 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.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* User: Roman Mandeleil
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
|
|
Loading…
Reference in New Issue