Refactor Account inherits from AccountState
This commit is contained in:
parent
f7f2f88946
commit
51292f8b20
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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){
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue