Merge pull request #21 from nicksavers/master

Impl faster ADD
This commit is contained in:
romanman 2014-06-05 06:34:19 +03:00
commit 734d25bdc0
24 changed files with 292 additions and 231 deletions

View File

@ -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();
}
}

View File

@ -27,7 +27,7 @@ public class AccountState {
*
* Since I typically wish to refer not to the tries 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];

View File

@ -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);
}
}
}
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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));
}
}

View File

@ -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

View File

@ -1,6 +1,5 @@
package org.ethereum.vm;
import org.ethereum.crypto.HashUtil;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;