Merge pull request #53 from nicksavers/database

Better encapsulation for Blockchain db
This commit is contained in:
romanman 2014-07-03 11:42:22 +01:00
commit 33be499ba6
21 changed files with 123 additions and 166 deletions

View File

@ -40,7 +40,6 @@ public class SystemProperties {
try { try {
String userDir = System.getProperty("user.dir"); String userDir = System.getProperty("user.dir");
System.out.println(userDir);
String fileName = userDir + "/config/system.properties"; String fileName = userDir + "/config/system.properties";
File file = new File(fileName); File file = new File(fileName);

View File

@ -71,7 +71,7 @@ public class Block {
timestamp, extraData, nonce); timestamp, extraData, nonce);
this.txsState = new Trie(null); this.txsState = new Trie(null);
byte[] stateRoot = WorldManager.instance.repository.getRootHash(); byte[] stateRoot = WorldManager.getInstance().getRepository().getRootHash();
this.header.setStateRoot(stateRoot); this.header.setStateRoot(stateRoot);
this.header.setTxTrieRoot(txsState.getRootHash()); this.header.setTxTrieRoot(txsState.getRootHash());
@ -108,9 +108,7 @@ public class Block {
} }
public Block getParent() { public Block getParent() {
byte[] rlpEncoded = WorldManager.instance.chainDB.get(ByteUtil return WorldManager.getInstance().getBlockChain().getByNumber(this.getNumber() - 1);
.longToBytes(this.getNumber() - 1));
return new Block(rlpEncoded);
} }
public byte[] getParentHash() { public byte[] getParentHash() {

View File

@ -54,7 +54,7 @@ public class Blockchain {
// to avoid using minGasPrice=0 from Genesis for the wallet // to avoid using minGasPrice=0 from Genesis for the wallet
private static long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue(); private static long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue();
private DatabaseImpl db; private DatabaseImpl chainDb;
private Wallet wallet; private Wallet wallet;
private long gasPrice = 1000; private long gasPrice = 1000;
@ -69,9 +69,8 @@ public class Blockchain {
private Map<String, WalletTransaction> walletTransactions = private Map<String, WalletTransaction> walletTransactions =
Collections.synchronizedMap(new HashMap<String, WalletTransaction>()); Collections.synchronizedMap(new HashMap<String, WalletTransaction>());
public Blockchain(Wallet wallet) { public Blockchain() {
this.db = WorldManager.instance.chainDB; this.chainDb = new DatabaseImpl("blockchain");
this.wallet = wallet;
} }
public Block getLastBlock() { public Block getLastBlock() {
@ -86,8 +85,8 @@ public class Blockchain {
return index.size(); return index.size();
} }
public Block getByNumber(long rowIndex) { public Block getByNumber(long blockNr) {
return new Block(db.get(ByteUtil.longToBytes(rowIndex))); return new Block(chainDb.get(ByteUtil.longToBytes(blockNr)));
} }
public void addBlocks(List<Block> blocks) { public void addBlocks(List<Block> blocks) {
@ -119,7 +118,7 @@ public class Blockchain {
// String blockState = Hex.toHexString(block.getStateRoot()); // String blockState = Hex.toHexString(block.getStateRoot());
// logger.debug("New world stateRoot {} and block stateRoot {}", newState, blockState); // logger.debug("New world stateRoot {} and block stateRoot {}", newState, blockState);
db.put(ByteUtil.longToBytes(block.getNumber()), block.getEncoded()); this.chainDb.put(ByteUtil.longToBytes(block.getNumber()), block.getEncoded());
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("block added to the chain with hash: {}", Hex.toHexString(block.getHash())); logger.debug("block added to the chain with hash: {}", Hex.toHexString(block.getHash()));
} }
@ -128,23 +127,23 @@ public class Blockchain {
for (Transaction tx : block.getTransactionsList()) { for (Transaction tx : block.getTransactionsList()) {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash())); logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash()));
removeWalletTransaction(tx); this.removeWalletTransaction(tx);
} }
} }
logger.info("*** Block chain size: [ {} ]", index.size()); logger.info("*** Block chain size: [ {} ]", index.size());
} }
private void addBlock(Block block) { public void addBlock(Block block) {
if(block.isValid()) { if(block.isValid()) {
if (!block.isGenesis()) if (!block.isGenesis())
WorldManager.instance.applyBlock(block); WorldManager.getInstance().applyBlock(block);
this.wallet.processBlock(block); this.wallet.processBlock(block);
// In case of the genesis block we don't want to rely on the min gas price // In case of the genesis block we don't want to rely on the min gas price
this.gasPrice = block.isGenesis() ? INITIAL_MIN_GAS_PRICE : block.getMinGasPrice(); this.gasPrice = block.isGenesis() ? INITIAL_MIN_GAS_PRICE : block.getMinGasPrice();
setLastBlock(block); this.setLastBlock(block);
index.put(block.getNumber(), block.getParentHash()); this.index.put(block.getNumber(), block.getParentHash());
} else { } else {
logger.warn("Invalid block with nr: {}", block.getNumber()); logger.warn("Invalid block with nr: {}", block.getNumber());
} }
@ -180,6 +179,10 @@ public class Blockchain {
logger.info("pending transaction removed with hash: {} ", hash); logger.info("pending transaction removed with hash: {} ", hash);
walletTransactions.remove(hash); walletTransactions.remove(hash);
} }
public void setWallet(Wallet wallet) {
this.wallet = wallet;
}
public byte[] getLatestBlockHash() { public byte[] getLatestBlockHash() {
if (index.isEmpty()) if (index.isEmpty())
@ -188,21 +191,21 @@ public class Blockchain {
return getLastBlock().getHash(); return getLastBlock().getHash();
} }
public void loadChain() { public void load() {
DBIterator iterator = db.iterator(); DBIterator iterator = chainDb.iterator();
try { try {
if (!iterator.hasNext()) { if (!iterator.hasNext()) {
logger.info("DB is empty - adding Genesis"); logger.info("DB is empty - adding Genesis");
this.lastBlock = Genesis.getInstance(); this.lastBlock = Genesis.getInstance();
this.addBlock(lastBlock); this.addBlock(lastBlock);
logger.debug("Block #{} -> {}", Genesis.NUMBER, lastBlock.toFlatString()); logger.debug("Block #{} -> {}", Genesis.NUMBER, lastBlock.toFlatString());
db.put(ByteUtil.longToBytes(Genesis.NUMBER), lastBlock.getEncoded()); chainDb.put(ByteUtil.longToBytes(Genesis.NUMBER), lastBlock.getEncoded());
} }
logger.debug("Displaying blocks stored in DB sorted on blocknumber"); logger.debug("Displaying blocks stored in DB sorted on blocknumber");
long blockNr = Genesis.NUMBER; long blockNr = Genesis.NUMBER;
for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) {
this.lastBlock = new Block(db.get(ByteUtil.longToBytes(blockNr))); this.lastBlock = new Block(chainDb.get(ByteUtil.longToBytes(blockNr)));
logger.debug("Block #{} -> {}", lastBlock.getNumber(), lastBlock.toFlatString()); logger.debug("Block #{} -> {}", lastBlock.getNumber(), lastBlock.toFlatString());
this.addBlock(lastBlock); this.addBlock(lastBlock);
blockNr = lastBlock.getNumber()+1; blockNr = lastBlock.getNumber()+1;
@ -216,4 +219,9 @@ public class Blockchain {
} }
} }
} }
public void close() {
if (this.chainDb != null)
chainDb.close();
}
} }

View File

@ -67,15 +67,14 @@ public class Genesis extends Block {
// The proof-of-concept series include a development premine, making the state root hash // The proof-of-concept series include a development premine, making the state root hash
// some value stateRoot. The latest documentation should be consulted for the value of the state root. // some value stateRoot. The latest documentation should be consulted for the value of the state root.
for (String address : premine) { for (String address : premine) {
WorldManager.instance.repository.createAccount(Hex.decode(address)); WorldManager.getInstance().getRepository().createAccount(Hex.decode(address));
WorldManager.instance.repository.addBalance (Hex.decode(address), BigInteger.valueOf(2).pow(200) ); WorldManager.getInstance().getRepository().addBalance (Hex.decode(address), BigInteger.valueOf(2).pow(200) );
} }
this.setStateRoot(WorldManager.getInstance().getRepository().getRootHash());
this.setStateRoot( WorldManager.instance.repository.getRootHash() ); WorldManager.getInstance().getRepository().dumpState(0, 0, null);
logger.info("Genesis-hash: " + Hex.toHexString(this.getHash())); logger.info("Genesis-hash: " + Hex.toHexString(this.getHash()));
logger.info("Genesis-stateRoot: " + Hex.toHexString(this.getStateRoot())); logger.info("Genesis-stateRoot: " + Hex.toHexString(this.getStateRoot()));
WorldManager.instance.repository.dumpState(0, 0, null);
} }
public static Block getInstance() { public static Block getInstance() {

View File

@ -37,7 +37,6 @@ public class DatabaseImpl implements Database {
try { try {
logger.debug("Opening database"); logger.debug("Opening database");
if(SystemProperties.CONFIG.databaseReset()) { if(SystemProperties.CONFIG.databaseReset()) {
logger.debug("Destroying '" + name + "' DB on startup ENABLED");
destroyDB(name); destroyDB(name);
} }
logger.debug("Initializing new or existing DB: '" + name + "'"); logger.debug("Initializing new or existing DB: '" + name + "'");
@ -62,16 +61,16 @@ public class DatabaseImpl implements Database {
} }
} }
/** Insert object(value) (key = sha3(value)) */
public void put(byte[] key, byte[] value) {
db.put(key, value);
}
/** Get object (key) -> value */ /** Get object (key) -> value */
public byte[] get(byte[] key) { public byte[] get(byte[] key) {
return db.get(key); return db.get(key);
} }
/** Insert object(value) (key = sha3(value)) */
public void put(byte[] key, byte[] value) {
db.put(key, value);
}
/** Delete object (key) from db **/ /** Delete object (key) from db **/
public void delete(byte[] key) { public void delete(byte[] key) {
delete(key); delete(key);

View File

@ -44,7 +44,7 @@ public class TrackDatabase implements Database {
public void put(byte[] key, byte[] value) { public void put(byte[] key, byte[] value) {
if (trackingChanges) { if (trackingChanges) {
changes.put( new ByteArrayWrapper(key) , value); changes.put(new ByteArrayWrapper(key), value);
} else { } else {
db.put(key, value); db.put(key, value);
} }

View File

@ -31,7 +31,7 @@ public class BlockChainTable extends JFrame {
this.toolBar = toolBar; this.toolBar = toolBar;
addCloseAction(); addCloseAction();
final BlockChainTable blockChainTable = this; final BlockChainTable blockchainTable = this;
setTitle("Block Chain Table"); setTitle("Block Chain Table");
setSize(700, 400); setSize(700, 400);
@ -48,7 +48,7 @@ public class BlockChainTable extends JFrame {
topPanel.setLayout(new BorderLayout()); topPanel.setLayout(new BorderLayout());
getContentPane().add(topPanel); getContentPane().add(topPanel);
// Create a new table instance // Create a new table getInstance()
table = new JTable(); table = new JTable();
table.setModel(new BlockTableModel()); table.setModel(new BlockTableModel());
@ -74,9 +74,9 @@ public class BlockChainTable extends JFrame {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (WorldManager.instance.getBlockChain().getSize() - 1 < lastFindIndex) return; if (WorldManager.getInstance().getBlockChain().getSize() - 1 < lastFindIndex) return;
Block block = WorldManager.instance.getBlockChain().getByNumber(lastFindIndex); Block block = WorldManager.getInstance().getBlockChain().getByNumber(lastFindIndex);
StringSelection stsel = new StringSelection(block.toString()); StringSelection stsel = new StringSelection(block.toString());
Clipboard system = Toolkit.getDefaultToolkit().getSystemClipboard(); Clipboard system = Toolkit.getDefaultToolkit().getSystemClipboard();
system.setContents(stsel,stsel); system.setContents(stsel,stsel);
@ -88,7 +88,7 @@ public class BlockChainTable extends JFrame {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
String toFind = JOptionPane.showInputDialog(blockChainTable, "Find:", String toFind = JOptionPane.showInputDialog(blockchainTable, "Find:",
"Find in BlockChain", JOptionPane.QUESTION_MESSAGE); "Find in BlockChain", JOptionPane.QUESTION_MESSAGE);
if (toFind.equals("")) { if (toFind.equals("")) {
@ -96,10 +96,10 @@ public class BlockChainTable extends JFrame {
return; return;
} }
for (int i = lastFindIndex + 1; i < WorldManager.instance.getBlockChain().getSize(); ++i) { for (int i = lastFindIndex + 1; i < WorldManager.getInstance().getBlockChain().getSize(); ++i) {
if (WorldManager.instance.getBlockChain().getSize() - 1 < i) return; if (WorldManager.getInstance().getBlockChain().getSize() - 1 < i) return;
Block block = WorldManager.instance.getBlockChain().getByNumber(i); Block block = WorldManager.getInstance().getBlockChain().getByNumber(i);
boolean found = block.toString().toLowerCase().contains(toFind.toLowerCase()); boolean found = block.toString().toLowerCase().contains(toFind.toLowerCase());
if (found) { if (found) {
// TODO: now we find the first occur // TODO: now we find the first occur

View File

@ -16,7 +16,7 @@ public class BlockTableModel extends AbstractTableModel {
public int getRowCount() { public int getRowCount() {
fireTableDataChanged(); fireTableDataChanged();
int rowCount = WorldManager.instance.getBlockChain().getSize(); int rowCount = WorldManager.getInstance().getBlockChain().getSize();
return rowCount; return rowCount;
} }
@ -31,7 +31,7 @@ public class BlockTableModel extends AbstractTableModel {
// byte[] hash = MainData.instance.getAllBlocks().get(rowIndex).getHash(); // byte[] hash = MainData.instance.getAllBlocks().get(rowIndex).getHash();
// return Hex.toHexString(hash); // return Hex.toHexString(hash);
Block block = WorldManager.instance.getBlockChain().getByNumber(rowIndex); Block block = WorldManager.getInstance().getBlockChain().getByNumber(rowIndex);
if (block == null) return ""; if (block == null) return "";
return block.toString(); return block.toString();

View File

@ -174,7 +174,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog {
editor.setForeground(Color.RED); editor.setForeground(Color.RED);
Collection<Account> accounts = Collection<Account> accounts =
WorldManager.instance.getWallet().getAccountCollection(); WorldManager.getInstance().getWallet().getAccountCollection();
for (Account account : accounts) { for (Account account : accounts) {
creatorAddressCombo.addItem(new AccountWrapper(account)); creatorAddressCombo.addItem(new AccountWrapper(account));
@ -226,8 +226,8 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog {
} }
byte[] contractAddress = Hex.decode( contractAddr ); byte[] contractAddress = Hex.decode( contractAddr );
final byte[] programCode = WorldManager.instance.repository.getCode(contractAddress); final byte[] programCode = WorldManager.getInstance().getRepository().getCode(contractAddress);
final Map storageMap = WorldManager.instance.repository.getContractDetails(contractAddress).getStorage(); final Map storageMap = WorldManager.getInstance().getRepository().getContractDetails(contractAddress).getStorage();
contractDataInput.setBounds(70, 80, 350, 145); contractDataInput.setBounds(70, 80, 350, 145);
contractDataInput.setViewportView(msgDataTA); contractDataInput.setViewportView(msgDataTA);
@ -301,13 +301,13 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog {
private void playContractCall() { private void playContractCall() {
byte[] contractAddress = Hex.decode(contractAddrInput.getText()); byte[] contractAddress = Hex.decode(contractAddrInput.getText());
ContractDetails contractDetails = WorldManager.instance.repository.getContractDetails(contractAddress); ContractDetails contractDetails = WorldManager.getInstance().getRepository().getContractDetails(contractAddress);
if (contractDetails == null) { if (contractDetails == null) {
alertStatusMsg("No contract for that address"); alertStatusMsg("No contract for that address");
return; return;
} }
byte[] programCode = WorldManager.instance.repository.getCode(contractAddress); byte[] programCode = WorldManager.getInstance().getRepository().getCode(contractAddress);
if (programCode == null || programCode.length == 0) { if (programCode == null || programCode.length == 0) {
alertStatusMsg("Such account exist but no code in the db"); alertStatusMsg("Such account exist but no code in the db");
return; return;
@ -316,7 +316,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog {
Transaction tx = createTransaction(); Transaction tx = createTransaction();
if (tx == null) return; if (tx == null) return;
ProgramPlayDialog.createAndShowGUI(programCode, tx, WorldManager.instance.getBlockChain().getLastBlock()); ProgramPlayDialog.createAndShowGUI(programCode, tx, WorldManager.getInstance().getBlockChain().getLastBlock());
} }
protected JRootPane createRootPane() { protected JRootPane createRootPane() {
@ -460,15 +460,15 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog {
} }
public static void main(String args[]) { public static void main(String args[]) {
WorldManager.instance.getWallet(); WorldManager.getInstance().getWallet();
WorldManager.instance.loadChain(); WorldManager.getInstance().loadBlockChain();
ContractCallDialog ccd = new ContractCallDialog(null); ContractCallDialog ccd = new ContractCallDialog(null);
ccd.setVisible(true); ccd.setVisible(true);
ccd.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); ccd.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
ccd.addWindowListener(new WindowAdapter() { ccd.addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosed(WindowEvent e) { public void windowClosed(WindowEvent e) {
WorldManager.instance.close(); WorldManager.getInstance().close();
} }
}); });
} }

View File

@ -108,7 +108,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
contractAddrInput.setText(Hex.toHexString(tx.getContractAddress())); contractAddrInput.setText(Hex.toHexString(tx.getContractAddress()));
ProgramPlayDialog.createAndShowGUI(tx.getData(), tx, ProgramPlayDialog.createAndShowGUI(tx.getData(), tx,
WorldManager.instance.getBlockChain().getLastBlock()); WorldManager.getInstance().getBlockChain().getLastBlock());
}} }}
); );
@ -170,7 +170,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
editor.setForeground(Color.RED); editor.setForeground(Color.RED);
Collection<Account> accounts = Collection<Account> accounts =
WorldManager.instance.getWallet().getAccountCollection(); WorldManager.getInstance().getWallet().getAccountCollection();
for (Account account : accounts) { for (Account account : accounts) {
creatorAddressCombo.addItem(new AccountWrapper(account)); creatorAddressCombo.addItem(new AccountWrapper(account));
@ -302,7 +302,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
Account account = ((AccountWrapper)creatorAddressCombo.getSelectedItem()).getAccount(); Account account = ((AccountWrapper)creatorAddressCombo.getSelectedItem()).getAccount();
BigInteger currentBalance = account.getBalance(); BigInteger currentBalance = account.getBalance();
BigInteger gasPrice = BigInteger.valueOf(WorldManager.instance.getBlockChain().getGasPrice()); BigInteger gasPrice = BigInteger.valueOf(WorldManager.getInstance().getBlockChain().getGasPrice());
BigInteger gasInput = new BigInteger( this.gasInput.getText()); BigInteger gasInput = new BigInteger( this.gasInput.getText());
boolean canAfford = currentBalance.compareTo(gasPrice.multiply(gasInput)) >= 0; boolean canAfford = currentBalance.compareTo(gasPrice.multiply(gasInput)) >= 0;

View File

@ -58,7 +58,7 @@ public class DialogWorker extends SwingWorker<Transaction, Object> {
} }
dialog.infoStatusMsg("Transaction got approved"); dialog.infoStatusMsg("Transaction got approved");
WorldManager.instance.getWallet().applyTransaction(tx); WorldManager.getInstance().getWallet().applyTransaction(tx);
return null; return null;
} }
} }

View File

@ -119,7 +119,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog {
byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes(); byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes();
byte[] nonce = accountState.getNonce() == BigInteger.ZERO ? null : accountState.getNonce().toByteArray(); byte[] nonce = accountState.getNonce() == BigInteger.ZERO ? null : accountState.getNonce().toByteArray();
byte[] gasPrice = BigInteger.valueOf( WorldManager.instance.getBlockChain().getGasPrice()).toByteArray(); byte[] gasPrice = BigInteger.valueOf( WorldManager.getInstance().getBlockChain().getGasPrice()).toByteArray();
Transaction tx = new Transaction(nonce, gasPrice, BigIntegers Transaction tx = new Transaction(nonce, gasPrice, BigIntegers
.asUnsignedByteArray(fee), address, BigIntegers .asUnsignedByteArray(fee), address, BigIntegers
@ -194,7 +194,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog {
// check if the tx is affordable // check if the tx is affordable
BigInteger ammountValue = new BigInteger(amountText); BigInteger ammountValue = new BigInteger(amountText);
BigInteger feeValue = new BigInteger(feeText); BigInteger feeValue = new BigInteger(feeText);
BigInteger gasPrice = BigInteger.valueOf(WorldManager.instance.getBlockChain().getGasPrice()); BigInteger gasPrice = BigInteger.valueOf(WorldManager.getInstance().getBlockChain().getGasPrice());
BigInteger currentBalance = accountState.getBalance(); BigInteger currentBalance = accountState.getBalance();
boolean canAfford = gasPrice.multiply(feeValue).add(ammountValue).compareTo(currentBalance) != 1; boolean canAfford = gasPrice.multiply(feeValue).add(ammountValue).compareTo(currentBalance) != 1;

View File

@ -4,7 +4,6 @@ import org.ethereum.core.Block;
import org.ethereum.core.Transaction; import org.ethereum.core.Transaction;
import org.ethereum.db.Repository; import org.ethereum.db.Repository;
import org.ethereum.manager.WorldManager; import org.ethereum.manager.WorldManager;
import org.ethereum.serpent.SerpentCompiler;
import org.ethereum.vm.*; import org.ethereum.vm.*;
import org.spongycastle.util.encoders.Hex; import org.spongycastle.util.encoders.Hex;
@ -52,7 +51,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
outputList = new ArrayList<String>(); outputList = new ArrayList<String>();
VM vm = new VM(); VM vm = new VM();
Repository tractRepository = WorldManager.instance.repository.getTrack(); Repository tractRepository = WorldManager.getInstance().getRepository().getTrack();
Program program = new Program(code , Program program = new Program(code ,
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, tractRepository)); ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, tractRepository));

View File

@ -24,7 +24,7 @@ public class ToolBar extends JFrame {
private ConnectionConsoleWindow connectionConsoleWindow = null; private ConnectionConsoleWindow connectionConsoleWindow = null;
private PeersTableWindow mainFrame = null; private PeersTableWindow mainFrame = null;
private BlockChainTable blockChainWindow = null; private BlockChainTable blockchainWindow = null;
private WalletWindow walletWindow = null; private WalletWindow walletWindow = null;
private SerpentEditor serpentEditor = null; private SerpentEditor serpentEditor = null;
@ -71,7 +71,7 @@ public class ToolBar extends JFrame {
addWindowListener(new WindowAdapter() { addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosing(WindowEvent e) { public void windowClosing(WindowEvent e) {
WorldManager.instance.close(); WorldManager.getInstance().close();
} }
}); });
@ -182,13 +182,13 @@ public class ToolBar extends JFrame {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
public void run() { public void run() {
if (blockChainWindow == null) if (blockchainWindow == null)
blockChainWindow = new BlockChainTable(ToolBar.this); blockchainWindow = new BlockChainTable(ToolBar.this);
blockChainWindow.setVisible(true); blockchainWindow.setVisible(true);
} }
}); });
} else if (e.getStateChange() == ItemEvent.DESELECTED) { } else if (e.getStateChange() == ItemEvent.DESELECTED) {
blockChainWindow.setVisible(false); blockchainWindow.setVisible(false);
} }
} }
}); });
@ -226,9 +226,9 @@ public class ToolBar extends JFrame {
cp.add(chainToggle); cp.add(chainToggle);
cp.add(walletToggle); cp.add(walletToggle);
WorldManager.instance.getWallet(); WorldManager.getInstance().getWallet();
WorldManager.instance.loadChain(); WorldManager.getInstance().loadBlockChain();
MainData.instance.toString(); MainData.instance.toString();
} }

View File

@ -41,7 +41,7 @@ public class WalletWindow extends JFrame implements Wallet.WalletListener{
Container contentPane = this.getContentPane(); Container contentPane = this.getContentPane();
contentPane.setBackground(new Color(255, 255, 255)); contentPane.setBackground(new Color(255, 255, 255));
Wallet wallet = WorldManager.instance.getWallet(); Wallet wallet = WorldManager.getInstance().getWallet();
wallet.addListener(this); wallet.addListener(this);
loadWallet(); loadWallet();
@ -53,7 +53,7 @@ public class WalletWindow extends JFrame implements Wallet.WalletListener{
contentPane.removeAll(); contentPane.removeAll();
contentPane.setLayout(new FlowLayout()); contentPane.setLayout(new FlowLayout());
Wallet wallet = WorldManager.instance.getWallet(); Wallet wallet = WorldManager.getInstance().getWallet();
for (Account account : wallet.getAccountCollection()) { for (Account account : wallet.getAccountCollection()) {
WalletAddressPanel rowPanel = new WalletAddressPanel(account); WalletAddressPanel rowPanel = new WalletAddressPanel(account);
@ -73,7 +73,7 @@ public class WalletWindow extends JFrame implements Wallet.WalletListener{
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
Wallet wallet = WorldManager.instance.getWallet(); Wallet wallet = WorldManager.getInstance().getWallet();
if (wallet.getAccountCollection().size() >= 5) { if (wallet.getAccountCollection().size() >= 5) {
JOptionPane.showMessageDialog(walletWindow, JOptionPane.showMessageDialog(walletWindow,
"Hey do you really need more than 5 address for a demo wallet"); "Hey do you really need more than 5 address for a demo wallet");

View File

@ -15,7 +15,6 @@ import org.ethereum.core.Transaction;
import org.ethereum.core.Wallet; import org.ethereum.core.Wallet;
import org.ethereum.crypto.ECKey; import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.HashUtil; import org.ethereum.crypto.HashUtil;
import org.ethereum.db.DatabaseImpl;
import org.ethereum.db.Repository; import org.ethereum.db.Repository;
import org.ethereum.vm.Program; import org.ethereum.vm.Program;
import org.ethereum.vm.ProgramInvoke; import org.ethereum.vm.ProgramInvoke;
@ -39,22 +38,19 @@ public class WorldManager {
private Logger logger = LoggerFactory.getLogger("main"); private Logger logger = LoggerFactory.getLogger("main");
private Logger stateLogger = LoggerFactory.getLogger("state"); private Logger stateLogger = LoggerFactory.getLogger("state");
private Blockchain blockChain; private Blockchain blockchain;
private Wallet wallet = new Wallet(); private Repository repository;
private Wallet wallet;
private Map<String, Transaction> pendingTransactions = Collections private Map<String, Transaction> pendingTransactions = Collections
.synchronizedMap(new HashMap<String, Transaction>()); .synchronizedMap(new HashMap<String, Transaction>());
public DatabaseImpl chainDB = new DatabaseImpl("blockchain"); private static WorldManager instance;
public Repository repository = new Repository();
public static WorldManager instance = new WorldManager();
public WorldManager() { public WorldManager() {
} this.blockchain = new Blockchain();
this.repository = new Repository();
public void loadChain() { this.wallet = new Wallet();
// Initialize Wallet // Initialize Wallet
byte[] cowAddr = HashUtil.sha3("cow".getBytes()); byte[] cowAddr = HashUtil.sha3("cow".getBytes());
ECKey key = ECKey.fromPrivate(cowAddr); ECKey key = ECKey.fromPrivate(cowAddr);
@ -68,15 +64,25 @@ public class WorldManager {
wallet.importKey(cbAddr); wallet.importKey(cbAddr);
// Initialize Blockchain // Initialize Blockchain
blockChain = new Blockchain(wallet); blockchain.setWallet(wallet);
blockChain.loadChain(); }
public void loadBlockChain() {
this.blockchain.load();
}
public static WorldManager getInstance() {
if(instance == null) {
instance = new WorldManager();
}
return instance;
} }
public void applyTransaction(Transaction tx, byte[] coinbase) { public void applyTransaction(Transaction tx, byte[] coinbase) {
// TODO: refactor the wallet pending transactions to the world manager // TODO: refactor the wallet pending transactions to the world manager
if (blockChain != null) if (blockchain != null)
blockChain.addWalletTransaction(tx); blockchain.addWalletTransaction(tx);
// TODO: what is going on with simple wallet transfer ? // TODO: what is going on with simple wallet transfer ?
@ -192,7 +198,7 @@ public class WorldManager {
byte[] initCode = tx.getData(); byte[] initCode = tx.getData();
Block lastBlock = blockChain.getLastBlock(); Block lastBlock = blockchain.getLastBlock();
ProgramInvoke programInvoke = ProgramInvokeFactory ProgramInvoke programInvoke = ProgramInvokeFactory
.createProgramInvoke(tx, lastBlock, trackRepository); .createProgramInvoke(tx, lastBlock, trackRepository);
@ -214,7 +220,7 @@ public class WorldManager {
.getReceiveAddress()); .getReceiveAddress());
if (programCode != null) { if (programCode != null) {
Block lastBlock = blockChain.getLastBlock(); Block lastBlock = blockchain.getLastBlock();
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.info("calling for existing contract: addres={}", logger.info("calling for existing contract: addres={}",
@ -267,7 +273,7 @@ public class WorldManager {
bodyCode = result.getHReturn().array(); bodyCode = result.getHReturn().array();
} }
BigInteger gasPrice = BigInteger.valueOf(blockChain.getGasPrice()); BigInteger gasPrice = BigInteger.valueOf(blockchain.getGasPrice());
BigInteger refund = gasDebit.subtract(BigInteger.valueOf( BigInteger refund = gasDebit.subtract(BigInteger.valueOf(
result.getGasUsed()).multiply(gasPrice)); result.getGasUsed()).multiply(gasPrice));
@ -316,8 +322,12 @@ public class WorldManager {
} }
} }
public Repository getRepository() {
return repository;
}
public Blockchain getBlockChain() { public Blockchain getBlockChain() {
return blockChain; return blockchain;
} }
public Wallet getWallet() { public Wallet getWallet() {
@ -325,7 +335,7 @@ public class WorldManager {
} }
public void close() { public void close() {
chainDB.close(); blockchain.close();
repository.close(); repository.close();
} }
} }

View File

@ -254,7 +254,7 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
}, 3000, secToAskForChain * 1000); }, 3000, secToAskForChain * 1000);
} }
WorldManager.instance.getBlockChain().addBlocks(blockList); WorldManager.getInstance().getBlockChain().addBlocks(blockList);
if (peerListener != null) peerListener.console(blocksMessage.toString()); if (peerListener != null) peerListener.console(blocksMessage.toString());
} }
@ -354,7 +354,7 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
private void sendGetChain(ChannelHandlerContext ctx) { private void sendGetChain(ChannelHandlerContext ctx) {
byte[] hash = WorldManager.instance.getBlockChain().getLatestBlockHash(); byte[] hash = WorldManager.getInstance().getBlockChain().getLatestBlockHash();
GetChainMessage chainMessage = new GetChainMessage((byte)100, hash); GetChainMessage chainMessage = new GetChainMessage((byte)100, hash);
chainMessage.toString(); chainMessage.toString();

View File

@ -34,7 +34,7 @@ public class TransactionTask implements Callable<Transaction> {
ClientPeer peer = MainData.instance.getActivePeer(); ClientPeer peer = MainData.instance.getActivePeer();
WalletTransaction walletTransaction = WorldManager.instance WalletTransaction walletTransaction = WorldManager.getInstance()
.getBlockChain().addWalletTransaction(tx); .getBlockChain().addWalletTransaction(tx);
peer.sendTransaction(tx); peer.sendTransaction(tx);
@ -44,7 +44,7 @@ public class TransactionTask implements Callable<Transaction> {
logger.info("return approved: {}", walletTransaction.getApproved()); logger.info("return approved: {}", walletTransaction.getApproved());
} catch (Throwable th) { } catch (Throwable th) {
logger.info("exception caugh: {}", th.getCause()); logger.info("exception caugh: {}", th.getCause());
WorldManager.instance.getBlockChain().removeWalletTransaction(tx); WorldManager.getInstance().getBlockChain().removeWalletTransaction(tx);
} }
return null; return null;
} }

View File

@ -24,8 +24,8 @@ public class TrackTrie implements TrieFacade {
} }
public void startTrack() { public void startTrack() {
changes = new HashMap<ByteArrayWrapper, byte[]>(); changes = new HashMap<>();
deletes = new HashMap<ByteArrayWrapper, byte[]>(); deletes = new HashMap<>();
trackingChanges = true; trackingChanges = true;
} }
@ -38,8 +38,8 @@ public class TrackTrie implements TrieFacade {
} }
public void rollbackTrack() { public void rollbackTrack() {
changes = new HashMap<ByteArrayWrapper, byte[]>(); changes = new HashMap<>();
deletes = new HashMap<ByteArrayWrapper, byte[]>(); deletes = new HashMap<>();
changes = null; changes = null;
trackingChanges = false; trackingChanges = false;
} }

View File

@ -75,7 +75,7 @@ samples.dir = samples
# the existing database will be # the existing database will be
# destroyed and all the data will be # destroyed and all the data will be
# downloaded from peers again # downloaded from peers again
database.reset = false database.reset = true
# this string is computed # this string is computed
# to be eventually the address # to be eventually the address

View File

@ -3,7 +3,6 @@ package org.ethereum.core;
import java.math.BigInteger; import java.math.BigInteger;
import org.ethereum.manager.WorldManager; import org.ethereum.manager.WorldManager;
import org.ethereum.util.ByteUtil;
import org.spongycastle.util.encoders.Hex; import org.spongycastle.util.encoders.Hex;
import org.ethereum.core.Block; import org.ethereum.core.Block;
import org.ethereum.core.Genesis; import org.ethereum.core.Genesis;
@ -18,64 +17,11 @@ public class BlockTest {
private String CPP_PoC5_GENESIS_HEX_RLP_ENCODED = "f8abf8a7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a08dbd704eb38d1c2b73ee4788715ea5828a030650829703f077729b2b613dd20680834000008080830f4240808080a004994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829c0c0"; private String CPP_PoC5_GENESIS_HEX_RLP_ENCODED = "f8abf8a7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a08dbd704eb38d1c2b73ee4788715ea5828a030650829703f077729b2b613dd20680834000008080830f4240808080a004994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829c0c0";
private String CPP_PoC5_GENESIS_HEX_HASH = "a7722d611450de26f55026b6544e34d9431b0a67a829e1794ac36fa4f079208f"; private String CPP_PoC5_GENESIS_HEX_HASH = "a7722d611450de26f55026b6544e34d9431b0a67a829e1794ac36fa4f079208f";
String block_1 = "f9072df8d3a077ef4fdaf389dca53236bcf7f72698e154eab2828f86fbc4fc6c" String block_1 = "f8abf8a7a0000000000000000000000000000000000000000000000000000000"
+ "d9225d285c89a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0" + "0000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d"
+ "a142fd40d493479476f5eabe4b342ee56b8ceba6ab2a770c3e2198e7a0faa0ca" + "49347940000000000000000000000000000000000000000a08dbd704eb38d1c2b73ee47"
+ "43105f667dceb168eb4e0cdc98ef28a9da5c381edef70d843207601719a06785" + "88715ea5828a030650829703f077729b2b613dd20680834000008080830f4240808080a"
+ "f3860460b2aa29122698e83a5151b270e82532c1663e89e3df8c5445b8ca833f" + "004994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829c0c0";
+ "f000018609184e72a000830f3e6f8227d2845387c58f80a00000000000000000"
+ "0000000000000000000000000000000094148d7738f78c04f90654f8c6f8a080"
+ "8609184e72a00082271094000000000000000000000000000000000000000080"
+ "b83a33604557602a5160106000396000f200604556330e0f602a59366000530a"
+ "0f602a596020600053013560005335576040600053016000546009581ca033a6"
+ "bfa5eb2f4b63f1b98bed9a987d096d32e56deecb050367c84955508f5365a015"
+ "034e7574ec073f0c448aac1d9f844387610dfef5342834b6825fbc35df5913a0"
+ "ee258e73d41ada73d8d6071ba7d236fbbe24fcfb9627fbd4310e24ffd87b961a"
+ "8203e9f90194f9016d018609184e72a000822710940000000000000000000000"
+ "00000000000000000080b901067f4e616d655265670000000000000000000000"
+ "00000000000000000000000000003057307f4e616d6552656700000000000000"
+ "000000000000000000000000000000000000577f436f6e666967000000000000"
+ "000000000000000000000000000000000000000073ccdeac59d35627b7de0933"
+ "2e819d5159e7bb72505773ccdeac59d35627b7de09332e819d5159e7bb72507f"
+ "436f6e6669670000000000000000000000000000000000000000000000000000"
+ "57336045576041516100c56000396000f20036602259604556330e0f600f5933"
+ "ff33560f601e5960003356576000335700604158600035560f602b590033560f"
+ "603659600033565733600035576000353357001ca0f3c527e484ea5546189979"
+ "c767b69aa9f1ad5a6f4b6077d4bccf5142723a67c9a069a4a29a2a315102fcd0"
+ "822d39ad696a6d7988c993bb2b911cc2a78bb8902d91a01ebe4782ea3ed224cc"
+ "bb777f5de9ee7b5bbb282ac08f7fa0ef95d3d1c1c6d1a1820ef7f8ccf8a60286"
+ "09184e72a00082271094ccdeac59d35627b7de09332e819d5159e7bb725080b8"
+ "4000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000002d0aceee7e5ab874e22ccf8d1a649f59106d74"
+ "e81ba095ad45bf574c080e4d72da2cfd3dbe06cc814c1c662b5f74561f13e1e7"
+ "5058f2a057745a3db5482bccb5db462922b074f4b79244c4b1fa811ed094d728"
+ "e7b6da92a08599ea5d6cb6b9ad3311f0d82a3337125e05f4a82b9b0556cb3776"
+ "a6e1a02f8782132df8abf885038609184e72a000822710942d0aceee7e5ab874"
+ "e22ccf8d1a649f59106d74e880a0476176000000000000000000000000000000"
+ "00000000000000000000000000001ca09b5fdabd54ebc284249d2d2df6d43875"
+ "cb86c52bd2bac196d4f064c8ade054f2a07b33f5c8b277a408ec38d2457441d2"
+ "af32e55681c8ecb28eef3d2a152e8db5a9a0227a67fceb1bf4ddd31a7047e24b"
+ "e93c947ab3b539471555bb3509ed6e393c8e82178df90277f90250048609184e"
+ "72a0008246dd94000000000000000000000000000000000000000080b901e961"
+ "010033577f476176436f696e0000000000000000000000000000000000000000"
+ "000000000060005460006000600760006000732d0aceee7e5ab874e22ccf8d1a"
+ "649f59106d74e860645c03f150436000576000600157620f424060025761017d"
+ "5161006c6000396000f2006020360e0f61013f59602060006000374360205460"
+ "0056600054602056602054437f6e000000000000000000000000000000000000"
+ "00000000000000000000000000560e0f0f61008059437f6e0000000000000000"
+ "0000000000000000000000000000000000000000000000576000602054610400"
+ "60005304600053036000547f6400000000000000000000000000000000000000"
+ "0000000000000000000000005660016000030460406000200a0f61013e596001"
+ "60205301602054600a6020530b0f6100f45961040060005304600053017f6400"
+ "0000000000000000000000000000000000000000000000000000000000005760"
+ "20537f6900000000000000000000000000000000000000000000000000000000"
+ "000000576000537f640000000000000000000000000000000000000000000000"
+ "000000000000000057006040360e0f0f61014a59003356604054600035566060"
+ "546020356080546080536040530a0f6101695900608053604053033357608053"
+ "60605301600035571ba0190fc7ab634dc497fe1656fde523a4c26926d51a93db"
+ "2ba37af8e83c3741225da066ae0ec1217b0ca698a5369d4881e1c4cbde56af99"
+ "31ebf9281580a23b659c08a051f947cb2315d0259f55848c630caa10cd91d6e4"
+ "4ff8bad7758c65b25e2191308227d2c0";
String block_2 = "f8b5f8b1a0cf4b25b08b39350304fe12a16e4216c01a426f8f3dbf0d392b5b45" String block_2 = "f8b5f8b1a0cf4b25b08b39350304fe12a16e4216c01a426f8f3dbf0d392b5b45"
+ "8ffb6a399da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a1" + "8ffb6a399da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a1"
@ -169,8 +115,7 @@ public class BlockTest {
assertEquals(new BigInteger(1, Genesis.DIFFICULTY), difficulty); assertEquals(new BigInteger(1, Genesis.DIFFICULTY), difficulty);
// Storing genesis because the parent needs to be in the DB for calculation. // Storing genesis because the parent needs to be in the DB for calculation.
WorldManager.instance.chainDB.put(ByteUtil.longToBytes(Genesis.NUMBER), WorldManager.getInstance().getBlockChain().addBlock(genesis);
genesis.getEncoded());
Block block1 = new Block(Hex.decode(block_1)); Block block1 = new Block(Hex.decode(block_1));
BigInteger calcDifficulty = new BigInteger(1, block1.calcDifficulty()); BigInteger calcDifficulty = new BigInteger(1, block1.calcDifficulty());
@ -179,20 +124,20 @@ public class BlockTest {
System.out.println("Block#1 calculated difficulty = " + calcDifficulty.toString()); System.out.println("Block#1 calculated difficulty = " + calcDifficulty.toString());
assertEquals(actualDifficulty, calcDifficulty); assertEquals(actualDifficulty, calcDifficulty);
} finally { } finally {
WorldManager.instance.close(); WorldManager.getInstance().close();
} }
} }
@Test @Test
public void testCalcGasLimit() { public void testCalcGasLimit() {
WorldManager.getInstance();
Block genesis = Genesis.getInstance(); Block genesis = Genesis.getInstance();
long gasLimit = genesis.calcGasLimit(); long gasLimit = genesis.calcGasLimit();
System.out.println("Genesis gasLimit = " + gasLimit); System.out.println("Genesis gasLimit = " + gasLimit);
assertEquals(Genesis.GAS_LIMIT, gasLimit); assertEquals(Genesis.GAS_LIMIT, gasLimit);
// Storing genesis because the parent needs to be in the DB for calculation. // Storing genesis because the parent needs to be in the DB for calculation.
WorldManager.instance.chainDB.put(ByteUtil.longToBytes(Genesis.NUMBER), WorldManager.getInstance().getBlockChain().addBlock(genesis);
genesis.getEncoded());
// Test with block // Test with block
Block block1 = new Block(Hex.decode(block_1)); Block block1 = new Block(Hex.decode(block_1));