diff --git a/build-post-package.xml b/build-post-package.xml index 38c7355e..73ab01b3 100644 --- a/build-post-package.xml +++ b/build-post-package.xml @@ -37,6 +37,11 @@ + + + + + diff --git a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java index 7431c47d..49084588 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java @@ -97,6 +97,21 @@ public class SystemProperties { return Boolean.parseBoolean(prop.getProperty("database.reset")); } + public String activePeerIP(){ + if(prop.isEmpty()) return "54.201.28.117"; + return prop.getProperty("peer.active.ip"); + } + + public int activePeerPort(){ + if(prop.isEmpty()) return 30303; + return Integer.parseInt(prop.getProperty("peer.active.port")); + } + + public String samplesDir(){ + if(prop.isEmpty()) return "samples"; + return prop.getProperty("samples.dir"); + } + public String toString() { Enumeration e = prop.propertyNames(); while (e.hasMoreElements()) { diff --git a/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java b/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java new file mode 100644 index 00000000..87cf6329 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java @@ -0,0 +1,92 @@ +package org.ethereum.core; + +import org.ethereum.crypto.ECKey; +import org.ethereum.crypto.HashUtil; +import org.ethereum.util.RLP; +import org.ethereum.util.Utils; + +import java.math.BigInteger; + +public class AccountState { + + private ECKey ecKey; + private byte[] rlpEncoded; + + /* A value equal to the number of transactions sent + * from this address, or, in the case of contract accounts, + * the number of contract-creations made by this account */ + private BigInteger nonce; + + /* A scalar value equal to the number of Wei owned by this address */ + private BigInteger balance; + + /* A 256-bit hash of the root node of a trie structure + * that encodes the storage contents of the contract, + * itself a simple mapping between byte arrays of size 32. + * The hash is formally denoted σ[a] s . + * + * 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 . + * 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]; + + /* The hash of the EVM code of this contract—this is the code + * that gets executed should this address receive a message call; + * it is immutable and thus, unlike all other fields, cannot be changed + * after construction. All such code fragments are contained in + * the state database under their corresponding hashes for later + * retrieval */ + private byte[] codeHash = HashUtil.sha3(new byte[0]); + + public AccountState() { + this(new ECKey(Utils.getRandom())); + } + + public AccountState(ECKey ecKey) { + this(ecKey, BigInteger.ZERO, BigInteger.ZERO); + } + + public AccountState(ECKey ecKey, BigInteger nonce, BigInteger balance) { + this.ecKey = ecKey; + this.nonce = nonce; + this.balance = balance; + } + + public AccountState(BigInteger nonce, BigInteger balance) { + this.nonce = nonce; + this.balance = balance; + } + + public ECKey getEcKey() { + return ecKey; + } + + public BigInteger getNonce() { + return nonce; + } + + public void incrementNonce(){ + this.nonce = nonce.add(BigInteger.ONE); + } + + public BigInteger getBalance() { + return balance; + } + + public void addToBalance(BigInteger value){ + this.balance = balance.add(value); + } + + public byte[] getEncoded() { + if(rlpEncoded == null) { + byte[] nonce = RLP.encodeBigInteger(this.nonce); + byte[] balance = RLP.encodeBigInteger(this.balance); + byte[] stateRoot = RLP.encodeElement(this.stateRoot); + byte[] codeHash = RLP.encodeElement(this.codeHash); + this.rlpEncoded = RLP.encodeList(balance, nonce, stateRoot, codeHash); + } + return rlpEncoded; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/AddressState.java b/ethereumj-core/src/main/java/org/ethereum/core/AddressState.java deleted file mode 100644 index b953b455..00000000 --- a/ethereumj-core/src/main/java/org/ethereum/core/AddressState.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.ethereum.core; - -import org.ethereum.crypto.ECKey; -import org.ethereum.util.Utils; - -import java.math.BigInteger; - -/** - * www.ethereumJ.com - * User: Roman Mandeleil - * Created on: 21/05/2014 10:43 - */ -public class AddressState { - - private ECKey ecKey; - private BigInteger nonce; - private BigInteger balance; - - public AddressState() { - this(new ECKey(Utils.getRandom())); - } - - public AddressState(ECKey ecKey) { - this(ecKey, BigInteger.ZERO, BigInteger.ZERO); - } - - public AddressState(ECKey ecKey, BigInteger nonce, BigInteger balance) { - this.ecKey = ecKey; - this.nonce = nonce; - this.balance = balance; - } - - public ECKey getEcKey() { - return ecKey; - } - - public BigInteger getNonce() { - return nonce; - } - - public void incrementNonce(){ - this.nonce = nonce.add(BigInteger.ONE); - } - - public BigInteger getBalance() { - return balance; - } - - public void addToBalance(BigInteger value){ - this.balance = balance.add(value); - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Block.java b/ethereumj-core/src/main/java/org/ethereum/core/Block.java index f754a732..c44c2e75 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Block.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Block.java @@ -1,6 +1,8 @@ package org.ethereum.core; import org.ethereum.crypto.HashUtil; +import org.ethereum.db.Config; +import org.ethereum.trie.Trie; import org.ethereum.util.ByteUtil; import org.ethereum.util.RLP; import org.ethereum.util.RLPElement; @@ -71,6 +73,7 @@ public class Block { private List transactionsList = new ArrayList(); private List uncleList = new ArrayList(); + private Trie state; public Block(byte[] rawData) { this.rlpEncoded = rawData; @@ -78,14 +81,15 @@ public class Block { } public Block(byte[] parentHash, byte[] unclesHash, byte[] coinbase, - byte[] stateRoot, byte[] txTrieRoot, byte[] difficulty, - long number, long minGasPrice, long gasLimit, long gasUsed, - long timestamp, byte[] extraData, byte[] nonce, - List transactionsList, List uncleList) { + byte[] txTrieRoot, byte[] difficulty, long number, + long minGasPrice, long gasLimit, long gasUsed, long timestamp, + byte[] extraData, byte[] nonce, List transactionsList, + List uncleList) { this.parentHash = parentHash; this.unclesHash = unclesHash; this.coinbase = coinbase; - this.stateRoot = stateRoot; + this.state = new Trie(Config.STATE_DB.getDb()); + this.stateRoot = state.getRootHash(); this.txTrieRoot = txTrieRoot; this.difficulty = difficulty; this.number = number; @@ -104,14 +108,13 @@ public class Block { // difficulty, number, minGasPrice, gasLimit, gasUsed, timestamp, // extradata, nonce] private void parseRLP() { - + RLPList params = (RLPList) RLP.decode2(rlpEncoded); - - this.hash = HashUtil.sha3(rlpEncoded); - RLPList block = (RLPList) params.get(0); - RLPList header = (RLPList) block.get(0); + // Parse Header + RLPList header = (RLPList) block.get(0); + this.parentHash = ((RLPItem) header.get(0)).getRLPData(); this.unclesHash = ((RLPItem) header.get(1)).getRLPData(); this.coinbase = ((RLPItem) header.get(2)).getRLPData(); @@ -129,12 +132,12 @@ public class Block { this.minGasPrice = gpBytes == null ? 0 : (new BigInteger(1, gpBytes)).longValue(); this.gasLimit = glBytes == null ? 0 : (new BigInteger(1, glBytes)).longValue(); this.gasUsed = guBytes == null ? 0 : (new BigInteger(1, guBytes)).longValue(); - this.timestamp = tsBytes == null ? 0 : (new BigInteger(tsBytes)).longValue(); + this.timestamp = tsBytes == null ? 0 : (new BigInteger(1, tsBytes)).longValue(); this.extraData = ((RLPItem) header.get(11)).getRLPData(); this.nonce = ((RLPItem) header.get(12)).getRLPData(); - // parse transactions + // Parse Transactions RLPList transactions = (RLPList) block.get(1); for (RLPElement rlpTx : transactions){ @@ -148,13 +151,14 @@ public class Block { RLPElement txRecipe2 = ((RLPList)rlpTx).get(2); } - // parse uncles + // Parse Uncles RLPList uncleBlocks = (RLPList) block.get(2); for (RLPElement rawUncle : uncleBlocks){ Block blockData = new Block(rawUncle.getRLPData()); this.uncleList.add(blockData); } this.parsed = true; + this.hash = this.getHash(); } public byte[] getHash(){ @@ -184,7 +188,7 @@ public class Block { public byte[] getStateRoot() { if (!parsed) parseRLP(); - return stateRoot; + return this.stateRoot; } public byte[] getTxTrieRoot() { @@ -314,6 +318,11 @@ public class Block { return toStringBuff.toString(); } + public byte[] updateState(byte[] key, byte[] value) { + this.state.update(key, value); + return this.stateRoot = this.state.getRootHash(); + } + /** * This mechanism enforces a homeostasis in terms of the time between blocks; * a smaller period between the last two blocks results in an increase in the diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Genesis.java b/ethereumj-core/src/main/java/org/ethereum/core/Genesis.java index 2ad1dd7b..965c90dd 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Genesis.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Genesis.java @@ -19,8 +19,6 @@ public class Genesis extends Block { public static byte[] PARENT_HASH = zeroHash256; public static byte[] UNCLES_HASH = sha3EmptyList; public static byte[] COINBASE = zeroHash160; - public static byte[] STATE_ROOT = // TODO: Get stateRoot from actual state - Hex.decode("12582945fc5ad12c3e7b67c4fc37a68fc0d52d995bb7f7291ff41a2739a7ca16"); public static byte[] TX_TRIE_ROOT = new byte[0]; public static byte[] DIFFICULTY = BigInteger.valueOf(2).pow(22).toByteArray(); public static long NUMBER = 0; @@ -32,9 +30,28 @@ public class Genesis extends Block { public static byte[] NONCE = HashUtil.sha3(new byte[]{42}); public Genesis() { - super(PARENT_HASH, UNCLES_HASH, COINBASE, STATE_ROOT, - TX_TRIE_ROOT, DIFFICULTY, NUMBER, MIN_GAS_PRICE, GAS_LIMIT, GAS_USED, - TIMESTAMP, EXTRA_DATA, NONCE, null, null); + super(PARENT_HASH, UNCLES_HASH, COINBASE, TX_TRIE_ROOT, DIFFICULTY, + NUMBER, MIN_GAS_PRICE, GAS_LIMIT, GAS_USED, TIMESTAMP, + EXTRA_DATA, NONCE, null, null); + // Premine state + AccountState acct = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200)); + // # (M) + this.updateState(Hex.decode("2ef47100e0787b915105fd5e3f4ff6752079d5cb"), acct.getEncoded()); + // # (A) + this.updateState(Hex.decode("1a26338f0d905e295fccb71fa9ea849ffa12aaf4"), acct.getEncoded()); + // # (J) + this.updateState(Hex.decode("e6716f9544a56c530d868e4bfbacb172315bdead"), acct.getEncoded()); + // # (G) + this.updateState(Hex.decode("8a40bfaa73256b60764c1bf40675a99083efb075"), acct.getEncoded()); + // # (CH) + this.updateState(Hex.decode("e4157b34ea9615cfbde6b4fda419828124b70c78"), acct.getEncoded()); + // # (V) + this.updateState(Hex.decode("1e12515ce3e0f817a4ddef9ca55788a1d66bd2df"), acct.getEncoded()); + // # (HH) + 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())); } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/GoState.java b/ethereumj-core/src/main/java/org/ethereum/core/GoState.java index 5cfc84f3..d6f16e2b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/GoState.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/GoState.java @@ -55,13 +55,13 @@ public class GoState { } public StateObject getContract(byte[] address) { - String data = this.trie.get(new String(address)); - if (data == "") { + byte[] data = this.trie.get(new String(address)); + if (data == null || data.length == 0) { return null; } // build contract - StateObject contract = new StateObject(address, data.getBytes()); + StateObject contract = new StateObject(address, data); // Check if there's a cached state for this contract GoState cachedState = this.states.get(new String(address)); @@ -76,11 +76,11 @@ public class GoState { } public StateObject getAccount(byte[] address) { - String data = this.trie.get(new String(address)); - if (data == "") { + byte[] data = this.trie.get(new String(address)); + if (data == null || data.length == 0) { return StateObject.createAccount(address, BigInteger.ZERO); } else { - return new StateObject(address, data.getBytes()); + return new StateObject(address, data); } } @@ -138,11 +138,11 @@ public class GoState { this.states.put(new String(addr), stateObject.getState()); } - this.trie.update(new String(addr), new String(stateObject.rlpEncode())); + this.trie.update(addr, stateObject.rlpEncode()); } public void put(byte[] key, byte[] object) { - this.trie.update(new String(key), new String(object)); + this.trie.update(key, object); } /** diff --git a/ethereumj-core/src/main/java/org/ethereum/core/StateObject.java b/ethereumj-core/src/main/java/org/ethereum/core/StateObject.java index 751daf82..aa0eca02 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/StateObject.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/StateObject.java @@ -58,11 +58,11 @@ public class StateObject { } public Value getAddress(byte[] address) { - return new Value(this.state.getTrie().get(new String(address)).getBytes()); + return new Value(this.state.getTrie().get(new String(address))); } public void setAddress(byte[] address, Object value) { - this.state.getTrie().update(new String(address), new String(new Value(value).encode())); + this.state.getTrie().update(address, new Value(value).encode()); } public GoState getState() { @@ -89,7 +89,7 @@ public class StateObject { public void setMem(BigInteger num, Value val) { byte[] address = num.toByteArray(); - this.state.getTrie().update(new String(address), new String(val.encode())); + this.state.getTrie().update(address, val.encode()); } // Return the gas back to the origin. Used by the Virtual machine or Closures diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Wallet.java b/ethereumj-core/src/main/java/org/ethereum/core/Wallet.java index f5b3605f..73f7b70f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Wallet.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Wallet.java @@ -34,7 +34,7 @@ public class Wallet { // private HashMap rows = new HashMap<>(); // table for a wallet - private HashMap rows = new HashMap(); + private HashMap rows = new HashMap(); private long high; private List listeners = new ArrayList(); @@ -42,14 +42,14 @@ public class Wallet { private HashMap transactionMap = new HashMap(); public void addNewKey(){ - AddressState addressState = new AddressState(); + AccountState addressState = new AccountState(); String address = Hex.toHexString(addressState.getEcKey().getAddress()); rows.put(address, addressState); for (WalletListener listener : listeners) listener.valueChanged(); } public void importKey(byte[] privKey){ - AddressState addressState = new AddressState(ECKey.fromPrivate(privKey)); + AccountState addressState = new AccountState(ECKey.fromPrivate(privKey)); String address = Hex.toHexString(addressState.getEcKey().getAddress()); rows.put(address, addressState); notifyListeners(); @@ -59,11 +59,11 @@ public class Wallet { this.listeners.add(walletListener); } - public Collection getAddressStateCollection(){ + public Collection getAddressStateCollection(){ return rows.values(); } - public AddressState getAddressState(byte[] addressBytes){ + public AccountState getAddressState(byte[] addressBytes){ String address = Hex.toHexString(addressBytes); return rows.get(address); } @@ -75,7 +75,7 @@ public class Wallet { public BigInteger totalBalance(){ BigInteger sum = BigInteger.ZERO; - for (AddressState addressState : rows.values()){ + for (AccountState addressState : rows.values()){ sum = sum.add(addressState.getBalance()); } return sum; @@ -86,7 +86,7 @@ public class Wallet { transactionMap.put(new BigInteger(transaction.getHash()), transaction ); byte[] senderAddress = transaction.getSender(); - AddressState senderState = rows.get(Hex.toHexString(senderAddress)); + AccountState senderState = rows.get(Hex.toHexString(senderAddress)); if (senderState != null){ BigInteger value = new BigInteger(transaction.getValue()); @@ -95,7 +95,7 @@ public class Wallet { } byte[] receiveAddress = transaction.getReceiveAddress(); - AddressState receiverState = rows.get(Hex.toHexString(receiveAddress)); + AccountState receiverState = rows.get(Hex.toHexString(receiveAddress)); if (receiverState != null){ receiverState.addToBalance(new BigInteger(1, transaction.getValue())); } @@ -214,7 +214,7 @@ public class Wallet { walletElement.setAttributeNode(high); int i = 0; - for (AddressState addressState : getAddressStateCollection()){ + for (AccountState addressState : getAddressStateCollection()){ Element raw = doc.createElement("raw"); Attr id = doc.createAttribute("id"); diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java b/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java index 57df17d5..b1490e58 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java @@ -9,10 +9,7 @@ import javax.swing.table.TableCellRenderer; import java.awt.*; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; +import java.awt.event.*; /** * www.ethereumJ.com @@ -27,7 +24,12 @@ public class BlockChainTable extends JFrame { private int lastFindIndex = 0; - public BlockChainTable() { + ToolBar toolBar; + + public BlockChainTable(ToolBar toolBar) { + + this.toolBar = toolBar; + addCloseAction(); final BlockChainTable blockChainTable = this; @@ -126,8 +128,20 @@ public class BlockChainTable extends JFrame { topPanel.add(scrollPane, BorderLayout.CENTER); } + public void addCloseAction(){ + this.addWindowListener( new WindowAdapter() + { + public void windowClosing(WindowEvent e) + { + toolBar.chainToggle.setSelected(false); + + } + }); + } + + public static void main(String args[]){ - BlockChainTable mainFrame = new BlockChainTable(); + BlockChainTable mainFrame = new BlockChainTable(null); mainFrame.setVisible(true); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/ConnectionConsoleWindow.java b/ethereumj-core/src/main/java/org/ethereum/gui/ConnectionConsoleWindow.java index 5fcecdbb..b2e7fe6d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ConnectionConsoleWindow.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ConnectionConsoleWindow.java @@ -1,16 +1,17 @@ package org.ethereum.gui; import java.awt.*; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; +import javax.swing.*; +import org.ethereum.config.SystemProperties; import org.ethereum.net.client.ClientPeer; import org.fife.ui.rsyntaxtextarea.*; import org.fife.ui.rtextarea.RTextScrollPane; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A simple example showing how to modify the fonts and colors used in an @@ -25,12 +26,17 @@ import org.fife.ui.rtextarea.RTextScrollPane; */ public class ConnectionConsoleWindow extends JFrame implements PeerListener{ + Logger logger = LoggerFactory.getLogger(getClass()); + + private static final long serialVersionUID = 1L; private boolean autoScroll = false; private RSyntaxTextArea textArea; + ToolBar toolBar = null; + /** * ERROR (exceptions) WARN (when something happens that's not supposed to) * INFO (wire output) @@ -38,13 +44,15 @@ public class ConnectionConsoleWindow extends JFrame implements PeerListener{ * TRACE (start/end method) */ - public ConnectionConsoleWindow() { + public ConnectionConsoleWindow(ToolBar toolBar) { final ConnectionConsoleWindow thisConsole = this; + this.toolBar = toolBar; java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png"); Toolkit kit = Toolkit.getDefaultToolkit(); Image img = kit.createImage(url); this.setIconImage(img); + addCloseAction(); JPanel cp = new JPanel(new BorderLayout()); @@ -68,36 +76,14 @@ public class ConnectionConsoleWindow extends JFrame implements PeerListener{ pack(); setLocation(775, 390); - this.addComponentListener(new ComponentAdapter() { - - @Override - public void componentShown(ComponentEvent e) { - Thread t = new Thread() { + Thread t = new Thread() { public void run() { - // Peer Server Zero: peer discovery -// new ClientPeer(thisConsole).connect("54.201.28.117", 30303); - - // Peer Server One: peer discovery -// new ClientPeer(thisConsole).connect("54.204.10.41", 30303); - - // Some dude in Canada -// new ClientPeer(thisConsole).connect("131.104.247.135", 30303); - - // Nick -// new ClientPeer(thisConsole).connect("82.217.72.169", 30303); - - // c++: ZeroGox - new ClientPeer(thisConsole).connect("54.204.10.41", 30303); - - // RomanJ -// new ClientPeer(thisConsole).connect("54.211.14.10", 40404); - + new ClientPeer(thisConsole).connect(SystemProperties.CONFIG.activePeerIP(), + SystemProperties.CONFIG.activePeerPort()); } - }; - t.start(); - } - }); + }; + t.start(); } @Override @@ -149,11 +135,23 @@ public class ConnectionConsoleWindow extends JFrame implements PeerListener{ } } + public void addCloseAction(){ + this.addWindowListener( new WindowAdapter() + { + public void windowClosing(WindowEvent e) + { + toolBar.logToggle.setSelected(false); + + } + }); + + } + public static void main(String[] args) { // Start all Swing applications on the EDT. SwingUtilities.invokeLater(new Runnable() { public void run() { - new ConnectionConsoleWindow().setVisible(true); + new ConnectionConsoleWindow(null).setVisible(true); } }); } diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java b/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java index a589a9dd..1d5a6c14 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java @@ -1,6 +1,6 @@ package org.ethereum.gui; -import org.ethereum.core.AddressState; +import org.ethereum.core.AccountState; import org.ethereum.core.Transaction; import org.ethereum.manager.MainData; import org.ethereum.net.client.ClientPeer; @@ -135,10 +135,10 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{ JComponent editor = (JComponent)(creatorAddressCombo.getEditor().getEditorComponent()); editor.setForeground(Color.RED); - Collection addressStates = + Collection addressStates = MainData.instance.getWallet().getAddressStateCollection(); - for (AddressState addressState : addressStates){ + for (AccountState addressState : addressStates){ creatorAddressCombo.addItem(new AddressStateWraper(addressState)); } @@ -229,7 +229,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{ byte[] contractAddress = Hex.decode( contractAddrInput.getText()); - AddressState addressState = ((AddressStateWraper)creatorAddressCombo.getSelectedItem()).getAddressState(); + AccountState addressState = ((AddressStateWraper)creatorAddressCombo.getSelectedItem()).getAddressState(); byte[] senderPrivKey = addressState.getEcKey().getPrivKeyBytes(); byte[] nonce = addressState.getNonce() == BigInteger.ZERO ? null : addressState.getNonce().toByteArray(); @@ -271,13 +271,13 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{ public class AddressStateWraper { - private AddressState addressState; + private AccountState addressState; - public AddressStateWraper(AddressState addressState) { + public AddressStateWraper(AccountState addressState) { this.addressState = addressState; } - public AddressState getAddressState() { + public AccountState getAddressState() { return addressState; } diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java b/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java index 5bf2c4a9..e4faaddb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java @@ -1,6 +1,6 @@ package org.ethereum.gui; -import org.ethereum.core.AddressState; +import org.ethereum.core.AccountState; import org.ethereum.core.Transaction; import org.ethereum.manager.MainData; import org.ethereum.net.client.ClientPeer; @@ -143,10 +143,10 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{ JComponent editor = (JComponent)(creatorAddressCombo.getEditor().getEditorComponent()); editor.setForeground(Color.RED); - Collection addressStates = + Collection addressStates = MainData.instance.getWallet().getAddressStateCollection(); - for (AddressState addressState : addressStates){ + for (AccountState addressState : addressStates){ creatorAddressCombo.addItem(new AddressStateWraper(addressState)); } @@ -234,7 +234,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{ public void submitContract(){ - AddressState addressState = ((AddressStateWraper)creatorAddressCombo.getSelectedItem()).getAddressState(); + AccountState addressState = ((AddressStateWraper)creatorAddressCombo.getSelectedItem()).getAddressState(); byte[] senderPrivKey = addressState.getEcKey().getPrivKeyBytes(); byte[] nonce = addressState.getNonce() == BigInteger.ZERO ? null : addressState.getNonce().toByteArray(); @@ -276,7 +276,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{ public static void main(String args[]) { - AddressState as = new AddressState(); + AccountState as = new AccountState(); ContractSubmitDialog pod = new ContractSubmitDialog(null, null); pod.setVisible(true); @@ -284,13 +284,13 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{ public class AddressStateWraper{ - private AddressState addressState; + private AccountState addressState; - public AddressStateWraper(AddressState addressState) { + public AddressStateWraper(AccountState addressState) { this.addressState = addressState; } - public AddressState getAddressState() { + public AccountState getAddressState() { return addressState; } diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java b/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java index 1cb498e9..a922cef9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java @@ -1,6 +1,6 @@ package org.ethereum.gui; -import org.ethereum.core.AddressState; +import org.ethereum.core.AccountState; import org.ethereum.core.Transaction; import org.ethereum.manager.MainData; import org.ethereum.net.client.ClientPeer; @@ -26,14 +26,14 @@ class PayOutDialog extends JDialog implements MessageAwareDialog{ PayOutDialog dialog; - AddressState addressState = null; + AccountState addressState = null; JLabel statusMsg = null; final JTextField receiverInput; final JTextField amountInput; final JTextField feeInput; - public PayOutDialog(Frame parent, final AddressState addressState) { + public PayOutDialog(Frame parent, final AccountState addressState) { super(parent, "Payout details: ", false); dialog = this; @@ -260,7 +260,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog{ } public static void main(String args[]) { - AddressState as = new AddressState(); + AccountState as = new AccountState(); PayOutDialog pod = new PayOutDialog(null, as); pod.setVisible(true); } diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/PeersTableWindow.java b/ethereumj-core/src/main/java/org/ethereum/gui/PeersTableWindow.java index b08d7424..5edc8868 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/PeersTableWindow.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/PeersTableWindow.java @@ -3,15 +3,12 @@ package org.ethereum.gui; import org.ethereum.manager.MainData; import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.util.Timer; import java.util.TimerTask; -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.ListSelectionModel; -import javax.swing.SwingConstants; +import javax.swing.*; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellRenderer; @@ -30,9 +27,13 @@ public class PeersTableWindow extends JFrame{ private JScrollPane scrollPane; private Timer updater = new Timer(); + private ToolBar toolBar; // Constructor of main frame - public PeersTableWindow() { + public PeersTableWindow(ToolBar toolBar) { + + this.toolBar = toolBar; + addCloseAction(); // Set the frame characteristics setTitle("Ethereum Peers"); @@ -96,9 +97,21 @@ public class PeersTableWindow extends JFrame{ MainData.instance.startPeerDiscovery(); } + public void addCloseAction(){ + this.addWindowListener( new WindowAdapter() + { + public void windowClosing(WindowEvent e) + { + toolBar.peersToggle.setSelected(false); + + } + }); + } + + public static void main(String args[]) { - PeersTableWindow mainFrame = new PeersTableWindow(); + PeersTableWindow mainFrame = new PeersTableWindow(null); mainFrame.setVisible(true); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/SerpentEditor.java b/ethereumj-core/src/main/java/org/ethereum/gui/SerpentEditor.java index 098b0789..84ea19c0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/SerpentEditor.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/SerpentEditor.java @@ -6,13 +6,14 @@ import org.fife.ui.rtextarea.RTextScrollPane; import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; +import java.awt.event.*; +import java.io.*; +import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static org.ethereum.config.SystemProperties.CONFIG; + /** * www.ethereumJ.com * User: Roman Mandeleil @@ -46,7 +47,7 @@ public class SerpentEditor extends JFrame { "\n" + "return(0)\n"; - private String codeSample3 = "\n" + + private String defaultCode = "\n" + "\n" + "init: \n" + "\n" + @@ -69,9 +70,14 @@ public class SerpentEditor extends JFrame { final JSplitPane splitPanel; final JTextArea result; final JPanel contentPane; + JFileChooser fileChooser = null; - public SerpentEditor() { + ToolBar toolBar = null; + public SerpentEditor(ToolBar toolBar) { + + this.toolBar = toolBar; + addCloseAction(); contentPane = new JPanel(new BorderLayout()); final JFrame mainWindow = this; @@ -88,7 +94,7 @@ public class SerpentEditor extends JFrame { codeArea.setSyntaxEditingStyle("text/serpent"); codeArea.setCodeFoldingEnabled(true); codeArea.setAntiAliasingEnabled(true); - codeArea.setText(codeSample3); + codeArea.setText(defaultCode); changeStyleProgrammatically(); @@ -103,6 +109,7 @@ public class SerpentEditor extends JFrame { splitPanel.setContinuousLayout(true); + contentPane.add(splitPanel, BorderLayout.CENTER); splitPanel.add(sp); @@ -123,6 +130,7 @@ public class SerpentEditor extends JFrame { contentPane.add(controlsPanel, BorderLayout.SOUTH); + createToolBar(); setContentPane(contentPane); @@ -130,6 +138,8 @@ public class SerpentEditor extends JFrame { pack(); + this.revalidate(); + this.repaint(); } @@ -187,19 +197,20 @@ public class SerpentEditor extends JFrame { } catch (Throwable th) { th.printStackTrace(); - splitPanel.setDividerLocation(0.7); + splitPanel.setDividerLocation(0.8); result.setVisible(true); result.setText(th.getMessage()); result.setForeground(Color.RED); return ; - } result.setForeground(Color.BLACK.brighter()); result.setVisible(true); result.setText(asmResult); - splitPanel.setDividerLocation(0.7); + splitPanel.setDividerLocation( + 1 - result.getPreferredSize().getHeight() / codeArea.getPreferredSize().getHeight()); + this.repaint(); } @@ -245,10 +256,7 @@ public class SerpentEditor extends JFrame { toolbar.setFloatable(false); final JPanel mainContentPane = SerpentEditor.this.contentPane; - - { - java.net.URL url = ClassLoader.getSystemResource("buttons/open-file.png"); Toolkit kit = Toolkit.getDefaultToolkit(); Image img = kit.createImage(url); @@ -273,7 +281,21 @@ public class SerpentEditor extends JFrame { new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - System.out.println("open file"); + + File file = callFileChooser(); + try { + if (file == null) return; + String content = new Scanner(file).useDelimiter("\\Z").next(); + codeArea.setText(content); + + } catch (FileNotFoundException e1) { + + e1.printStackTrace(); + } catch (java.util.NoSuchElementException e2){ + + // don't worry it's just the file is empty + codeArea.setText(""); + } } } ); @@ -306,7 +328,24 @@ public class SerpentEditor extends JFrame { new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - System.out.println("save file"); + + File file = null; + if (fileChooser == null || fileChooser.getSelectedFile() == null) { + file = callFileChooser(); + if (fileChooser.getSelectedFile() == null) + return; + } + else{ + file = fileChooser.getSelectedFile(); + } + + try { + BufferedWriter out = new BufferedWriter(new FileWriter(file), 32768); + out.write(codeArea.getText()); + out.close(); + } catch (IOException e1) { + e1.printStackTrace(); + } } } ); @@ -431,11 +470,44 @@ public class SerpentEditor extends JFrame { this.contentPane.add(toolbar, BorderLayout.EAST); } + + protected File callFileChooser(){ + + File file = null; + + if (fileChooser == null) { + fileChooser = new JFileChooser(CONFIG.samplesDir()); + fileChooser.setMultiSelectionEnabled(false); + } + + switch (fileChooser.showOpenDialog(SerpentEditor.this)) + { + case JFileChooser.APPROVE_OPTION: + + file = fileChooser.getSelectedFile(); + break; + } + + return file; + } + + public void addCloseAction(){ + this.addWindowListener( new WindowAdapter() + { + public void windowClosing(WindowEvent e) + { + toolBar.editorToggle.setSelected(false); + + } + }); + } + + public static void main(String[] args) { // Start all Swing applications on the EDT. SwingUtilities.invokeLater(new Runnable() { public void run() { - new SerpentEditor().setVisible(true); + new SerpentEditor(null).setVisible(true); } }); } diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java b/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java index 6ec06742..c8719ad0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java @@ -18,7 +18,6 @@ import java.awt.event.ItemListener; */ public class ToolBar extends JFrame { - Logger logger = LoggerFactory.getLogger(getClass()); Logger introLogger = LoggerFactory.getLogger("Intro"); @@ -28,6 +27,13 @@ public class ToolBar extends JFrame { WalletWindow walletWindow = null; SerpentEditor serpentEditor = null; + JToggleButton editorToggle; + JToggleButton logToggle; + JToggleButton peersToggle; + JToggleButton chainToggle; + JToggleButton walletToggle; + + public ToolBar() throws HeadlessException { introLogger.info(""); @@ -80,7 +86,7 @@ public class ToolBar extends JFrame { ImageIcon image_5 = new ImageIcon(imageURL_5); - JToggleButton editorToggle = new JToggleButton(""); + editorToggle = new JToggleButton(""); editorToggle.setIcon(image_1); editorToggle.setContentAreaFilled(true); editorToggle.setToolTipText("Serpent Editor"); @@ -88,24 +94,24 @@ public class ToolBar extends JFrame { editorToggle.setBorderPainted(false); editorToggle.setFocusPainted(false); editorToggle.setCursor(new Cursor(Cursor.HAND_CURSOR)); - editorToggle.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - if (serpentEditor == null) - serpentEditor = new SerpentEditor(); - serpentEditor.setVisible(true); - } - }); - } else if (e.getStateChange() == ItemEvent.DESELECTED) { - serpentEditor.setVisible(false); - } - } - }); + editorToggle.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED){ + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (serpentEditor == null) + serpentEditor = new SerpentEditor(ToolBar.this); + serpentEditor.setVisible(true); + } + }); + } else if (e.getStateChange() == ItemEvent.DESELECTED) { + serpentEditor.setVisible(false); + } + } + }); - JToggleButton logToggle = new JToggleButton(); + logToggle = new JToggleButton(); logToggle.setIcon(image_2); logToggle.setToolTipText("Log Console"); logToggle.setContentAreaFilled(true); @@ -113,25 +119,25 @@ public class ToolBar extends JFrame { logToggle.setBorderPainted(false); logToggle.setFocusPainted(false); logToggle.setCursor(new Cursor(Cursor.HAND_CURSOR)); - logToggle.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { + logToggle.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - if (connectionConsoleWindow == null) - connectionConsoleWindow = new ConnectionConsoleWindow(); - connectionConsoleWindow.setVisible(true); - } - }); - } else if (e.getStateChange() == ItemEvent.DESELECTED) { - connectionConsoleWindow.setVisible(false); - } - } - }); + if (e.getStateChange() == ItemEvent.SELECTED){ + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (connectionConsoleWindow == null) + connectionConsoleWindow = new ConnectionConsoleWindow(ToolBar.this); + connectionConsoleWindow.setVisible(true); + } + }); + } else if (e.getStateChange() == ItemEvent.DESELECTED) { + connectionConsoleWindow.setVisible(false); + } + } + }); - JToggleButton peersToggle = new JToggleButton(); + peersToggle = new JToggleButton(); peersToggle.setIcon(image_3); peersToggle.setToolTipText("Peers"); peersToggle.setContentAreaFilled(true); @@ -146,7 +152,7 @@ public class ToolBar extends JFrame { SwingUtilities.invokeLater(new Runnable() { public void run() { if (mainFrame == null) - mainFrame = new PeersTableWindow(); + mainFrame = new PeersTableWindow(ToolBar.this); mainFrame.setVisible( true ); } }); @@ -156,7 +162,7 @@ public class ToolBar extends JFrame { } }); - JToggleButton chainToggle = new JToggleButton(); + chainToggle = new JToggleButton(); chainToggle.setIcon(image_4); chainToggle.setToolTipText("Block Chain"); chainToggle.setContentAreaFilled(true); @@ -164,25 +170,25 @@ public class ToolBar extends JFrame { chainToggle.setBorderPainted(false); chainToggle.setFocusPainted(false); chainToggle.setCursor(new Cursor(Cursor.HAND_CURSOR)); - chainToggle.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { + chainToggle.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED){ + SwingUtilities.invokeLater(new Runnable() { + public void run() { - if (blockChainWindow == null) - blockChainWindow = new BlockChainTable(); - blockChainWindow.setVisible(true); - } - }); - } else if (e.getStateChange() == ItemEvent.DESELECTED) { - blockChainWindow.setVisible(false); - } - } - }); + if (blockChainWindow == null) + blockChainWindow = new BlockChainTable(ToolBar.this); + blockChainWindow.setVisible(true); + } + }); + } else if (e.getStateChange() == ItemEvent.DESELECTED) { + blockChainWindow.setVisible(false); + } + } + }); - JToggleButton walletToggle = new JToggleButton(); + walletToggle = new JToggleButton(); walletToggle.setIcon(image_5); walletToggle.setToolTipText("Wallet"); walletToggle.setContentAreaFilled(true); @@ -190,23 +196,26 @@ public class ToolBar extends JFrame { walletToggle.setBorderPainted(false); walletToggle.setFocusPainted(false); walletToggle.setCursor(new Cursor(Cursor.HAND_CURSOR)); - walletToggle.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - if (walletWindow == null) - walletWindow = new WalletWindow(); - walletWindow.setVisible(true); - } - }); - } else if (e.getStateChange() == ItemEvent.DESELECTED) { - walletWindow.setVisible(false); - } + walletToggle.addItemListener( + new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED){ + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (walletWindow == null) + walletWindow = new WalletWindow(ToolBar.this); + walletWindow.setVisible(true); + } + }); + } else if (e.getStateChange() == ItemEvent.DESELECTED) { + walletWindow.setVisible(false); + } + + } + } + ); - } - }); cp.add(editorToggle); cp.add(logToggle); cp.add(peersToggle); @@ -223,4 +232,4 @@ public class ToolBar extends JFrame { } }); } -} +} \ No newline at end of file diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/WalletAddressPanel.java b/ethereumj-core/src/main/java/org/ethereum/gui/WalletAddressPanel.java index 50c671ba..c4275f4f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/WalletAddressPanel.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/WalletAddressPanel.java @@ -1,6 +1,6 @@ package org.ethereum.gui; -import org.ethereum.core.AddressState; +import org.ethereum.core.AccountState; import org.ethereum.util.Utils; import org.spongycastle.util.encoders.Hex; @@ -21,7 +21,7 @@ import java.net.URL; */ public class WalletAddressPanel extends JPanel{ - public WalletAddressPanel(final AddressState addressState) { + public WalletAddressPanel(final AccountState addressState) { final WalletAddressPanel walletAddressPanel = this; diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/WalletSumPanel.java b/ethereumj-core/src/main/java/org/ethereum/gui/WalletSumPanel.java index 1fb255f6..2ba4b877 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/WalletSumPanel.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/WalletSumPanel.java @@ -53,7 +53,7 @@ public class WalletSumPanel extends JPanel{ payOutLabel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - System.out.println("boom"); + JOptionPane.showMessageDialog(null, "Under construction"); } }); diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/WalletWindow.java b/ethereumj-core/src/main/java/org/ethereum/gui/WalletWindow.java index 5499478e..071e33d4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/WalletWindow.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/WalletWindow.java @@ -1,6 +1,6 @@ package org.ethereum.gui; -import org.ethereum.core.AddressState; +import org.ethereum.core.AccountState; import org.ethereum.core.Wallet; import org.ethereum.manager.MainData; @@ -9,6 +9,8 @@ import javax.swing.*; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.net.URL; /** @@ -19,8 +21,12 @@ import java.net.URL; public class WalletWindow extends JFrame implements Wallet.WalletListener{ WalletWindow walletWindow; + ToolBar toolBar; - public WalletWindow() { + public WalletWindow(ToolBar toolBar) { + + addCloseAction(); + this.toolBar = toolBar; walletWindow = this; java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png"); @@ -50,7 +56,7 @@ public class WalletWindow extends JFrame implements Wallet.WalletListener{ Wallet wallet = MainData.instance.getWallet(); - for (AddressState addressState : wallet.getAddressStateCollection()){ + for (AccountState addressState : wallet.getAddressStateCollection()){ WalletAddressPanel rowPanel = new WalletAddressPanel(addressState); @@ -92,6 +98,18 @@ public class WalletWindow extends JFrame implements Wallet.WalletListener{ contentPane.repaint(); } + public void addCloseAction(){ + this.addWindowListener( new WindowAdapter() + { + public void windowClosing(WindowEvent e) + { + toolBar.walletToggle.setSelected(false); + + } + }); + } + + @Override public void valueChanged() { loadWallet(); diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/MainData.java b/ethereumj-core/src/main/java/org/ethereum/manager/MainData.java index 8ded8051..95f1d085 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/MainData.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/MainData.java @@ -7,17 +7,13 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import org.ethereum.core.AddressState; +import org.ethereum.core.AccountState; import org.ethereum.core.Blockchain; -import org.ethereum.core.Transaction; import org.ethereum.core.Wallet; import org.ethereum.crypto.ECKey; import org.ethereum.crypto.HashUtil; -import org.ethereum.db.Config; import org.ethereum.db.IpGeoDB; import org.ethereum.net.client.ClientPeer; import org.ethereum.net.client.PeerData; @@ -51,7 +47,7 @@ public class MainData { ECKey key = ECKey.fromPrivate(cowAddr); wallet.importKey(cowAddr); - AddressState state = wallet.getAddressState(key.getAddress()); + AccountState state = wallet.getAddressState(key.getAddress()); state.addToBalance(BigInteger.valueOf(2).pow(200)); // 1606938044258990275541962092341162602522202993782792835301376 wallet.importKey(HashUtil.sha3("cat".getBytes())); diff --git a/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java b/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java index 8459ad07..e511994c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java +++ b/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java @@ -19,6 +19,12 @@ public class Cache { nodes = new HashMap(); } + /** + * Put the node in the cache if RLP encoded value is longer than 32 bytes + * + * @param o the Node which could be a pair-, multi-item Node or single Value + * @return sha3 hash of RLP encoded node if length > 32 otherwise return node itself + */ public Object put(Object o) { Value value = new Value(o); byte[] enc = value.encode(); diff --git a/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java b/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java index debad971..cce04fd6 100644 --- a/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java +++ b/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java @@ -9,7 +9,6 @@ import java.util.Arrays; import org.ethereum.crypto.HashUtil; import org.ethereum.util.Value; import org.iq80.leveldb.DB; -import org.spongycastle.util.encoders.Hex; /** * The modified Merkle Patricia tree (trie) provides a persistent data structure @@ -82,10 +81,20 @@ public class Trie { * @param value */ public void update(String key, String value) { + this.update(key.getBytes(), value.getBytes()); + } + + /** + * Insert key/value pair into trie + * + * @param key + * @param value + */ + public void update(byte[] key, byte[] value) { if (key == null) throw new NullPointerException("Key should not be blank"); - byte[] k = binToNibbles(key.getBytes()); - this.root = this.insertOrDelete(this.root, k, value.getBytes()); + byte[] k = binToNibbles(key); + this.root = this.insertOrDelete(this.root, k, value); } /** @@ -94,10 +103,10 @@ public class Trie { * @param key * @return value */ - public String get(String key) { + public byte[] get(String key) { byte[] k = binToNibbles(key.getBytes()); Value c = new Value( this.get(this.root, k) ); - return c.asString(); + return c.asBytes(); } /** @@ -106,7 +115,7 @@ public class Trie { * @param key */ public void delete(String key) { - this.update(key, ""); + this.update(key.getBytes(), "".getBytes()); } /**************************************** @@ -322,7 +331,7 @@ public class Trie { // Simple compare function which compared the tries based on their stateRoot public boolean cmp(Trie trie) { - return this.getRootHash().equals(trie.getRootHash()); + return Arrays.equals(this.getRootHash(), trie.getRootHash()); } // Save the cached value to the database. @@ -368,19 +377,18 @@ public class Trie { return slice; } - public String getRootHash() { + public byte[] getRootHash() { Object root = this.getRoot(); if (root == null || (root instanceof byte[] && ((byte[]) root).length == 0) || (root instanceof String && "".equals((String) root))) { - return ""; + return new byte[0]; } else if (root instanceof byte[]) { - return Hex.toHexString((byte[])this.getRoot()); + return (byte[]) this.getRoot(); } else { Value rootValue = new Value(this.getRoot()); byte[] val = rootValue.encode(); - byte[] key = HashUtil.sha3(val); - return Hex.toHexString(key); + return HashUtil.sha3(val); } } } diff --git a/ethereumj-core/src/main/java/org/ethereum/util/RLP.java b/ethereumj-core/src/main/java/org/ethereum/util/RLP.java index c119fac3..48562cc1 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/RLP.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/RLP.java @@ -9,6 +9,7 @@ import java.util.Queue; import static java.util.Arrays.copyOfRange; import static org.ethereum.util.ByteUtil.byteArrayToInt; import static org.spongycastle.util.Arrays.concatenate; +import static org.spongycastle.util.BigIntegers.asUnsignedByteArray; import java.util.List; @@ -233,7 +234,7 @@ public class RLP { } byte[] valueBytes = new byte[length]; System.arraycopy(data, index, valueBytes, 0, length); - value = new BigInteger(valueBytes); + value = new BigInteger(1, valueBytes); return value; } @@ -783,7 +784,7 @@ public class RLP { if(srcBigInteger == BigInteger.ZERO) return encodeByte((byte)0); else - return encodeElement(srcBigInteger.toByteArray()); + return encodeElement(asUnsignedByteArray(srcBigInteger)); } public static byte[] encodeElement(byte[] srcData) { @@ -878,13 +879,13 @@ public class RLP { return inputString.getBytes(); } else if(input instanceof Long) { Long inputLong = (Long) input; - return (inputLong == 0) ? new byte[0] : BigInteger.valueOf(inputLong).toByteArray(); + return (inputLong == 0) ? new byte[0] : asUnsignedByteArray(BigInteger.valueOf(inputLong)); } else if(input instanceof Integer) { Integer inputInt = (Integer) input; - return (inputInt == 0) ? new byte[0] : BigInteger.valueOf(inputInt.longValue()).toByteArray(); + return (inputInt == 0) ? new byte[0] : asUnsignedByteArray(BigInteger.valueOf(inputInt.intValue())); } else if(input instanceof BigInteger) { BigInteger inputBigInt = (BigInteger) input; - return (inputBigInt == BigInteger.ZERO) ? new byte[0] : inputBigInt.toByteArray(); + return (inputBigInt == BigInteger.ZERO) ? new byte[0] : asUnsignedByteArray(inputBigInt); } else if (input instanceof Value) { Value val = (Value) input; return toBytes(val.asObj()); diff --git a/ethereumj-core/src/main/java/org/ethereum/util/Value.java b/ethereumj-core/src/main/java/org/ethereum/util/Value.java index 9cb30af5..083f3e42 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/Value.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/Value.java @@ -44,7 +44,7 @@ public class Value { if (isInt()) { return (Integer) value; } else if (isBytes()) { - return new BigInteger(asBytes()).intValue(); + return new BigInteger(1, asBytes()).intValue(); } return 0; } @@ -53,7 +53,7 @@ public class Value { if (isLong()) { return (Long) value; } else if (isBytes()) { - return new BigInteger(asBytes()).longValue(); + return new BigInteger(1, asBytes()).longValue(); } return 0; } diff --git a/ethereumj-core/src/main/resources/log4j.properties b/ethereumj-core/src/main/resources/log4j.properties index 1118f65b..a6766f51 100644 --- a/ethereumj-core/src/main/resources/log4j.properties +++ b/ethereumj-core/src/main/resources/log4j.properties @@ -8,4 +8,6 @@ log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern= %d{HH:mm:ss} [%c{1}] %m%n # filter noisy classes -log4j.logger.org.ethereum.net.peerdiscovery = WARN \ No newline at end of file +log4j.logger.org.ethereum.net.peerdiscovery = WARN +log4j.logger.java.nio = WARN +log4j.logger.io.netty = WARN \ No newline at end of file diff --git a/ethereumj-core/src/main/resources/system.properties b/ethereumj-core/src/main/resources/system.properties index 88496c78..5a1cfe3b 100644 --- a/ethereumj-core/src/main/resources/system.properties +++ b/ethereumj-core/src/main/resources/system.properties @@ -7,6 +7,39 @@ server.acceptConnections = false peer.discovery.ip = 54.201.28.117 peer.discovery.port = 30303 +# Peer Server Zero: peer discovery +#peer.discovery.ip = 54.201.28.117 +#peer.discovery.port = 30303 + +# Peer Server One: peer discovery +#peer.discovery.ip = 54.204.10.41 +#peer.discovery.port = 30303 + +# Some dude in Canada +#peer.discovery.ip = 131.104.247.135 +#peer.discovery.port = 30303 + +# Nick +#peer.discovery.ip = 82.217.72.169 +#peer.discovery.port = 30303 + +# ZeroGox +#peer.discovery.ip = 54.204.10.41 +#peer.discovery.port = 30303 + +# RomanJ +# peer.discovery.ip = 54.211.14.10 +# peer.discovery.port = 40404 + + + +# active peer ip and port +# that is the peer through +# we get the chain: [54.201.28.117] port: [30303] +peer.active.ip = 151.64.223.120 +peer.active.port = 30304 + + # specify if the mechanism # to discover more and more # peers and check the already @@ -33,10 +66,22 @@ peer.discovery.timeout = 2 # retrieved from the peer [seconds] transaction.approve.timeout = 5 +<<<<<<< HEAD +======= +# default directory where we keep +# basic Serpent samples relative +# to home.dir +samples.dir = samples + +>>>>>>> merge # everytime the application starts # the existing database will be # destroyed and all the data will be # downloaded from peers again +<<<<<<< HEAD database.reset = true +======= +database.reset = true +>>>>>>> merge diff --git a/ethereumj-core/src/test/java/org/ethereum/core/AccountStateTest.java b/ethereumj-core/src/test/java/org/ethereum/core/AccountStateTest.java new file mode 100644 index 00000000..52b5aa97 --- /dev/null +++ b/ethereumj-core/src/test/java/org/ethereum/core/AccountStateTest.java @@ -0,0 +1,19 @@ +package org.ethereum.core; + +import static org.junit.Assert.*; + +import java.math.BigInteger; + +import org.junit.Test; +import org.spongycastle.util.encoders.Hex; + +public class AccountStateTest { + + @Test + public void testGetEncoded() { + String expected = "f83e9a01000000000000000000000000000000000000000000000000008080a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"; + AccountState acct = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200)); + assertEquals(expected, Hex.toHexString(acct.getEncoded())); + } + +} diff --git a/ethereumj-core/src/test/java/org/ethereum/core/StateTest.java b/ethereumj-core/src/test/java/org/ethereum/core/StateTest.java new file mode 100644 index 00000000..ff785cdd --- /dev/null +++ b/ethereumj-core/src/test/java/org/ethereum/core/StateTest.java @@ -0,0 +1,53 @@ +package org.ethereum.core; + +import static org.junit.Assert.*; + +import java.math.BigInteger; + +import org.ethereum.trie.MockDB; +import org.ethereum.trie.Trie; +import org.junit.Test; +import org.spongycastle.util.encoders.Hex; + +public class StateTest { + + @Test + public void testGenesisAccounts() { + Trie trie = new Trie(new MockDB()); + + // 2ef47100e0787b915105fd5e3f4ff6752079d5cb # (M) + AccountState acct5 = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200)); + trie.update(Hex.decode("2ef47100e0787b915105fd5e3f4ff6752079d5cb"), acct5.getEncoded()); + + // 1a26338f0d905e295fccb71fa9ea849ffa12aaf4 # (A) + AccountState acct4 = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200)); + trie.update(Hex.decode("1a26338f0d905e295fccb71fa9ea849ffa12aaf4"), acct4.getEncoded()); + + // e6716f9544a56c530d868e4bfbacb172315bdead # (J) + AccountState acct2 = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200)); + trie.update(Hex.decode("e6716f9544a56c530d868e4bfbacb172315bdead"), acct2.getEncoded()); + + // 8a40bfaa73256b60764c1bf40675a99083efb075 # (G) + AccountState acct1 = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200)); + trie.update(Hex.decode("8a40bfaa73256b60764c1bf40675a99083efb075"), acct1.getEncoded()); + + // e4157b34ea9615cfbde6b4fda419828124b70c78 # (CH) + AccountState acct8 = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200)); + trie.update(Hex.decode("e4157b34ea9615cfbde6b4fda419828124b70c78"), acct8.getEncoded()); + + // 1e12515ce3e0f817a4ddef9ca55788a1d66bd2df # (V) + AccountState acct3 = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200)); + trie.update(Hex.decode("1e12515ce3e0f817a4ddef9ca55788a1d66bd2df"), acct3.getEncoded()); + + // 6c386a4b26f73c802f34673f7248bb118f97424a # (HH) + AccountState acct7 = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200)); + trie.update(Hex.decode("6c386a4b26f73c802f34673f7248bb118f97424a"), acct7.getEncoded()); + + // cd2a3d9f938e13cd947ec05abc7fe734df8dd826 # (R) + AccountState acct6 = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200)); + trie.update(Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826"), acct6.getEncoded()); + + assertEquals("12582945fc5ad12c3e7b67c4fc37a68fc0d52d995bb7f7291ff41a2739a7ca16", Hex.toHexString(trie.getRootHash())); + } + +} diff --git a/ethereumj-core/src/test/java/org/ethereum/core/WalletTest.java b/ethereumj-core/src/test/java/org/ethereum/core/WalletTest.java index a86fc66a..b926261f 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/WalletTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/WalletTest.java @@ -29,8 +29,8 @@ public class WalletTest { wallet.importKey(catKey.getPrivKeyBytes()); - AddressState cowAddressState = (AddressState) wallet.getAddressState(cowKey.getAddress()); - AddressState catAddressState = (AddressState) wallet.getAddressState(catKey.getAddress()); + AccountState cowAddressState = (AccountState) wallet.getAddressState(cowKey.getAddress()); + AccountState catAddressState = (AccountState) wallet.getAddressState(catKey.getAddress()); cowAddressState.addToBalance(new BigInteger("234234")); catAddressState.addToBalance(new BigInteger("84758")); diff --git a/ethereumj-core/src/test/java/org/ethereum/crypto/CryptoTest.java b/ethereumj-core/src/test/java/org/ethereum/crypto/CryptoTest.java index 6c4463b1..4937a338 100644 --- a/ethereumj-core/src/test/java/org/ethereum/crypto/CryptoTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/crypto/CryptoTest.java @@ -90,7 +90,7 @@ public class CryptoTest { // todo: https://tools.ietf.org/html/rfc6979#section-2.2 // todo: https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java - System.out.println(new BigInteger(1, Hex.decode("3913517ebd3c0c65000000"))); + System.out.println(new BigInteger(Hex.decode("3913517ebd3c0c65000000"))); System.out.println(Utils.getValueShortString(new BigInteger("69000000000000000000000000"))); diff --git a/ethereumj-core/src/test/java/org/ethereum/trie/TrieTest.java b/ethereumj-core/src/test/java/org/ethereum/trie/TrieTest.java index ac062d07..0397a1fb 100644 --- a/ethereumj-core/src/test/java/org/ethereum/trie/TrieTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/trie/TrieTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.*; import org.ethereum.trie.Trie; import org.junit.Test; +import org.spongycastle.util.encoders.Hex; public class TrieTest { @@ -34,7 +35,7 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update("", dog); - assertEquals(dog, trie.get("")); + assertEquals(dog, new String(trie.get(""))); } @Test @@ -42,7 +43,7 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(cat, dog); - assertEquals(dog, trie.get(cat)); + assertEquals(dog, new String(trie.get(cat))); } @Test @@ -50,33 +51,33 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(cat, LONG_STRING); - assertEquals(LONG_STRING, trie.get(cat)); + assertEquals(LONG_STRING, new String(trie.get(cat))); } @Test public void testInsertMultipleItems1() { Trie trie = new Trie(mockDb); trie.update(ca, dude); - assertEquals(dude, trie.get(ca)); + assertEquals(dude, new String(trie.get(ca))); trie.update(cat, dog); - assertEquals(dog, trie.get(cat)); + assertEquals(dog, new String(trie.get(cat))); trie.update(dog, test); - assertEquals(test, trie.get(dog)); + assertEquals(test, new String(trie.get(dog))); trie.update(doge, LONG_STRING); - assertEquals(LONG_STRING, trie.get(doge)); + assertEquals(LONG_STRING, new String(trie.get(doge))); trie.update(test, LONG_STRING); - assertEquals(LONG_STRING, trie.get(test)); + assertEquals(LONG_STRING, new String(trie.get(test))); // Test if everything is still there - assertEquals(dude, trie.get(ca)); - assertEquals(dog, trie.get(cat)); - assertEquals(test, trie.get(dog)); - assertEquals(LONG_STRING, trie.get(doge)); - assertEquals(LONG_STRING, trie.get(test)); + assertEquals(dude, new String(trie.get(ca))); + assertEquals(dog, new String(trie.get(cat))); + assertEquals(test, new String(trie.get(dog))); + assertEquals(LONG_STRING, new String(trie.get(doge))); + assertEquals(LONG_STRING, new String(trie.get(test))); } @Test @@ -84,26 +85,26 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(cat, dog); - assertEquals(dog, trie.get(cat)); + assertEquals(dog, new String(trie.get(cat))); trie.update(ca, dude); - assertEquals(dude, trie.get(ca)); + assertEquals(dude, new String(trie.get(ca))); trie.update(doge, LONG_STRING); - assertEquals(LONG_STRING, trie.get(doge)); + assertEquals(LONG_STRING, new String(trie.get(doge))); trie.update(dog, test); - assertEquals(test, trie.get(dog)); + assertEquals(test, new String(trie.get(dog))); trie.update(test, LONG_STRING); - assertEquals(LONG_STRING, trie.get(test)); + assertEquals(LONG_STRING, new String(trie.get(test))); // Test if everything is still there - assertEquals(dog, trie.get(cat)); - assertEquals(dude, trie.get(ca)); - assertEquals(LONG_STRING, trie.get(doge)); - assertEquals(test, trie.get(dog)); - assertEquals(LONG_STRING, trie.get(test)); + assertEquals(dog, new String(trie.get(cat))); + assertEquals(dude, new String(trie.get(ca))); + assertEquals(LONG_STRING, new String(trie.get(doge))); + assertEquals(test, new String(trie.get(dog))); + assertEquals(LONG_STRING, new String(trie.get(test))); } @Test @@ -111,19 +112,19 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(cat, dog); - assertEquals(dog, trie.get(cat)); + assertEquals(dog, new String(trie.get(cat))); trie.update(cat, dog+"1"); - assertEquals(dog+"1", trie.get(cat)); + assertEquals(dog+"1", new String(trie.get(cat))); } @Test public void testUpdateLongToLongString() { Trie trie = new Trie(mockDb); trie.update(cat, LONG_STRING); - assertEquals(LONG_STRING, trie.get(cat)); + assertEquals(LONG_STRING, new String(trie.get(cat))); trie.update(cat, LONG_STRING+"1"); - assertEquals(LONG_STRING+"1", trie.get(cat)); + assertEquals(LONG_STRING+"1", new String(trie.get(cat))); } @Test @@ -131,10 +132,10 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(cat, dog); - assertEquals(dog, trie.get(cat)); + assertEquals(dog, new String(trie.get(cat))); trie.update(cat, LONG_STRING+"1"); - assertEquals(LONG_STRING+"1", trie.get(cat)); + assertEquals(LONG_STRING+"1", new String(trie.get(cat))); } @Test @@ -142,10 +143,10 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(cat, LONG_STRING); - assertEquals(LONG_STRING, trie.get(cat)); + assertEquals(LONG_STRING, new String(trie.get(cat))); trie.update(cat, dog+"1"); - assertEquals(dog+"1", trie.get(cat)); + assertEquals(dog+"1", new String(trie.get(cat))); } @Test @@ -155,15 +156,15 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(cat, dog); - assertEquals(dog, trie.get(cat)); + assertEquals(dog, new String(trie.get(cat))); trie.update(ca, dude); - assertEquals(dude, trie.get(ca)); - assertEquals(ROOT_HASH_BEFORE, trie.getRootHash()); + assertEquals(dude, new String(trie.get(ca))); + assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash())); trie.delete(ca); - assertEquals("", trie.get(ca)); - assertEquals(ROOT_HASH_AFTER, trie.getRootHash()); + assertEquals("", new String(trie.get(ca))); + assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash())); } @Test @@ -173,15 +174,15 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(ca, dude); - assertEquals(dude, trie.get(ca)); + assertEquals(dude, new String(trie.get(ca))); trie.update(cat, dog); - assertEquals(dog, trie.get(cat)); - assertEquals(ROOT_HASH_BEFORE, trie.getRootHash()); + assertEquals(dog, new String(trie.get(cat))); + assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash())); trie.delete(cat); - assertEquals("", trie.get(cat)); - assertEquals(ROOT_HASH_AFTER, trie.getRootHash()); + assertEquals("", new String(trie.get(cat))); + assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash())); } @Test @@ -191,15 +192,15 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(cat, dude); - assertEquals(dude, trie.get(cat)); + assertEquals(dude, new String(trie.get(cat))); trie.update(dog, test); - assertEquals(test, trie.get(dog)); - assertEquals(ROOT_HASH_BEFORE, trie.getRootHash()); + assertEquals(test, new String(trie.get(dog))); + assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash())); trie.delete(dog); - assertEquals("", trie.get(dog)); - assertEquals(ROOT_HASH_AFTER, trie.getRootHash()); + assertEquals("", new String(trie.get(dog))); + assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash())); } @Test @@ -209,15 +210,15 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(cat, LONG_STRING); - assertEquals(LONG_STRING, trie.get(cat)); + assertEquals(LONG_STRING, new String(trie.get(cat))); trie.update(dog, LONG_STRING); - assertEquals(LONG_STRING, trie.get(dog)); - assertEquals(ROOT_HASH_BEFORE, trie.getRootHash()); + assertEquals(LONG_STRING, new String(trie.get(dog))); + assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash())); trie.delete(dog); - assertEquals("", trie.get(dog)); - assertEquals(ROOT_HASH_AFTER, trie.getRootHash()); + assertEquals("", new String(trie.get(dog))); + assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash())); } @Test @@ -227,15 +228,15 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(ca, LONG_STRING); - assertEquals(LONG_STRING, trie.get(ca)); + assertEquals(LONG_STRING, new String(trie.get(ca))); trie.update(cat, LONG_STRING); - assertEquals(LONG_STRING, trie.get(cat)); - assertEquals(ROOT_HASH_BEFORE, trie.getRootHash()); + assertEquals(LONG_STRING, new String(trie.get(cat))); + assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash())); trie.delete(cat); - assertEquals("", trie.get(cat)); - assertEquals(ROOT_HASH_AFTER, trie.getRootHash()); + assertEquals("", new String(trie.get(cat))); + assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash())); } @Test @@ -245,15 +246,15 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(cat, LONG_STRING); - assertEquals(LONG_STRING, trie.get(cat)); + assertEquals(LONG_STRING, new String(trie.get(cat))); trie.update(ca, LONG_STRING); - assertEquals(LONG_STRING, trie.get(ca)); - assertEquals(ROOT_HASH_BEFORE, trie.getRootHash()); + assertEquals(LONG_STRING, new String(trie.get(ca))); + assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash())); trie.delete(ca); - assertEquals("", trie.get(ca)); - assertEquals(ROOT_HASH_AFTER, trie.getRootHash()); + assertEquals("", new String(trie.get(ca))); + assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash())); } @Test @@ -264,28 +265,28 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(cat, dog); - assertEquals(dog, trie.get(cat)); + assertEquals(dog, new String(trie.get(cat))); trie.update(ca, dude); - assertEquals(dude, trie.get(ca)); + assertEquals(dude, new String(trie.get(ca))); trie.update(doge, LONG_STRING); - assertEquals(LONG_STRING, trie.get(doge)); + assertEquals(LONG_STRING, new String(trie.get(doge))); trie.update(dog, test); - assertEquals(test, trie.get(dog)); + assertEquals(test, new String(trie.get(dog))); trie.update(test, LONG_STRING); - assertEquals(LONG_STRING, trie.get(test)); - assertEquals(ROOT_HASH_BEFORE, trie.getRootHash()); + assertEquals(LONG_STRING, new String(trie.get(test))); + assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash())); trie.delete(dog); - assertEquals("", trie.get(dog)); - assertEquals(ROOT_HASH_AFTER1, trie.getRootHash()); + assertEquals("", new String(trie.get(dog))); + assertEquals(ROOT_HASH_AFTER1, Hex.toHexString(trie.getRootHash())); trie.delete(test); - assertEquals("", trie.get(test)); - assertEquals(ROOT_HASH_AFTER2, trie.getRootHash()); + assertEquals("", new String(trie.get(test))); + assertEquals(ROOT_HASH_AFTER2, Hex.toHexString(trie.getRootHash())); } @Test @@ -296,39 +297,39 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update(c, LONG_STRING); - assertEquals(LONG_STRING, trie.get(c)); + assertEquals(LONG_STRING, new String(trie.get(c))); trie.update(ca, LONG_STRING); - assertEquals(LONG_STRING, trie.get(ca)); + assertEquals(LONG_STRING, new String(trie.get(ca))); trie.update(cat, LONG_STRING); - assertEquals(LONG_STRING, trie.get(cat)); - assertEquals(ROOT_HASH_BEFORE, trie.getRootHash()); + assertEquals(LONG_STRING, new String(trie.get(cat))); + assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash())); trie.delete(ca); - assertEquals("", trie.get(ca)); - assertEquals(ROOT_HASH_AFTER1, trie.getRootHash()); + assertEquals("", new String(trie.get(ca))); + assertEquals(ROOT_HASH_AFTER1, Hex.toHexString(trie.getRootHash())); trie.delete(cat); - assertEquals("", trie.get(cat)); - assertEquals(ROOT_HASH_AFTER2, trie.getRootHash()); + assertEquals("", new String(trie.get(cat))); + assertEquals(ROOT_HASH_AFTER2, Hex.toHexString(trie.getRootHash())); } @Test public void testDeleteAll() { String ROOT_HASH_BEFORE = "a84739b4762ddf15e3acc4e6957e5ab2bbfaaef00fe9d436a7369c6f058ec90d"; Trie trie = new Trie(mockDb); - assertEquals(ROOT_HASH_EMPTY, trie.getRootHash()); + assertEquals(ROOT_HASH_EMPTY, Hex.toHexString(trie.getRootHash())); trie.update(ca, dude); trie.update(cat, dog); trie.update(doge, LONG_STRING); - assertEquals(ROOT_HASH_BEFORE, trie.getRootHash()); + assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash())); trie.delete(ca); trie.delete(cat); trie.delete(doge); - assertEquals(ROOT_HASH_EMPTY, trie.getRootHash()); + assertEquals(ROOT_HASH_EMPTY, Hex.toHexString(trie.getRootHash())); } @Test @@ -339,12 +340,12 @@ public class TrieTest { trie1.update(doge, LONG_STRING); trie2.update(doge, LONG_STRING); assertTrue("Expected tries to be equal", trie1.cmp(trie2)); - assertEquals(trie1.getRootHash(), trie2.getRootHash()); + assertEquals(Hex.toHexString(trie1.getRootHash()), Hex.toHexString(trie2.getRootHash())); trie1.update(dog, LONG_STRING); trie2.update(cat, LONG_STRING); assertFalse("Expected tries not to be equal", trie1.cmp(trie2)); - assertNotEquals(trie1.getRootHash(), trie2.getRootHash()); + assertNotEquals(Hex.toHexString(trie1.getRootHash()), Hex.toHexString(trie2.getRootHash())); } @Test @@ -386,12 +387,26 @@ public class TrieTest { @Test public void testTrieCopy() { - fail("To be implemented"); + Trie trie = new Trie(mockDb); + trie.update("doe", "reindeer"); + Trie trie2 = trie.copy(); + assertFalse(trie.equals(trie2)); // avoid possibility that its just a reference copy + assertEquals(Hex.toHexString(trie.getRootHash()), Hex.toHexString(trie2.getRootHash())); + assertTrue(trie.cmp(trie2)); } @Test public void testTrieUndo() { - fail("To be implemented"); + Trie trie = new Trie(mockDb); + trie.update("doe", "reindeer"); + assertEquals("11a0327cfcc5b7689b6b6d727e1f5f8846c1137caaa9fc871ba31b7cce1b703e", Hex.toHexString(trie.getRootHash())); + trie.sync(); + + trie.update("dog", "puppy"); + assertEquals("05ae693aac2107336a79309e0c60b24a7aac6aa3edecaef593921500d33c63c4", Hex.toHexString(trie.getRootHash())); + + trie.undo(); + assertEquals("11a0327cfcc5b7689b6b6d727e1f5f8846c1137caaa9fc871ba31b7cce1b703e", Hex.toHexString(trie.getRootHash())); } // Using tests from: https://github.com/ethereum/tests/blob/master/trietest.json @@ -401,20 +416,20 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update("A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - assertEquals("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab", trie.getRootHash()); + assertEquals("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab", Hex.toHexString(trie.getRootHash())); } @Test public void testDogs() { Trie trie = new Trie(mockDb); trie.update("doe", "reindeer"); - assertEquals("11a0327cfcc5b7689b6b6d727e1f5f8846c1137caaa9fc871ba31b7cce1b703e", trie.getRootHash()); + assertEquals("11a0327cfcc5b7689b6b6d727e1f5f8846c1137caaa9fc871ba31b7cce1b703e", Hex.toHexString(trie.getRootHash())); trie.update("dog", "puppy"); - assertEquals("05ae693aac2107336a79309e0c60b24a7aac6aa3edecaef593921500d33c63c4", trie.getRootHash()); + assertEquals("05ae693aac2107336a79309e0c60b24a7aac6aa3edecaef593921500d33c63c4", Hex.toHexString(trie.getRootHash())); trie.update("dogglesworth", "cat"); - assertEquals("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3", trie.getRootHash()); + assertEquals("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3", Hex.toHexString(trie.getRootHash())); } @Test @@ -425,7 +440,7 @@ public class TrieTest { trie.update("doge", "coin"); trie.update("dog", "puppy"); - assertEquals("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84", trie.getRootHash()); + assertEquals("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84", Hex.toHexString(trie.getRootHash())); } @Test @@ -440,7 +455,7 @@ public class TrieTest { trie.update("dog", "puppy"); trie.update("shaman", ""); - assertEquals("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84", trie.getRootHash()); + assertEquals("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84", Hex.toHexString(trie.getRootHash())); } @Test @@ -450,7 +465,7 @@ public class TrieTest { trie.update("food", "bat"); trie.update("food", "bass"); - assertEquals("17beaa1648bafa633cda809c90c04af50fc8aed3cb40d16efbddee6fdf63c4c3", trie.getRootHash()); + assertEquals("17beaa1648bafa633cda809c90c04af50fc8aed3cb40d16efbddee6fdf63c4c3", Hex.toHexString(trie.getRootHash())); } @Test @@ -460,7 +475,7 @@ public class TrieTest { trie.update("be", "e"); trie.update("dog", "puppy"); trie.update("bed", "d"); - assertEquals("3f67c7a47520f79faa29255d2d3c084a7a6df0453116ed7232ff10277a8be68b", trie.getRootHash()); + assertEquals("3f67c7a47520f79faa29255d2d3c084a7a6df0453116ed7232ff10277a8be68b", Hex.toHexString(trie.getRootHash())); } @Test @@ -468,9 +483,9 @@ public class TrieTest { Trie trie = new Trie(mockDb); trie.update("test", "test"); - assertEquals("85d106d4edff3b7a4889e91251d0a87d7c17a1dda648ebdba8c6060825be23b8", trie.getRootHash()); + assertEquals("85d106d4edff3b7a4889e91251d0a87d7c17a1dda648ebdba8c6060825be23b8", Hex.toHexString(trie.getRootHash())); trie.update("te", "testy"); - assertEquals("8452568af70d8d140f58d941338542f645fcca50094b20f3c3d8c3df49337928", trie.getRootHash()); + assertEquals("8452568af70d8d140f58d941338542f645fcca50094b20f3c3d8c3df49337928", Hex.toHexString(trie.getRootHash())); } } diff --git a/ethereumj-core/src/test/java/org/ethereum/util/RLPTest.java b/ethereumj-core/src/test/java/org/ethereum/util/RLPTest.java index 031c51fa..6d8755fe 100644 --- a/ethereumj-core/src/test/java/org/ethereum/util/RLPTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/util/RLPTest.java @@ -85,9 +85,9 @@ public class RLPTest { BigInteger peerId = RLP.decodeBigInteger(payload, nextIndex); BigInteger expectedPeerId = - new BigInteger("-3757679129454624401847229560118336025674165800491763435653406124634392418475888088940922052683656239666728251000337405781915693264977453978537202650777524"); + new BigInteger("9650128800487972697726795438087510101805200020100629942070155319087371611597658887860952245483247188023303607186148645071838189546969115967896446355306572"); assertEquals(expectedPeerId, peerId); - + nextIndex = RLP.getNextElementIndex(payload, nextIndex); nextIndex = RLP.getFirstListElement(payload, nextIndex); ip = RLP.decodeIP4Bytes(payload, nextIndex); @@ -101,7 +101,7 @@ public class RLPTest { peerId = RLP.decodeBigInteger(payload, nextIndex); expectedPeerId = - new BigInteger("-3757679129454624401847229560118336025674165800491763435653406124634392418475888088940922052683656239666728251000337405781915693264977453978537202650777524"); + new BigInteger("9650128800487972697726795438087510101805200020100629942070155319087371611597658887860952245483247188023303607186148645071838189546969115967896446355306572"); assertEquals(expectedPeerId ,peerId); @@ -429,7 +429,7 @@ public class RLPTest { assertEquals(expected, Hex.toHexString(encoderesult)); byte[] decodeResult = (byte[]) RLP.decode(encoderesult, 0).getDecoded(); - assertEquals(test, new BigInteger(decodeResult)); + assertEquals(test, new BigInteger(1, decodeResult)); } @Test @@ -615,10 +615,10 @@ public class RLPTest { assertEquals(test11, byteArrayToInt(decodedData)); decodedData = (byte[]) RLP.decode(Hex.decode(result12), pos).getDecoded(); - assertTrue(test12.compareTo(new BigInteger(decodedData)) == 0); + assertTrue(test12.compareTo(new BigInteger(1, decodedData)) == 0); decodedData = (byte[]) RLP.decode(Hex.decode(result13), pos).getDecoded(); - assertTrue(test13.compareTo(new BigInteger(decodedData)) == 0); + assertTrue(test13.compareTo(new BigInteger(1, decodedData)) == 0); // Need to test with different expected value, because decoding doesn't recognize types Object testObject1 = RLP.decode(Hex.decode(result14), pos).getDecoded(); diff --git a/ethereumj-core/src/test/java/org/ethereum/util/RlpTestData.java b/ethereumj-core/src/test/java/org/ethereum/util/RlpTestData.java index 44faaad2..6c60bb78 100644 --- a/ethereumj-core/src/test/java/org/ethereum/util/RlpTestData.java +++ b/ethereumj-core/src/test/java/org/ethereum/util/RlpTestData.java @@ -41,7 +41,7 @@ public class RlpTestData { public static String result11 = "8203e8"; public static BigInteger test12 = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639935"); - public static String result12 = "a100ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + public static String result12 = "a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; public static BigInteger test13 = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639936"); public static String result13 = "a1010000000000000000000000000000000000000000000000000000000000000000"; diff --git a/samples/my-currency.se b/samples/my-currency.se new file mode 100644 index 00000000..9a9f5b2e --- /dev/null +++ b/samples/my-currency.se @@ -0,0 +1,34 @@ + + +# the sample is good example how one can +# save program that manage his own currency + +init: + + # this part run only on init stage + # we are about to set the maxim + # amount of currency + contract.storage[0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826] = 1000000 +code: + + + # the currency manager + # support two functions + if msg.datasize == 1: + + # 1. balance check + addr = msg.data[0] + return(contract.storage[addr]) + else: + + # 2. balance manipulation + from = msg.sender + fromvalue = contract.storage[from] + to = msg.data[0] + value = msg.data[1] + if fromvalue >= value: + contract.storage[from] = fromvalue - value + contract.storage[to] = contract.storage[to] + value + return(1) + else: + return(0) diff --git a/samples/namecoin.se b/samples/namecoin.se new file mode 100644 index 00000000..0f36bce5 --- /dev/null +++ b/samples/namecoin.se @@ -0,0 +1,10 @@ + +# The sample demonstrates how you +# can simply create a program running +# on top of chain and saving values for +# futre use +if !(contract.storage[msg.data[0]]): + contract.storage[msg.data[0]] = msg.data[1] + return(1) +else: + return(0) \ No newline at end of file