mirror of
https://github.com/status-im/ethereumj-personal.git
synced 2025-02-03 15:44:51 +00:00
new shiny wallet design
This commit is contained in:
parent
c738f750b7
commit
979763106d
@ -1,6 +1,7 @@
|
||||
package org.ethereum.core;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import org.ethereum.crypto.ECKey;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
@ -13,7 +14,10 @@ public class Account {
|
||||
|
||||
private ECKey ecKey;
|
||||
private byte[] address;
|
||||
|
||||
|
||||
private Set<Transaction> pendingTransactions =
|
||||
Collections.synchronizedSet(new HashSet<Transaction>());
|
||||
|
||||
public Account() {
|
||||
this.ecKey = new ECKey(Utils.getRandom());
|
||||
address = this.ecKey.getAddress();
|
||||
@ -24,7 +28,6 @@ public class Account {
|
||||
address = this.ecKey.getAddress();
|
||||
}
|
||||
|
||||
|
||||
public ECKey getEcKey() {
|
||||
return ecKey;
|
||||
}
|
||||
@ -49,10 +52,29 @@ public class Account {
|
||||
AccountState accountState =
|
||||
WorldManager.getInstance().getRepository().getAccountState(this.address);
|
||||
|
||||
if (accountState != null)
|
||||
return accountState.getBalance();
|
||||
BigInteger balance = BigInteger.ZERO;
|
||||
|
||||
return null;
|
||||
if (accountState != null)
|
||||
balance = accountState.getBalance();
|
||||
|
||||
synchronized (pendingTransactions){
|
||||
if (!pendingTransactions.isEmpty()){
|
||||
|
||||
for (Transaction tx : pendingTransactions){
|
||||
if (Arrays.equals(this.address, tx.getSender())){
|
||||
balance = balance.subtract(new BigInteger(1, tx.getValue()));
|
||||
}
|
||||
|
||||
if (Arrays.equals(this.address, tx.getReceiveAddress())){
|
||||
balance = balance.add(new BigInteger(1, tx.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
// todo: calculate the fee for pending
|
||||
}
|
||||
}
|
||||
|
||||
return balance;
|
||||
}
|
||||
|
||||
|
||||
@ -61,9 +83,37 @@ public class Account {
|
||||
AccountState accountState =
|
||||
WorldManager.getInstance().getRepository().getAccountState(this.address);
|
||||
|
||||
if (accountState != null)
|
||||
return accountState.getNonce();
|
||||
BigInteger nonce = BigInteger.ZERO;
|
||||
|
||||
return null;
|
||||
if (accountState != null)
|
||||
nonce = accountState.getNonce();
|
||||
|
||||
synchronized (pendingTransactions){
|
||||
if (!pendingTransactions.isEmpty()){
|
||||
|
||||
for (Transaction tx : pendingTransactions){
|
||||
if (Arrays.equals(this.address, tx.getSender())){
|
||||
nonce = nonce.add(BigInteger.ONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nonce;
|
||||
}
|
||||
|
||||
|
||||
public void addPendingTransaction(Transaction transaction){
|
||||
synchronized (pendingTransactions){
|
||||
pendingTransactions.add(transaction);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void clearAllPendingTransactions(){
|
||||
synchronized (pendingTransactions){
|
||||
pendingTransactions.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,9 +95,6 @@ public class Blockchain implements org.ethereum.facade.Blockchain{
|
||||
|
||||
if (block == null)
|
||||
return;
|
||||
|
||||
if (block.getNumber() == 12390)
|
||||
logger.debug("Block #12390");
|
||||
|
||||
// if it is the first block to add
|
||||
// make sure the parent is genesis
|
||||
|
@ -286,4 +286,26 @@ public class Transaction {
|
||||
receiveAddress, value, data, v, r, s);
|
||||
return rlpEncoded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
byte[] hash = this.getHash();
|
||||
int hashCode = 0;
|
||||
|
||||
for (int i = 0; i < hash.length; ++i){
|
||||
hashCode += hash[i] * i;
|
||||
}
|
||||
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (!(obj instanceof Transaction)) return false;
|
||||
Transaction tx = (Transaction)obj;
|
||||
|
||||
return tx.hashCode() == this.hashCode();
|
||||
}
|
||||
}
|
@ -92,7 +92,24 @@ public class Wallet {
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The wallet will call this method once transaction been send to the network,
|
||||
* once the the GET_TRANSACTION will be answered with that particular transaction
|
||||
* it will be considered as received by the net
|
||||
*
|
||||
* @param transaction
|
||||
* @return
|
||||
*/
|
||||
public WalletTransaction addByWalletTransaction(Transaction transaction){
|
||||
String hash = Hex.toHexString(transaction.getHash());
|
||||
WalletTransaction walletTransaction = new WalletTransaction(transaction);
|
||||
this.walletTransactions.put(hash, walletTransaction);
|
||||
|
||||
return walletTransaction;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 1) the dialog put a pending transaction on the list
|
||||
* 2) the dialog send the transaction to a net
|
||||
@ -111,6 +128,9 @@ public class Wallet {
|
||||
walletTransaction = new WalletTransaction(transaction);
|
||||
this.walletTransactions.put(hash, walletTransaction);
|
||||
}
|
||||
|
||||
this.applyTransaction(transaction);
|
||||
|
||||
return walletTransaction;
|
||||
}
|
||||
|
||||
@ -141,16 +161,23 @@ public class Wallet {
|
||||
byte[] senderAddress = transaction.getSender();
|
||||
Account sender = rows.get(Hex.toHexString(senderAddress));
|
||||
if (sender != null) {
|
||||
sender.addPendingTransaction(transaction);
|
||||
|
||||
BigInteger value = new BigInteger(-1, transaction.getValue());
|
||||
// sender.addToBalance(value);
|
||||
// sender.incrementNonce();
|
||||
logger.info("Pending transaction added to " +
|
||||
"\n account: [ {} ], " +
|
||||
"\n tx: [ {} ]",
|
||||
Hex.toHexString(sender.getAddress()), Hex.toHexString(transaction.getHash()));
|
||||
}
|
||||
|
||||
byte[] receiveAddress = transaction.getReceiveAddress();
|
||||
Account receiver = rows.get(Hex.toHexString(receiveAddress));
|
||||
if (receiver != null) {
|
||||
// receiver.addToBalance(new BigInteger(1, transaction.getValue()));
|
||||
receiver.addPendingTransaction(transaction);
|
||||
|
||||
logger.info("Pending transaction added to " +
|
||||
"\n account: [ {} ], " +
|
||||
"\n tx: [ {} ]",
|
||||
Hex.toHexString(receiver.getAddress()), Hex.toHexString(transaction.getHash()));
|
||||
}
|
||||
this.notifyListeners();
|
||||
}
|
||||
@ -158,24 +185,11 @@ public class Wallet {
|
||||
|
||||
public void processBlock(Block block) {
|
||||
|
||||
if (block == null) return;
|
||||
|
||||
// TODO: proceed coinbase when you are the miner that gets an award
|
||||
boolean walletUpdated = false;
|
||||
|
||||
List<Transaction> transactions = block.getTransactionsList();
|
||||
|
||||
for (Transaction tx : transactions) {
|
||||
boolean txExist = transactionMap.get(new ByteArrayWrapper(tx.getHash())) != null;
|
||||
if (txExist) break;
|
||||
else {
|
||||
this.applyTransaction(tx);
|
||||
walletUpdated = true;
|
||||
}
|
||||
for (Account account : getAccountCollection()){
|
||||
account.clearAllPendingTransactions();
|
||||
}
|
||||
|
||||
this.high = block.getNumber();
|
||||
if (walletUpdated) notifyListeners();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -478,15 +478,28 @@ public class Repository {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isClosed(){
|
||||
return chainDB == null;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (this.chainDB != null)
|
||||
chainDB.close();
|
||||
if (this.stateDB != null)
|
||||
|
||||
if (this.chainDB != null){
|
||||
chainDB.close();
|
||||
chainDB = null;
|
||||
}
|
||||
|
||||
if (this.stateDB != null){
|
||||
|
||||
stateDB.close();
|
||||
if (this.detailsDB != null)
|
||||
stateDB = null;
|
||||
}
|
||||
|
||||
if (this.detailsDB != null){
|
||||
|
||||
detailsDB.close();
|
||||
detailsDB = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void validateAddress(byte[] addr) {
|
||||
@ -496,3 +509,4 @@ public class Repository {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,4 +159,8 @@ public class EthereumImpl implements Ethereum {
|
||||
public boolean isConnected() {
|
||||
return WorldManager.getInstance().getActivePeer() != null;
|
||||
}
|
||||
|
||||
|
||||
// public Future<Transaction> submitTransaction() -- wait for approve (like in wallet dialog)
|
||||
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ import org.ethereum.net.peerdiscovery.PeerDiscovery;
|
||||
public class WorldManager {
|
||||
|
||||
private Blockchain blockchain;
|
||||
private final Repository repository;
|
||||
private Repository repository;
|
||||
private Wallet wallet;
|
||||
|
||||
private PeerDiscovery peerDiscovery;
|
||||
@ -59,6 +59,13 @@ public class WorldManager {
|
||||
|
||||
}
|
||||
|
||||
// used for testing
|
||||
public void reset(){
|
||||
|
||||
this.repository = new Repository();
|
||||
this.blockchain = new Blockchain(repository);
|
||||
}
|
||||
|
||||
public void init(){
|
||||
this.wallet = new Wallet();
|
||||
|
||||
|
@ -89,7 +89,7 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
||||
public void run() {
|
||||
sendGetTransactions();
|
||||
}
|
||||
}, 2000, 30000);
|
||||
}, 2000, 10000);
|
||||
|
||||
chainAskTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
@ -198,8 +198,9 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
List<Transaction> txList = transactionsMessage.getTransactions();
|
||||
for(Transaction tx : txList)
|
||||
WorldManager.getInstance().getBlockchain()
|
||||
.applyTransaction(null, tx);
|
||||
// WorldManager.getInstance().getBlockchain()
|
||||
// .applyTransaction(null, tx);
|
||||
WorldManager.getInstance().getWallet().addTransaction(tx);
|
||||
|
||||
logger.info(transactionsMessage.toString());
|
||||
if (peerListener != null) peerListener.console(transactionsMessage.toString());
|
||||
|
@ -33,7 +33,7 @@ public class TransactionTask implements Callable<Transaction> {
|
||||
|
||||
ClientPeer peer = WorldManager.getInstance().getActivePeer();
|
||||
|
||||
WalletTransaction walletTransaction = WorldManager.getInstance().getWallet().addTransaction(tx);
|
||||
WalletTransaction walletTransaction = WorldManager.getInstance().getWallet().addByWalletTransaction(tx);
|
||||
peer.sendTransaction(tx);
|
||||
|
||||
while(walletTransaction.getApproved() < 1) {
|
||||
|
@ -3,15 +3,25 @@ package org.ethereum.core;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.Genesis;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class BlockTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() {
|
||||
if (WorldManager.getInstance().getRepository().isClosed())
|
||||
WorldManager.getInstance().reset();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
WorldManager.getInstance().close();
|
||||
}
|
||||
|
||||
// https://ethereum.etherpad.mozilla.org/12
|
||||
private String CPP_PoC5_GENESIS_HEX_RLP_ENCODED = "f8abf8a7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a08dbd704eb38d1c2b73ee4788715ea5828a030650829703f077729b2b613dd20680834000008080830f4240808080a004994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829c0c0";
|
||||
@ -108,24 +118,21 @@ public class BlockTest {
|
||||
|
||||
@Test
|
||||
public void testCalcDifficulty() {
|
||||
try {
|
||||
Block genesis = Genesis.getInstance();
|
||||
BigInteger difficulty = new BigInteger(1, genesis.calcDifficulty());
|
||||
System.out.println("Genesis difficulty = " + difficulty.toString());
|
||||
assertEquals(new BigInteger(1, Genesis.DIFFICULTY), difficulty);
|
||||
|
||||
// Storing genesis because the parent needs to be in the DB for calculation.
|
||||
WorldManager.getInstance().getBlockchain().add(genesis);
|
||||
Block genesis = Genesis.getInstance();
|
||||
BigInteger difficulty = new BigInteger(1, genesis.calcDifficulty());
|
||||
System.out.println("Genesis difficulty = " + difficulty.toString());
|
||||
assertEquals(new BigInteger(1, Genesis.DIFFICULTY), difficulty);
|
||||
|
||||
Block block1 = new Block(Hex.decode(block_1));
|
||||
BigInteger calcDifficulty = new BigInteger(1, block1.calcDifficulty());
|
||||
BigInteger actualDifficulty = new BigInteger(1, block1.getDifficulty());
|
||||
System.out.println("Block#1 actual difficulty = " + actualDifficulty.toString());
|
||||
System.out.println("Block#1 calculated difficulty = " + calcDifficulty.toString());
|
||||
assertEquals(actualDifficulty, calcDifficulty);
|
||||
} finally {
|
||||
WorldManager.getInstance().close();
|
||||
}
|
||||
// Storing genesis because the parent needs to be in the DB for calculation.
|
||||
WorldManager.getInstance().getBlockchain().add(genesis);
|
||||
|
||||
Block block1 = new Block(Hex.decode(block_1));
|
||||
BigInteger calcDifficulty = new BigInteger(1, block1.calcDifficulty());
|
||||
BigInteger actualDifficulty = new BigInteger(1, block1.getDifficulty());
|
||||
System.out.println("Block#1 actual difficulty = " + actualDifficulty.toString());
|
||||
System.out.println("Block#1 calculated difficulty = " + calcDifficulty.toString());
|
||||
assertEquals(actualDifficulty, calcDifficulty);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -2,8 +2,11 @@ package org.ethereum.core;
|
||||
|
||||
import org.ethereum.crypto.ECKey;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.ethereum.db.Repository;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.junit.*;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
@ -17,8 +20,70 @@ import java.math.BigInteger;
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 17/05/14 17:06
|
||||
*/
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class WalletTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() {
|
||||
if (WorldManager.getInstance().getRepository().isClosed())
|
||||
WorldManager.getInstance().reset();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
WorldManager.getInstance().close();
|
||||
}
|
||||
|
||||
@Test // Testing account for simple balance set
|
||||
public void accountTest_1(){
|
||||
|
||||
Repository repository = WorldManager.getInstance().getRepository();
|
||||
|
||||
ECKey cowKey = ECKey.fromPrivate(HashUtil.sha3("cow".getBytes()));
|
||||
repository.createAccount(cowKey.getAddress());
|
||||
repository.addBalance(cowKey.getAddress(), BigInteger.TEN);
|
||||
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.importKey(cowKey.getPrivKeyBytes());
|
||||
|
||||
BigInteger walletBalance = wallet.getBalance(cowKey.getAddress());
|
||||
Assert.assertEquals(BigInteger.TEN, walletBalance);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test // test account balance with pending "unblocked" transaction
|
||||
public void accountTest_2(){
|
||||
|
||||
Repository repository = WorldManager.getInstance().getRepository();
|
||||
|
||||
ECKey cowKey = ECKey.fromPrivate(HashUtil.sha3("cow".getBytes()));
|
||||
repository.createAccount(cowKey.getAddress());
|
||||
repository.addBalance(cowKey.getAddress(), BigInteger.TEN);
|
||||
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.importKey(cowKey.getPrivKeyBytes());
|
||||
|
||||
Transaction tx = new Transaction(
|
||||
new byte[]{},
|
||||
Hex.decode("09184E72A000"),
|
||||
Hex.decode("03E8"),
|
||||
cowKey.getAddress(),
|
||||
Hex.decode("0A"),
|
||||
new byte[]{}
|
||||
);
|
||||
|
||||
ECKey catKey = ECKey.fromPrivate(HashUtil.sha3("cat".getBytes()));
|
||||
tx.sign(catKey.getPrivKeyBytes());
|
||||
|
||||
wallet.applyTransaction(tx);
|
||||
|
||||
BigInteger walletBalance = wallet.getBalance(cowKey.getAddress());
|
||||
Assert.assertEquals(BigInteger.valueOf(20), walletBalance);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSave1() throws TransformerException, ParserConfigurationException {
|
||||
|
||||
@ -29,13 +94,6 @@ public class WalletTest {
|
||||
wallet.importKey(cowKey.getPrivKeyBytes());
|
||||
wallet.importKey(catKey.getPrivKeyBytes());
|
||||
|
||||
|
||||
AccountState cowAddressState = wallet.getAccountState(cowKey.getAddress());
|
||||
AccountState catAddressState = wallet.getAccountState(catKey.getAddress());
|
||||
|
||||
cowAddressState.addToBalance(new BigInteger("234234"));
|
||||
catAddressState.addToBalance(new BigInteger("84758"));
|
||||
|
||||
wallet.setHigh(4354);
|
||||
|
||||
wallet.save();
|
||||
|
@ -58,7 +58,6 @@ public class DialogWorker extends SwingWorker<Transaction, Object> {
|
||||
}
|
||||
|
||||
dialog.infoStatusMsg("Transaction got approved");
|
||||
WorldManager.getInstance().getWallet().applyTransaction(tx);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user