Refactor Account inherits from AccountState

This commit is contained in:
nicksavers 2014-06-27 18:14:12 +02:00
parent f7f2f88946
commit 51292f8b20
8 changed files with 72 additions and 118 deletions

View File

@ -8,25 +8,22 @@ import org.ethereum.util.Utils;
/**
* Representation of an actual account or contract
*/
public class Account {
public class Account extends AccountState {
private ECKey ecKey;
private byte[] address;
private AccountState state;
public Account() {
this.ecKey = new ECKey(Utils.getRandom());
this.state = new AccountState();
}
public Account(ECKey ecKey) {
this.ecKey = ecKey;
this.state = new AccountState();
}
public Account(ECKey ecKey, BigInteger nonce, BigInteger balance) {
super(nonce, balance);
this.ecKey = ecKey;
this.state = new AccountState(nonce, balance);
}
public ECKey getEcKey() {
@ -40,12 +37,4 @@ public class Account {
public void setAddress(byte[] address) {
this.address = address;
}
public AccountState getState() {
return state;
}
public void setState(AccountState state) {
this.state = state;
}
}

View File

@ -64,18 +64,18 @@ public class Wallet {
public AccountState getAccountState(byte[] addressBytes){
String address = Hex.toHexString(addressBytes);
return rows.get(address).getState();
return rows.get(address);
}
public BigInteger getBalance(byte[] addressBytes){
String address = Hex.toHexString(addressBytes);
return rows.get(address).getState().getBalance();
return rows.get(address).getBalance();
}
public BigInteger totalBalance(){
BigInteger sum = BigInteger.ZERO;
for (Account account : rows.values()){
sum = sum.add(account.getState().getBalance());
sum = sum.add(account.getBalance());
}
return sum;
}
@ -89,17 +89,16 @@ public class Wallet {
if (sender != null){
BigInteger value = new BigInteger(-1, transaction.getValue());
sender.getState().addToBalance(value);
sender.getState().incrementNonce();
sender.addToBalance(value);
sender.incrementNonce();
}
byte[] receiveAddress = transaction.getReceiveAddress();
Account receiver = rows.get(Hex.toHexString(receiveAddress));
if (receiver != null){
receiver.getState().addToBalance(new BigInteger(1, transaction.getValue()));
receiver.addToBalance(new BigInteger(1, transaction.getValue()));
}
notifyListeners();
this.notifyListeners();
}
@ -232,7 +231,7 @@ public class Wallet {
privKey.setTextContent(Hex.toHexString(account.getEcKey().getPrivKeyBytes()));
Element value = doc.createElement("value");
value.setTextContent(account.getState().getBalance().toString());
value.setTextContent(account.getBalance().toString());
raw.appendChild(addressE);
raw.appendChild(privKey);

View File

@ -4,10 +4,8 @@ import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.ethereum.config.SystemProperties;
@ -16,7 +14,6 @@ import org.iq80.leveldb.DBIterator;
import org.iq80.leveldb.Options;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
/**
* Generic interface for Ethereum database
@ -26,12 +23,11 @@ import org.spongycastle.util.encoders.Hex;
* Pure Java: https://github.com/dain/leveldb
* JNI binding: https://github.com/fusesource/leveldbjni
*/
public class DatabaseImpl implements Database{
public class DatabaseImpl implements Database {
private static Logger logger = LoggerFactory.getLogger(DatabaseImpl.class);
private DB db;
private String name;
public DatabaseImpl(String name) {
// Initialize Database
@ -98,20 +94,15 @@ public class DatabaseImpl implements Database{
}
}
public List<ByteArrayWrapper> dumpKeys() {
DBIterator iterator = getDb().iterator();
ArrayList<ByteArrayWrapper> keys = new ArrayList<ByteArrayWrapper>();
public ArrayList<ByteArrayWrapper> dumpKeys(){
DBIterator iterator = getDb().iterator();
ArrayList<ByteArrayWrapper> keys = new ArrayList<>();
while(iterator.hasNext()){
ByteArrayWrapper key = new ByteArrayWrapper(iterator.next().getKey());
keys.add(key);
}
Collections.sort((List)keys);
return keys;
}
while (iterator.hasNext()) {
ByteArrayWrapper key = new ByteArrayWrapper(iterator.next().getKey());
keys.add(key);
}
Collections.sort((List<ByteArrayWrapper>) keys);
return keys;
}
}

View File

@ -16,7 +16,7 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.ethereum.config.SystemProperties.CONFIG;
@ -25,7 +25,7 @@ import static org.ethereum.config.SystemProperties.CONFIG;
*
*
***********************************************************************************
MainRepository
Repository
|
--> AccountState ---> Trie ---> leveldb (state) /key=address
--> nonce
@ -47,7 +47,7 @@ public class Repository {
private Logger logger = LoggerFactory.getLogger("repository");
Trie worldState;
public Trie worldState;
TrackTrie accountStateDB;
TrackDatabase contractDetailsDB;
@ -55,19 +55,15 @@ public class Repository {
// todo: Listeners listeners
// todo: cash impl
DatabaseImpl detailsDB = null;
DatabaseImpl stateDB = null;
private DatabaseImpl detailsDB = null;
private DatabaseImpl stateDB = null;
public Repository() {
detailsDB = new DatabaseImpl("details");
contractDetailsDB = new TrackDatabase(detailsDB);
stateDB = new DatabaseImpl("state");
worldState = new Trie(stateDB.getDb());
accountStateDB = new TrackTrie(worldState);
}
@ -77,33 +73,30 @@ public class Repository {
}
public Repository getTrack(){
TrackTrie trackState = new TrackTrie(accountStateDB);
TrackDatabase trackDetails = new TrackDatabase(contractDetailsDB);
return new Repository (trackState, trackDetails);
}
public void startTracking(){
public void startTracking() {
logger.info("start tracking");
accountStateDB.startTrack();
contractDetailsDB.startTrack();
}
public void commit(){
public void commit() {
logger.info("commit changes");
accountStateDB.commitTrack();
contractDetailsDB.commitTrack();
}
public void rollback(){
public void rollback() {
logger.info("rollback changes");
accountStateDB.rollbackTrack();
contractDetailsDB.rollbackTrack();
}
public AccountState createAccount(byte[] addr){
public AccountState createAccount(byte[] addr) {
// 1. Save AccountState
AccountState state = new AccountState();
@ -116,78 +109,67 @@ public class Repository {
if (logger.isInfoEnabled())
logger.info("New account created: [ {} ]", Hex.toHexString(addr));
return state;
}
public AccountState getAccountState(byte[] addr){
public AccountState getAccountState(byte[] addr) {
byte[] accountStateRLP = accountStateDB.get(addr);
if (accountStateRLP.length == 0){
if (accountStateRLP.length == 0){
if (logger.isInfoEnabled())
logger.info("No account: [ {} ]", Hex.toHexString(addr));
return null;
}
AccountState state = new AccountState(accountStateRLP);
return state;
}
public ContractDetails getContractDetails(byte[] addr){
public ContractDetails getContractDetails(byte[] addr) {
byte[] accountDetailsRLP = contractDetailsDB.get(addr);
byte[] accountDetailsRLP = contractDetailsDB.get(addr);
if (accountDetailsRLP == null){
if (accountDetailsRLP == null) {
if (logger.isInfoEnabled())
logger.info("No account: [ {} ]", Hex.toHexString(addr));
return null;
}
ContractDetails details = new ContractDetails(accountDetailsRLP);
return details;
}
if (logger.isInfoEnabled())
logger.info("No account: [ {} ]", Hex.toHexString(addr));
return null;
}
public BigInteger addBalance(byte[] address, BigInteger value) {
ContractDetails details = new ContractDetails(accountDetailsRLP);
return details;
}
AccountState state = getAccountState(address);
if (state == null)
return BigInteger.ZERO;
public BigInteger addBalance(byte[] address, BigInteger value){
BigInteger newBalance = state.addToBalance(value);
AccountState state = getAccountState(address);
if (state == null) return BigInteger.ZERO;
if (logger.isInfoEnabled())
logger.info("Changing balance: account: [ {} ] new balance: [ {} ]",
Hex.toHexString(address), newBalance.toString());
BigInteger newBalance = state.addToBalance(value);
if (logger.isInfoEnabled())
logger.info("Changing balance: account: [ {} ] new balance: [ {} ]",
Hex.toHexString(address), newBalance.toString());
accountStateDB.update(address, state.getEncoded());
return newBalance;
}
accountStateDB.update(address, state.getEncoded());
return newBalance;
}
public BigInteger getBalance(byte[] address){
AccountState state = getAccountState(address);
if (state == null) return BigInteger.ZERO;
return state.getBalance();
}
public BigInteger getNonce(byte[] address){
AccountState state = getAccountState(address);
if (state == null) return BigInteger.ZERO;
return state.getNonce();
}
public BigInteger increaseNonce(byte[] address){
AccountState state = getAccountState(address);
if (state == null) return BigInteger.ZERO;
state.incrementNonce();
if (logger.isInfoEnabled())
@ -201,7 +183,7 @@ public class Repository {
public void addStorageRow(byte[] address, DataWord key, DataWord value){
if (address == null || key == null) return;
AccountState state = getAccountState(address);
AccountState state = getAccountState(address);
ContractDetails details = getContractDetails(address);
if (state == null || details == null) return;
@ -234,14 +216,12 @@ public class Repository {
}
public byte[] getCode(byte[] address){
ContractDetails details = getContractDetails(address);
if (details == null) return null;
return details.getCode();
}
public void saveCode(byte[] address, byte[] code){
public void saveCode(byte[] address, byte[] code) {
if (code == null) return;
@ -264,26 +244,23 @@ public class Repository {
contractDetailsDB.put(address, details.getEncoded());
}
public byte[] getRootHash(){
public byte[] getRootHash() {
return this.worldState.getRootHash();
}
public void close(){
public void close() {
if (this.stateDB != null)
stateDB.close();
if (this.detailsDB != null)
detailsDB.close();
}
public void dumpState(long blockNumber, int txNumber, String txHash){
public void dumpState(long blockNumber, int txNumber, String txHash) {
if (!CONFIG.dumpFull()) return;
if (txHash == null)
if (CONFIG.dumpCleanOnRestart()){
if (CONFIG.dumpCleanOnRestart()) {
try {FileUtils.deleteDirectory(CONFIG.dumpDir());} catch (IOException e) {}
}
@ -291,9 +268,8 @@ public class Repository {
String fileName = "0.dmp";
if (txHash != null)
fileName =
String.format("%d_%d_%s.dmp",
blockNumber, txNumber, txHash.substring(0, 8));
fileName = String.format("%d_%d_%s.dmp",
blockNumber, txNumber, txHash.substring(0, 8));
File dumpFile = new File(System.getProperty("user.dir") + "/" + dir + fileName);
try {
@ -304,7 +280,7 @@ public class Repository {
FileWriter fw = new FileWriter(dumpFile.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
ArrayList<ByteArrayWrapper> keys = this.detailsDB.dumpKeys();
List<ByteArrayWrapper> keys = this.detailsDB.dumpKeys();
// dump json file
for (ByteArrayWrapper key : keys){

View File

@ -397,7 +397,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
Account account = ((AccountWrapper)creatorAddressCombo.getSelectedItem()).getAccount();
byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes();
byte[] nonce = account.getState().getNonce() == BigInteger.ZERO ? null : account.getState().getNonce().toByteArray();
byte[] nonce = account.getNonce() == BigInteger.ZERO ? null : account.getNonce().toByteArray();
byte[] gasPrice = new BigInteger("10000000000000").toByteArray();
BigInteger gasBI = new BigInteger(gasInput.getText());
@ -444,7 +444,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
@Override
public String toString() {
String addressShort = Utils.getAddressShortString(account.getEcKey().getAddress());
String valueShort = Utils.getValueShortString(account.getState().getBalance());
String valueShort = Utils.getValueShortString(account.getBalance());
String result = String.format(" By: [%s] %s", addressShort,
valueShort);
return result;

View File

@ -292,7 +292,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
Account account = ((AccountWrapper)creatorAddressCombo.getSelectedItem()).getAccount();
byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes();
byte[] nonce = account.getState().getNonce() == BigInteger.ZERO ? null : account.getState().getNonce().toByteArray();
byte[] nonce = account.getNonce() == BigInteger.ZERO ? null : account.getNonce().toByteArray();
byte[] gasPrice = new BigInteger("10000000000000").toByteArray();
BigInteger gasBI = new BigInteger(gasInput.getText());
@ -313,7 +313,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
private boolean validInput() {
Account account = ((AccountWrapper)creatorAddressCombo.getSelectedItem()).getAccount();
BigInteger currentBalance = account.getState().getBalance();
BigInteger currentBalance = account.getBalance();
BigInteger gasPrice = BigInteger.valueOf(WorldManager.instance.getBlockChain().getGasPrice());
BigInteger gasInput = new BigInteger( this.gasInput.getText());
@ -350,7 +350,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
@Override
public String toString() {
String addressShort = Utils.getAddressShortString(account.getEcKey().getAddress());
String valueShort = Utils.getValueShortString(account.getState().getBalance());
String valueShort = Utils.getValueShortString(account.getBalance());
String result =
String.format(" By: [%s] %s", addressShort, valueShort);

View File

@ -30,7 +30,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog {
private PayOutDialog dialog;
private AccountState addressState = null;
private AccountState accountState = null;
private JLabel statusMsg = null;
final JTextField receiverInput;
@ -41,7 +41,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog {
super(parent, "Payout details: ", false);
dialog = this;
this.addressState = account.getState();
this.accountState = account;
receiverInput = new JTextField(18);
GUIUtils.addStyle(receiverInput, "Pay to:");
@ -117,7 +117,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog {
}
byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes();
byte[] nonce = addressState.getNonce() == BigInteger.ZERO ? null : addressState.getNonce().toByteArray();
byte[] nonce = accountState.getNonce() == BigInteger.ZERO ? null : accountState.getNonce().toByteArray();
byte[] gasPrice = BigInteger.valueOf( WorldManager.instance.getBlockChain().getGasPrice()).toByteArray();
@ -195,7 +195,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog {
BigInteger ammountValue = new BigInteger(amountText);
BigInteger feeValue = new BigInteger(feeText);
BigInteger gasPrice = BigInteger.valueOf(WorldManager.instance.getBlockChain().getGasPrice());
BigInteger currentBalance = addressState.getBalance();
BigInteger currentBalance = accountState.getBalance();
boolean canAfford = gasPrice.multiply(feeValue).add(ammountValue).compareTo(currentBalance) != 1;

View File

@ -1,7 +1,6 @@
package org.ethereum.gui;
import org.ethereum.core.Account;
import org.ethereum.core.AccountState;
import org.ethereum.util.Utils;
import org.spongycastle.util.encoders.Hex;
@ -47,7 +46,7 @@ public class WalletAddressPanel extends JPanel{
amount.setBorder(border);
amount.setEnabled(true);
amount.setEditable(false);
amount.setText(Utils.getValueShortString(account.getState().getBalance()));
amount.setText(Utils.getValueShortString(account.getBalance()));
amount.setForeground(new Color(143, 170, 220));
amount.setBackground(Color.WHITE);
amount.setPreferredSize(new Dimension(100, 35));