ContractCallDialong:

+ enhanced with the option to see contract details: storage/code
+ refactored Block Chain into a WorldManager
This commit is contained in:
romanman 2014-06-15 20:08:35 +01:00
parent 1e6835f71d
commit f3e57269bd
14 changed files with 284 additions and 85 deletions

View File

@ -48,7 +48,6 @@ public class Blockchain {
public Blockchain(Wallet wallet) { public Blockchain(Wallet wallet) {
this.db = WorldManager.instance.chainDB; this.db = WorldManager.instance.chainDB;
this.wallet = wallet; this.wallet = wallet;
this.loadChain();
} }
public Block getLastBlock() { public Block getLastBlock() {
@ -162,24 +161,31 @@ public class Blockchain {
public void loadChain() { public void loadChain() {
DBIterator iterator = db.iterator(); DBIterator iterator = db.iterator();
try { try {
if (!iterator.hasNext()) { if (index.size() == 0) {
logger.info("DB is empty - adding Genesis"); logger.info("DB is empty - adding Genesis");
Block genesis = Genesis.getInstance(); Block genesis = Genesis.getInstance();
this.addBlock(genesis); this.addBlock(genesis);
logger.debug("Block: " + genesis.getNumber() + " ---> " + genesis.toFlatString()); logger.debug("Block: " + genesis.getNumber() + " ---> " + genesis.toFlatString());
db.put(genesis.getParentHash(), genesis.getEncoded()); db.put(genesis.getParentHash(), genesis.getEncoded());
} else { }
logger.debug("Displaying blocks stored in DB sorted on blocknumber");
byte[] parentHash = Genesis.PARENT_HASH; // get Genesis block by parentHash logger.debug("Displaying blocks stored in DB sorted on blocknumber");
for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { byte[] parentHash = Genesis.PARENT_HASH; // get Genesis block by parentHash
byte[] parentRLP = db.get(parentHash); for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) {
if (parentRLP == null) return;
byte[] parentRLP = db.get(parentHash);
if (parentRLP == null) return;
Block block = new Block(parentRLP);
this.addBlock(block);
// in case of cold load play the contracts
WorldManager.instance.applyBlock(block);
if (logger.isDebugEnabled())
logger.debug("Block: " + getLastBlock().getNumber() + " ---> " + getLastBlock().toFlatString());
parentHash = getLastBlock().getHash();
this.addBlock(new Block(parentRLP));
if (logger.isDebugEnabled())
logger.debug("Block: " + getLastBlock().getNumber() + " ---> " + getLastBlock().toFlatString());
parentHash = getLastBlock().getHash();
}
} }
} finally { } finally {
// Make sure you close the iterator to avoid resource leaks. // Make sure you close the iterator to avoid resource leaks.

View File

@ -2,6 +2,7 @@ package org.ethereum.gui;
import org.ethereum.core.Block; import org.ethereum.core.Block;
import org.ethereum.manager.MainData; import org.ethereum.manager.MainData;
import org.ethereum.manager.WorldManager;
import javax.swing.*; import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableCellRenderer;
@ -74,9 +75,9 @@ public class BlockChainTable extends JFrame {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (MainData.instance.getBlockchain().getSize() - 1 < lastFindIndex) return; if (WorldManager.instance.getBlockChain().getSize() - 1 < lastFindIndex) return;
Block block = MainData.instance.getBlockchain().getByNumber(lastFindIndex); Block block = WorldManager.instance.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);
@ -96,10 +97,10 @@ public class BlockChainTable extends JFrame {
return; return;
} }
for (int i = lastFindIndex + 1; i < MainData.instance.getBlockchain().getSize(); ++i) { for (int i = lastFindIndex + 1; i < WorldManager.instance.getBlockChain().getSize(); ++i) {
if (MainData.instance.getBlockchain().getSize() - 1 < i) return; if (WorldManager.instance.getBlockChain().getSize() - 1 < i) return;
Block block = MainData.instance.getBlockchain().getByNumber(i); Block block = WorldManager.instance.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

@ -2,6 +2,7 @@ package org.ethereum.gui;
import org.ethereum.core.Block; import org.ethereum.core.Block;
import org.ethereum.manager.MainData; import org.ethereum.manager.MainData;
import org.ethereum.manager.WorldManager;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
@ -16,7 +17,7 @@ public class BlockTableModel extends AbstractTableModel {
public int getRowCount() { public int getRowCount() {
fireTableDataChanged(); fireTableDataChanged();
int rowCount = MainData.instance.getBlockchain().getSize(); int rowCount = WorldManager.instance.getBlockChain().getSize();
return rowCount; return rowCount;
} }
@ -31,7 +32,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 = MainData.instance.getBlockchain().getByNumber(rowIndex); Block block = WorldManager.instance.getBlockChain().getByNumber(rowIndex);
if (block == null) return ""; if (block == null) return "";
return block.toString(); return block.toString();

View File

@ -1,5 +1,6 @@
package org.ethereum.gui; package org.ethereum.gui;
import com.sun.javafx.binding.StringFormatter;
import org.ethereum.core.Account; import org.ethereum.core.Account;
import org.ethereum.core.AccountState; import org.ethereum.core.AccountState;
import org.ethereum.core.ContractDetails; import org.ethereum.core.ContractDetails;
@ -9,6 +10,7 @@ import org.ethereum.manager.WorldManager;
import org.ethereum.net.client.ClientPeer; import org.ethereum.net.client.ClientPeer;
import org.ethereum.util.ByteUtil; import org.ethereum.util.ByteUtil;
import org.ethereum.util.Utils; import org.ethereum.util.Utils;
import org.ethereum.vm.DataWord;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.spongycastle.util.BigIntegers; import org.spongycastle.util.BigIntegers;
@ -16,17 +18,22 @@ import org.spongycastle.util.encoders.Hex;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.Border; import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.plaf.ComboBoxUI; import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.basic.BasicComboBoxUI; import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup; import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.URL; import java.net.URL;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
/** /**
* www.ethereumJ.com * www.ethereumJ.com
@ -42,8 +49,14 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
JComboBox<AccountWrapper> creatorAddressCombo; JComboBox<AccountWrapper> creatorAddressCombo;
final JTextField gasInput; final JTextField gasInput;
final JTextField contractAddrInput; final JTextField contractAddrInput;
JScrollPane contractDataInput;
JTextArea msgDataTA; JTextArea msgDataTA;
JLabel statusMsg = null; JLabel statusMsg = null;
JLabel playLabel = null;
JLabel rejectLabel = null;
JLabel approveLabel = null;
public ContractCallDialog(Frame parent) { public ContractCallDialog(Frame parent) {
super(parent, "Call Contract: ", false); super(parent, "Call Contract: ", false);
@ -51,6 +64,20 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
contractAddrInput = new JTextField(5); contractAddrInput = new JTextField(5);
GUIUtils.addStyle(contractAddrInput, "Contract Address: "); GUIUtils.addStyle(contractAddrInput, "Contract Address: ");
contractAddrInput.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
populateContractDetails();
}
});
}
});
contractAddrInput.setBounds(70, 30, 350, 45); contractAddrInput.setBounds(70, 30, 350, 45);
this.getContentPane().add(contractAddrInput); this.getContentPane().add(contractAddrInput);
@ -60,9 +87,9 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
msgDataTA = new JTextArea(); msgDataTA = new JTextArea();
msgDataTA.setLineWrap(true); msgDataTA.setLineWrap(true);
JScrollPane contractDataInput = new JScrollPane(msgDataTA); contractDataInput = new JScrollPane(msgDataTA);
GUIUtils.addStyle(msgDataTA, null, false); GUIUtils.addStyle(msgDataTA, null, false);
GUIUtils.addStyle(contractDataInput, "Data:"); GUIUtils.addStyle(contractDataInput, "Input:");
msgDataTA.setText(""); msgDataTA.setText("");
msgDataTA.setCaretPosition(0); msgDataTA.setCaretPosition(0);
@ -78,20 +105,19 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
URL rejectIconURL = ClassLoader.getSystemResource("buttons/reject.png"); URL rejectIconURL = ClassLoader.getSystemResource("buttons/reject.png");
ImageIcon rejectIcon = new ImageIcon(rejectIconURL); ImageIcon rejectIcon = new ImageIcon(rejectIconURL);
JLabel rejectLabel = new JLabel(rejectIcon); rejectLabel = new JLabel(rejectIcon);
rejectLabel.setToolTipText("Cancel"); rejectLabel.setToolTipText("Cancel");
rejectLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); rejectLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
URL playIconURL = ClassLoader.getSystemResource("buttons/play.png"); URL playIconURL = ClassLoader.getSystemResource("buttons/play.png");
ImageIcon playIcon = new ImageIcon(playIconURL); ImageIcon playIcon = new ImageIcon(playIconURL);
JLabel playLabel = new JLabel(playIcon); playLabel = new JLabel(playIcon);
playLabel.setToolTipText("Play Drafted"); playLabel.setToolTipText("Play Drafted");
playLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); playLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
playLabel.addMouseListener( playLabel.addMouseListener(
new MouseAdapter() { new MouseAdapter() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
ContractCallDialog.this.playContractCall(); ContractCallDialog.this.playContractCall();
}} }}
); );
@ -118,7 +144,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
URL approveIconURL = ClassLoader.getSystemResource("buttons/approve.png"); URL approveIconURL = ClassLoader.getSystemResource("buttons/approve.png");
ImageIcon approveIcon = new ImageIcon(approveIconURL); ImageIcon approveIcon = new ImageIcon(approveIconURL);
JLabel approveLabel = new JLabel(approveIcon); approveLabel = new JLabel(approveIcon);
approveLabel.setToolTipText("Submit the transaction"); approveLabel.setToolTipText("Submit the transaction");
approveLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); approveLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
@ -157,7 +183,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
editor.setForeground(Color.RED); editor.setForeground(Color.RED);
Collection<Account> accounts = Collection<Account> accounts =
MainData.instance.getWallet().getAccountCollection(); WorldManager.instance.getWallet().getAccountCollection();
for (Account account : accounts){ for (Account account : accounts){
creatorAddressCombo.addItem(new AccountWrapper(account)); creatorAddressCombo.addItem(new AccountWrapper(account));
@ -191,7 +217,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
((AbstractButton) creatorAddressCombo.getComponent(i)).setBorder(line); ((AbstractButton) creatorAddressCombo.getComponent(i)).setBorder(line);
} }
} }
creatorAddressCombo.setBounds(73, 267, 230, 36); creatorAddressCombo.setBounds(70, 267, 230, 36);
this.getContentPane().add(creatorAddressCombo); this.getContentPane().add(creatorAddressCombo);
this.getContentPane().revalidate(); this.getContentPane().revalidate();
@ -199,6 +225,117 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
this.setResizable(false); this.setResizable(false);
} }
private void populateContractDetails() {
String contractAddr = contractAddrInput.getText();
if (!Pattern.matches("[0-9a-fA-F]+", contractAddr) || (contractAddr.length() != 40)){
return;
}
byte[] contractAddress = Hex.decode( contractAddr );
byte[] contractStateB = WorldManager.instance.worldState.get(contractAddress);
if (contractStateB == null || contractStateB.length == 0){
return;
}
AccountState contractState = new AccountState(contractStateB);
final byte[] programCode = WorldManager.instance.chainDB.get(contractState.getCodeHash());
if (programCode == null || programCode.length == 0){
return;
}
byte[] contractDetailsB =
WorldManager.instance.detaildDB.get(contractAddress);
ContractDetails contractDetails = null;
final Map storageMap = new HashMap();
if (contractDetailsB != null){
contractDetails = new ContractDetails(contractDetailsB);
Map<DataWord, DataWord> tmpStorage = contractDetails.getStorage();
if (tmpStorage != null){
for (DataWord key : tmpStorage.keySet()){
String keyToSave = Hex.toHexString (key.getNoLeadZeroesData());
String valueToSave = Hex.toHexString (tmpStorage.get(key).getNoLeadZeroesData());
storageMap.put(keyToSave, valueToSave);
}
}
}
contractDataInput.setBounds(70, 80, 350, 145);
contractDataInput.setViewportView(msgDataTA);
URL expandIconURL = ClassLoader.getSystemResource("buttons/add-23x23.png");
ImageIcon expandIcon = new ImageIcon(expandIconURL);
final JLabel expandLabel = new JLabel(expandIcon);
expandLabel.setToolTipText("Cancel");
expandLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
expandLabel.setBounds(235, 232, 23, 23);
this.getContentPane().add(expandLabel);
expandLabel.setVisible(true);
final Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
final JPanel detailPanel = new JPanel();
detailPanel.setBorder(border);
detailPanel.setBounds(135, 242, 230, 2);
final JPanel spacer = new JPanel();
spacer.setForeground(Color.white);
spacer.setBackground(Color.white);
spacer.setBorder(null);
spacer.setBounds(225, 232, 40, 20);
this.getContentPane().add(spacer);
this.getContentPane().add(detailPanel);
expandLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
ContractCallDialog.this.setSize(500, 530);
ContractCallDialog.this.creatorAddressCombo.setBounds(70, 367, 230, 36);
ContractCallDialog.this.gasInput.setBounds(330, 360, 90, 45);
ContractCallDialog.this.rejectLabel.setBounds(260, 425, 45, 45);
ContractCallDialog.this.approveLabel.setBounds(200, 425, 45, 45);
ContractCallDialog.this.statusMsg.setBounds(50, 460, 400, 50);
spacer.setVisible(false);
expandLabel.setVisible(false);
detailPanel.setVisible(false);
JTextField contractCode = new JTextField(15);
contractCode.setText(Hex.toHexString( programCode ));
GUIUtils.addStyle(contractCode, "Code: ");
contractCode.setBounds(70, 230, 350, 45);
JTable storage = new JTable(2, 2);
storage.setTableHeader(null);
storage.setShowGrid(false);
storage.setIntercellSpacing(new Dimension(15, 0));
storage.setCellSelectionEnabled(false);
GUIUtils.addStyle(storage);
JTableStorageModel tableModel = new JTableStorageModel(storageMap);
storage.setModel(tableModel);
JScrollPane scrollPane = new JScrollPane(storage);
scrollPane.setBorder(null);
scrollPane.getViewport().setBackground(Color.WHITE);
scrollPane.setBounds(70, 290, 350, 50);
ContractCallDialog.this.getContentPane().add(contractCode);
ContractCallDialog.this.getContentPane().add(scrollPane);
}
});
this.repaint();
}
private void playContractCall() { private void playContractCall() {
@ -226,7 +363,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, MainData.instance.getBlockchain().getLastBlock(), contractDetails); ProgramPlayDialog.createAndShowGUI(programCode, tx, WorldManager.instance.getBlockChain().getLastBlock(), contractDetails);
} }
protected JRootPane createRootPane() { protected JRootPane createRootPane() {
@ -355,5 +492,38 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
return result; return result;
} }
} }
private class JTableStorageModel extends DefaultTableModel {
private JTableStorageModel(Map<String, String> data) {
if (data != null){
this.setColumnCount(2);
this.setRowCount(data.size());
int i = 0;
for (String key : data.keySet()){
this.setValueAt(key, i, 0);
this.setValueAt(data.get(key), i, 1);
++i;
}
}
}
}
public static void main(String args[]){
WorldManager.instance.getWallet();
WorldManager.instance.loadChain();
ContractCallDialog ccd = new ContractCallDialog(null);
ccd.setVisible(true);
ccd.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
ccd.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
WorldManager.instance.close();
}
});
}
} }

View File

@ -109,7 +109,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,
MainData.instance.getBlockchain().getLastBlock(), null); WorldManager.instance.getBlockChain().getLastBlock(), null);
}} }}
); );
@ -174,7 +174,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
editor.setForeground(Color.RED); editor.setForeground(Color.RED);
Collection<Account> accounts = Collection<Account> accounts =
MainData.instance.getWallet().getAccountCollection(); WorldManager.instance.getWallet().getAccountCollection();
for (Account account : accounts){ for (Account account : accounts){
creatorAddressCombo.addItem(new AccountWrapper(account)); creatorAddressCombo.addItem(new AccountWrapper(account));
@ -314,7 +314,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
Account account = ((AccountWrapper)creatorAddressCombo.getSelectedItem()).getAccount(); Account account = ((AccountWrapper)creatorAddressCombo.getSelectedItem()).getAccount();
BigInteger currentBalance = account.getState().getBalance(); BigInteger currentBalance = account.getState().getBalance();
BigInteger gasPrice = BigInteger.valueOf(MainData.instance.getBlockchain().getGasPrice()); BigInteger gasPrice = BigInteger.valueOf(WorldManager.instance.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

@ -2,6 +2,7 @@ package org.ethereum.gui;
import org.ethereum.core.Transaction; import org.ethereum.core.Transaction;
import org.ethereum.manager.MainData; import org.ethereum.manager.MainData;
import org.ethereum.manager.WorldManager;
import org.ethereum.net.submit.TransactionExecutor; import org.ethereum.net.submit.TransactionExecutor;
import org.ethereum.net.submit.TransactionTask; import org.ethereum.net.submit.TransactionTask;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -58,7 +59,7 @@ public class DialogWorker extends SwingWorker {
} }
dialog.infoStatusMsg("Transaction got approved"); dialog.infoStatusMsg("Transaction got approved");
MainData.instance.getWallet().applyTransaction(tx); WorldManager.instance.getWallet().applyTransaction(tx);
return null; return null;
} }
} }

View File

@ -64,6 +64,11 @@ public class GUIUtils {
jScrollPane.setHorizontalScrollBar(null); jScrollPane.setHorizontalScrollBar(null);
} }
public static void addStyle(JTable jTable){
jTable.setForeground(new Color(143, 170, 220));
jTable.setBackground(Color.WHITE);
jTable.setFont(new Font("Monospaced", 0, 13));
}
public static String getHexStyledText(byte[] data){ public static String getHexStyledText(byte[] data){
String[] dataHex = Hex.toHexString(data).split("(?<=\\G.{2})"); String[] dataHex = Hex.toHexString(data).split("(?<=\\G.{2})");

View File

@ -4,6 +4,7 @@ import org.ethereum.core.Account;
import org.ethereum.core.AccountState; import org.ethereum.core.AccountState;
import org.ethereum.core.Transaction; import org.ethereum.core.Transaction;
import org.ethereum.manager.MainData; import org.ethereum.manager.MainData;
import org.ethereum.manager.WorldManager;
import org.ethereum.net.client.ClientPeer; import org.ethereum.net.client.ClientPeer;
import org.spongycastle.util.BigIntegers; import org.spongycastle.util.BigIntegers;
import org.spongycastle.util.encoders.Hex; import org.spongycastle.util.encoders.Hex;
@ -118,7 +119,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog {
byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes(); byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes();
byte[] nonce = addressState.getNonce() == BigInteger.ZERO ? null : addressState.getNonce().toByteArray(); byte[] nonce = addressState.getNonce() == BigInteger.ZERO ? null : addressState.getNonce().toByteArray();
byte[] gasPrice = BigInteger.valueOf( MainData.instance.getBlockchain().getGasPrice()).toByteArray(); byte[] gasPrice = BigInteger.valueOf( WorldManager.instance.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
@ -193,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(MainData.instance.getBlockchain().getGasPrice()); BigInteger gasPrice = BigInteger.valueOf(WorldManager.instance.getBlockChain().getGasPrice());
BigInteger currentBalance = addressState.getBalance(); BigInteger currentBalance = addressState.getBalance();
boolean canAfford = gasPrice.multiply(feeValue).add(ammountValue).compareTo(currentBalance) != 1; boolean canAfford = gasPrice.multiply(feeValue).add(ammountValue).compareTo(currentBalance) != 1;

View File

@ -3,6 +3,7 @@ package org.ethereum.gui;
import org.ethereum.core.Account; import org.ethereum.core.Account;
import org.ethereum.core.Wallet; import org.ethereum.core.Wallet;
import org.ethereum.manager.MainData; import org.ethereum.manager.MainData;
import org.ethereum.manager.WorldManager;
import javax.swing.*; import javax.swing.*;
@ -41,7 +42,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 = MainData.instance.getWallet(); Wallet wallet = WorldManager.instance.getWallet();
wallet.addListener(this); wallet.addListener(this);
loadWallet(); loadWallet();
@ -54,7 +55,7 @@ public class WalletWindow extends JFrame implements Wallet.WalletListener{
contentPane.removeAll(); contentPane.removeAll();
contentPane.setLayout(new FlowLayout()); contentPane.setLayout(new FlowLayout());
Wallet wallet = MainData.instance.getWallet(); Wallet wallet = WorldManager.instance.getWallet();
for (Account account : wallet.getAccountCollection()){ for (Account account : wallet.getAccountCollection()){
@ -76,7 +77,7 @@ public class WalletWindow extends JFrame implements Wallet.WalletListener{
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
Wallet wallet = MainData.instance.getWallet(); Wallet wallet = WorldManager.instance.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

@ -33,8 +33,6 @@ public class MainData {
Logger logger = LoggerFactory.getLogger(getClass().getName()); Logger logger = LoggerFactory.getLogger(getClass().getName());
private List<PeerData> peers = Collections.synchronizedList(new ArrayList<PeerData>()); private List<PeerData> peers = Collections.synchronizedList(new ArrayList<PeerData>());
private Blockchain blockChain;
private Wallet wallet = new Wallet();
private ClientPeer activePeer; private ClientPeer activePeer;
PeerDiscovery peerDiscovery; PeerDiscovery peerDiscovery;
@ -42,23 +40,6 @@ public class MainData {
public static MainData instance = new MainData(); public static MainData instance = new MainData();
public MainData() { public MainData() {
// Initialize Wallet
byte[] cowAddr = HashUtil.sha3("cow".getBytes());
ECKey key = ECKey.fromPrivate(cowAddr);
wallet.importKey(cowAddr);
AccountState state = wallet.getAccountState(key.getAddress());
state.addToBalance(BigInteger.valueOf(2).pow(200));
// wallet.importKey(HashUtil.sha3("cat".getBytes()));
String secret = CONFIG.coinbaseSecret();
byte[] cbAddr = HashUtil.sha3(secret.getBytes());
wallet.importKey(cbAddr);
// Initialize Blockchain
blockChain = new Blockchain(wallet);
// Initialize PeerData // Initialize PeerData
try { try {
@ -73,13 +54,6 @@ public class MainData {
} }
} }
public Blockchain getBlockchain() {
return blockChain;
}
public Wallet getWallet() {
return wallet;
}
public void setActivePeer(ClientPeer peer){ public void setActivePeer(ClientPeer peer){
this.activePeer = peer; this.activePeer = peer;

View File

@ -1,9 +1,7 @@
package org.ethereum.manager; package org.ethereum.manager;
import org.ethereum.core.AccountState; import org.ethereum.core.*;
import org.ethereum.core.Block; import org.ethereum.crypto.ECKey;
import org.ethereum.core.ContractDetails;
import org.ethereum.core.Transaction;
import org.ethereum.crypto.HashUtil; import org.ethereum.crypto.HashUtil;
import org.ethereum.db.DatabaseImpl; import org.ethereum.db.DatabaseImpl;
import org.ethereum.db.TrackDatabase; import org.ethereum.db.TrackDatabase;
@ -20,6 +18,8 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.ethereum.config.SystemProperties.CONFIG;
/** /**
* *
* WorldManager is the main class to handle the processing of transactions and managing the world state. * WorldManager is the main class to handle the processing of transactions and managing the world state.
@ -34,7 +34,10 @@ 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");
public static WorldManager instance = new WorldManager();
private Blockchain blockChain;
private Wallet wallet = new Wallet();
private Map<String, Transaction> pendingTransactions = private Map<String, Transaction> pendingTransactions =
Collections.synchronizedMap(new HashMap<String, Transaction>()); Collections.synchronizedMap(new HashMap<String, Transaction>());
@ -45,10 +48,37 @@ public class WorldManager {
public Trie worldState = new Trie(stateDB.getDb()); public Trie worldState = new Trie(stateDB.getDb());
public static WorldManager instance = new WorldManager();
public WorldManager() {
}
public void loadChain(){
// Initialize Wallet
byte[] cowAddr = HashUtil.sha3("cow".getBytes());
ECKey key = ECKey.fromPrivate(cowAddr);
wallet.importKey(cowAddr);
AccountState state = wallet.getAccountState(key.getAddress());
state.addToBalance(BigInteger.valueOf(2).pow(200));
// wallet.importKey(HashUtil.sha3("cat".getBytes()));
String secret = CONFIG.coinbaseSecret();
byte[] cbAddr = HashUtil.sha3(secret.getBytes());
wallet.importKey(cbAddr);
// Initialize Blockchain
blockChain = new Blockchain(wallet);
blockChain.loadChain();
}
public void applyTransaction(Transaction tx) { public void applyTransaction(Transaction tx) {
// TODO: refactor the wallet transactions to the world manager // TODO: refactor the wallet transactions to the world manager
MainData.instance.getBlockchain().addWalletTransaction(tx); if (blockChain != null)
blockChain.addWalletTransaction(tx);
// TODO: what is going on with simple wallet transfer // TODO: what is going on with simple wallet transfer
@ -167,7 +197,7 @@ public class WorldManager {
byte[] initCode = tx.getData(); byte[] initCode = tx.getData();
Block lastBlock = Block lastBlock =
MainData.instance.getBlockchain().getLastBlock(); blockChain.getLastBlock();
ProgramInvoke programInvoke = ProgramInvoke programInvoke =
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, null, trackDetailDB, trackChainDb, trackStateDB); ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, null, trackDetailDB, trackChainDb, trackStateDB);
@ -191,7 +221,7 @@ public class WorldManager {
if (programCode != null && programCode.length != 0){ if (programCode != null && programCode.length != 0){
Block lastBlock = Block lastBlock =
MainData.instance.getBlockchain().getLastBlock(); blockChain.getLastBlock();
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.info("calling for existing contract: addres={}" , Hex.toHexString(tx.getReceiveAddress())); logger.info("calling for existing contract: addres={}" , Hex.toHexString(tx.getReceiveAddress()));
@ -262,7 +292,7 @@ public class WorldManager {
} }
BigInteger gasPrice = BigInteger gasPrice =
BigInteger.valueOf( MainData.instance.getBlockchain().getGasPrice()); BigInteger.valueOf( blockChain.getGasPrice());
BigInteger refund = BigInteger refund =
gasDebit.subtract(BigInteger.valueOf( result.getGasUsed()).multiply(gasPrice)); gasDebit.subtract(BigInteger.valueOf( result.getGasUsed()).multiply(gasPrice));
@ -306,6 +336,14 @@ public class WorldManager {
} }
} }
public Blockchain getBlockChain() {
return blockChain;
}
public Wallet getWallet() {
return wallet;
}
public void close() { public void close() {
chainDB.close(); chainDB.close();
stateDB.close(); stateDB.close();

View File

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

View File

@ -2,6 +2,7 @@ package org.ethereum.net.submit;
import org.ethereum.core.Transaction; import org.ethereum.core.Transaction;
import org.ethereum.manager.MainData; import org.ethereum.manager.MainData;
import org.ethereum.manager.WorldManager;
import org.ethereum.net.client.ClientPeer; import org.ethereum.net.client.ClientPeer;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -34,8 +35,8 @@ public class TransactionTask implements Callable<Transaction> {
ClientPeer peer = MainData.instance.getActivePeer(); ClientPeer peer = MainData.instance.getActivePeer();
WalletTransaction walletTransaction = MainData.instance WalletTransaction walletTransaction = WorldManager.instance
.getBlockchain().addWalletTransaction(tx); .getBlockChain().addWalletTransaction(tx);
peer.sendTransaction(tx); peer.sendTransaction(tx);
while(walletTransaction.getApproved() < 1 ){ while(walletTransaction.getApproved() < 1 ){
@ -45,7 +46,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());
MainData.instance.getBlockchain().removeWalletTransaction(tx); WorldManager.instance.getBlockChain().removeWalletTransaction(tx);
} }
return null; return null;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB