Skip to content

Instantly share code, notes, and snippets.

@agran
Created November 11, 2015 14:28
Show Gist options
  • Save agran/3250073b15cbdd6411d7 to your computer and use it in GitHub Desktop.
Save agran/3250073b15cbdd6411d7 to your computer and use it in GitHub Desktop.
package qora.wallet;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Logger;
import org.mapdb.Fun.Tuple2;
import qora.account.Account;
import qora.account.PrivateKeyAccount;
import qora.assets.Asset;
import qora.assets.Order;
import qora.block.Block;
import qora.block.GenesisBlock;
import qora.crypto.Crypto;
import qora.naming.Name;
import qora.naming.NameSale;
import qora.transaction.BuyNameTransaction;
import qora.transaction.CancelOrderTransaction;
import qora.transaction.CancelSellNameTransaction;
import qora.transaction.CreateOrderTransaction;
import qora.transaction.CreatePollTransaction;
import qora.transaction.IssueAssetTransaction;
import qora.transaction.PaymentTransaction;
import qora.transaction.RegisterNameTransaction;
import qora.transaction.SellNameTransaction;
import qora.transaction.Transaction;
import qora.transaction.UpdateNameTransaction;
import qora.transaction.VoteOnPollTransaction;
import qora.voting.Poll;
import utils.ObserverMessage;
import utils.Pair;
import at.AT_Transaction;
import com.google.common.primitives.Bytes;
import com.google.common.primitives.Ints;
import controller.Controller;
import database.DBSet;
import database.wallet.SecureWalletDatabase;
import database.wallet.WalletDatabase;
public class Wallet extends Observable implements Observer
{
public static final int STATUS_UNLOCKED = 1;
public static final int STATUS_LOCKED = 0;
private WalletDatabase database;
private SecureWalletDatabase secureDatabase;
private int secondsToUnlock = -1;
private Timer lockTimer = new Timer();
public static boolean done = false;
public static int counter = 0;
public static long startTime = 0;
//CONSTRUCTORS
public Wallet()
{
//CHECK IF EXISTS
if(this.exists())
{
//OPEN WALLET
this.database = new WalletDatabase();
//ADD OBSERVER
Controller.getInstance().addObserver(this);
DBSet.getInstance().getCompletedOrderMap().addObserver(this);
}
}
//GETTERS/SETTERS
public void setSecondsToUnlock(int seconds)
{
this.secondsToUnlock = seconds;
}
public int getVersion()
{
return this.database.getVersion();
}
public boolean isUnlocked()
{
return this.secureDatabase != null;
}
public List<Account> getAccounts()
{
return this.database.getAccountMap().getAccounts();
}
public boolean accountExists(String address)
{
return this.database.getAccountMap().exists(address);
}
public Account getAccount(String address)
{
return this.database.getAccountMap().getAccount(address);
}
public boolean isWalletDatabaseExisting()
{
return database != null;
}
public BigDecimal getUnconfirmedBalance(String address)
{
return this.database.getAccountMap().getUnconfirmedBalance(address);
}
public List<PrivateKeyAccount> getprivateKeyAccounts()
{
if(this.secureDatabase == null)
{
return new ArrayList<PrivateKeyAccount>();
}
return this.secureDatabase.getAccountSeedMap().getPrivateKeyAccounts();
}
public PrivateKeyAccount getPrivateKeyAccount(String address)
{
if(this.secureDatabase == null)
{
return null;
}
return this.secureDatabase.getAccountSeedMap().getPrivateKeyAccount(address);
}
public boolean exists()
{
return WalletDatabase.exists();
}
public List<Pair<Account, Transaction>> getLastTransactions(int limit)
{
if(!this.exists())
{
new ArrayList<Pair<Account, Transaction>>();
}
List<Account> accounts = this.getAccounts();
return this.database.getTransactionMap().get(accounts, limit);
}
public List<Transaction> getLastTransactions(Account account, int limit)
{
if(!this.exists())
{
return new ArrayList<Transaction>();
}
return this.database.getTransactionMap().get(account, limit);
}
public List<Pair<Account, Block>> getLastBlocks()
{
if(!this.exists())
{
return new ArrayList<Pair<Account, Block>>();
}
List<Account> accounts = this.getAccounts();
return this.database.getBlockMap().get(accounts);
}
public List<Block> getLastBlocks(Account account)
{
if(!this.exists())
{
return new ArrayList<Block>();
}
return this.database.getBlockMap().get(account);
}
public List<Pair<Account, Name>> getNames()
{
if(!this.exists())
{
return new ArrayList<Pair<Account, Name>>();
}
List<Account> accounts = this.getAccounts();
return this.database.getNameMap().get(accounts);
}
public List<Name> getNames(Account account)
{
if(!this.exists())
{
return new ArrayList<Name>();
}
return this.database.getNameMap().get(account);
}
public List<Pair<Account, NameSale>> getNameSales()
{
if(!this.exists())
{
return new ArrayList<Pair<Account, NameSale>>();
}
List<Account> accounts = this.getAccounts();
return this.database.getNameSaleMap().get(accounts);
}
public List<NameSale> getNameSales(Account account)
{
if(!this.exists())
{
return new ArrayList<NameSale>();
}
return this.database.getNameSaleMap().get(account);
}
public List<Pair<Account, Poll>> getPolls()
{
if(!this.exists())
{
return new ArrayList<Pair<Account, Poll>>();
}
List<Account> accounts = this.getAccounts();
return this.database.getPollMap().get(accounts);
}
public List<Poll> getPolls(Account account)
{
if(!this.exists())
{
return new ArrayList<Poll>();
}
return this.database.getPollMap().get(account);
}
public void addAssetFavorite(Asset asset)
{
if(!this.exists())
{
return;
}
this.database.getAssetFavoritesSet().add(asset.getKey());
}
public void removeAssetFavorite(Asset asset)
{
if(!this.exists())
{
return;
}
this.database.getAssetFavoritesSet().delete(asset.getKey());
}
public boolean isAssetFavorite(Asset asset)
{
if(!this.exists())
{
return false;
}
return this.database.getAssetFavoritesSet().contains(asset.getKey());
}
//CREATE
public boolean create(byte[] seed, String password, int depth, boolean synchronize)
{
//OPEN WALLET
WalletDatabase database = new WalletDatabase();
//OPEN SECURE WALLET
SecureWalletDatabase secureDatabase = new SecureWalletDatabase(password);
//CREATE
return this.create(database, secureDatabase, seed, depth, synchronize);
}
public boolean create(WalletDatabase database, SecureWalletDatabase secureDatabase, byte[] seed, int depth, boolean synchronize)
{
//CREATE WALLET
this.database = database;
//CREATE SECURE WALLET
this.secureDatabase = secureDatabase;
//ADD VERSION
this.database.setVersion(1);
//ADD SEED
this.secureDatabase.setSeed(seed);
//ADD NONCE
this.secureDatabase.setNonce(0);
//CREATE ACCOUNTS
for(int i=1; i<=depth; i++)
{
this.generateNewAccount();
}
//SCAN TRANSACTIONS
if(synchronize)
{
this.synchronize();
}
//COMMIT
this.commit();
//ADD OBSERVER
Controller.getInstance().addObserver(this);
DBSet.getInstance().getCompletedOrderMap().addObserver(this);
return true;
}
public String generateNewAccount()
{
//CHECK IF WALLET IS OPEN
if(!this.isUnlocked())
{
return "";
}
//READ SEED
byte[] seed = this.secureDatabase.getSeed();
//READ NONCE
int nonce = this.secureDatabase.getAndIncrementNonce();
//GENERATE ACCOUNT SEED
byte[] accountSeed = this.generateAccountSeed(seed, nonce);
PrivateKeyAccount account = new PrivateKeyAccount(accountSeed);
//CHECK IF ACCOUNT ALREADY EXISTS
if(!this.accountExists(account.getAddress()))
{
//ADD TO DATABASE
this.secureDatabase.getAccountSeedMap().add(account);
this.database.getAccountMap().add(account);
Logger.getGlobal().info("Added account #" + nonce);
this.secureDatabase.commit();
this.database.commit();
//NOTIFY
this.setChanged();
this.notifyObservers(new ObserverMessage(ObserverMessage.ADD_ACCOUNT_TYPE, account));
}
return account.getAddress();
}
private byte[] generateAccountSeed(byte[] seed, int nonce)
{
byte[] nonceBytes = Ints.toByteArray(nonce);
byte[] accountSeed = Bytes.concat(nonceBytes, seed, nonceBytes);
return Crypto.getInstance().doubleDigest(accountSeed);
}
//DELETE
public boolean deleteAccount(PrivateKeyAccount account)
{
//CHECK IF WALLET IS OPEN
if(!this.isUnlocked())
{
return false;
}
//DELETE FROM DATABASE
this.database.delete(account);
this.secureDatabase.delete(account);
//NOTIFY
this.setChanged();
this.notifyObservers(new ObserverMessage(ObserverMessage.REMOVE_ACCOUNT_TYPE, account));
//RETURN
return true;
}
//SYNCRHONIZE
public void synchronize()
{
List<Account> accounts = this.getAccounts();
//RESET MAPS
this.database.getTransactionMap().reset();
this.database.getBlockMap().reset();
this.database.getNameMap().reset();
this.database.getNameSaleMap().reset();
this.database.getPollMap().reset();
this.database.getAssetMap().reset();
this.database.getOrderMap().reset();
Logger.getGlobal().info("Resetted maps");
//REPROCESS BLOCKS
Block block = new GenesisBlock();
this.database.setLastBlockSignature(new byte[]{1,1,1,1,1,1,1,1});
startTime = System.currentTimeMillis()/1000;
Timer2 r = new Timer2();
Thread t = new Thread(r);
t.setPriority( Thread.MIN_PRIORITY );
t.start();
try{
Controller.getInstance().isProcessSynchronize = true;
do
{
//UPDATE
this.update(this, new ObserverMessage(ObserverMessage.ADD_BLOCK_TYPE, block));
counter ++;
if(block.getHeight() % 2000 == 0)
{
Logger.getGlobal().info("Synchronize wallet: " + block.getHeight());
this.database.commit();
}
//LOAD NEXT
block = block.getChild();
}
while(block != null);
done = true;
}finally{
Controller.getInstance().isProcessSynchronize = false;
this.database.commit();
}
//RESET UNCONFIRMED BALANCE
synchronized(accounts)
{
for(Account account: accounts)
{
this.database.getAccountMap().update(account, account.getConfirmedBalance());
}
}
Logger.getGlobal().info("Resetted balances");
//SET LAST BLOCK
/*//SCAN TRANSACTIONS
Map<Account, List<Transaction>> transactions;
synchronized(accounts)
{
transactions = Controller.getInstance().scanTransactions(accounts);
}
//DELETE TRANSACTIONS
this.database.getTransactionMap().deleteAll(accounts);
//ADD TRANSACTIONS
this.database.getTransactionMap().addAll(transactions);
//TODO SCAN UNCONFIRMED TRANSACTIONS
//SCAN BLOCKS
Map<Account, List<Block>> blocks;
synchronized(accounts)
{
blocks = Controller.getInstance().scanBlocks(accounts);
}
//DELETE BLOCKS
this.database.getBlockMap().deleteAll(accounts);
//ADD BLOCKS
this.database.getBlockMap().addAll(blocks);
//SCAN NAMES
Map<Account, List<Name>> names;
synchronized(accounts)
{
names = Controller.getInstance().scanNames(accounts);
}
//DELETE NAMES
this.database.getNameMap().deleteAll(accounts);
//ADD NAMES
this.database.getNameMap().addAll(names);
//TODO SCAN UNCONFIRMED NAMES
//SCAN NAMESALES
Map<Account, List<NameSale>> nameSales;
synchronized(accounts)
{
nameSales = Controller.getInstance().scanNameSales(accounts);
}
//DELETE NAMESALES
this.database.getNameSaleMap().deleteAll(accounts);
//ADD NAMES
this.database.getNameSaleMap().addAll(nameSales);
//SCAN POLLS
Map<Account, List<Poll>> polls;
synchronized(accounts)
{
polls = Controller.getInstance().scanPolls(accounts);
}
//DELETE POLLS
this.database.getPollMap().deleteAll(accounts);
//ADD POLLS
this.database.getPollMap().addAll(polls);
//SCAN ASSETS
Map<Account, List<Asset>> assets;
synchronized(accounts)
{
assets = Controller.getInstance().scanAssets(accounts);
}
//DELETE ASSETS
this.database.getAssetMap().deleteAll(accounts);
//ADD ASSETS
this.database.getAssetMap().addAll(assets);
//SCAN ORDERS
Map<Account, List<Order>> orders;
synchronized(accounts)
{
orders = Controller.getInstance().scanOrders(accounts);
}
//DELETE ASSETS
this.database.getOrderMap().deleteAll(accounts);
//ADD ASSETS
this.database.getOrderMap().addAll(orders);
//SET LAST BLOCK
this.database.setLastBlockSignature(Controller.getInstance().getLastBlock().getSignature());*/
}
//UNLOCK
public boolean unlock(String password)
{
if(this.isUnlocked())
{
return false;
}
//TRY TO UNLOCK
try
{
SecureWalletDatabase secureDatabase = new SecureWalletDatabase(password);
return this.unlock(secureDatabase);
}
catch(Exception e)
{
return false;
}
}
public boolean unlock(SecureWalletDatabase secureDatabase)
{
this.secureDatabase = secureDatabase;
//NOTIFY
this.setChanged();
this.notifyObservers(new ObserverMessage(ObserverMessage.WALLET_STATUS, STATUS_UNLOCKED));
if(this.secondsToUnlock > 0)
{
this.lockTimer.cancel();
this.lockTimer = new Timer();
TimerTask action = new TimerTask() {
public void run() {
lock();
}
};
this.lockTimer.schedule(action, this.secondsToUnlock*1000);
}
return true;
}
public boolean lock()
{
if(!this.isUnlocked())
{
return false;
}
//CLOSE
this.secureDatabase.close();
this.secureDatabase = null;
//NOTIFY
this.setChanged();
this.notifyObservers(new ObserverMessage(ObserverMessage.WALLET_STATUS, STATUS_LOCKED));
this.secondsToUnlock = -1;
this.lockTimer.cancel();
//LOCK SUCCESSFULL
return true;
}
//IMPORT/EXPORT
public String importAccountSeed(byte[] accountSeed)
{
//CHECK IF WALLET IS OPEN
if(!this.isUnlocked())
{
return "";
}
//CHECK LENGTH
if(accountSeed.length != 32)
{
return "";
}
//CREATE ACCOUNT
PrivateKeyAccount account = new PrivateKeyAccount(accountSeed);
//CHECK IF ACCOUNT ALREADY EXISTS
if(!this.accountExists(account.getAddress()))
{
//ADD TO DATABASE
this.secureDatabase.getAccountSeedMap().add(account);
this.database.getAccountMap().add(account);
//SYNCHRONIZE
this.synchronize();
//NOTIFY
this.setChanged();
this.notifyObservers(new ObserverMessage(ObserverMessage.ADD_ACCOUNT_TYPE, account));
//RETURN
return account.getAddress();
}
return "";
}
public byte[] exportAccountSeed(String address)
{
//CHECK IF WALLET IS OPEN
if(!this.isUnlocked())
{
return null;
}
PrivateKeyAccount account = this.getPrivateKeyAccount(address);
if(account == null)
{
return null;
}
return account.getSeed();
}
public byte[] exportSeed()
{
//CHECK IF WALLET IS OPEN
if(!this.isUnlocked())
{
return null;
}
return this.secureDatabase.getSeed();
}
//OBSERVER
@Override
public void addObserver(Observer o)
{
super.addObserver(o);
//REGISTER ON ACCOUNTS
this.database.getAccountMap().addObserver(o);
//REGISTER ON TRANSACTIONS
this.database.getTransactionMap().addObserver(o);
//REGISTER ON BLOCKS
this.database.getBlockMap().addObserver(o);
//REGISTER ON NAMES
this.database.getNameMap().addObserver(o);
//REGISTER ON NAME SALES
this.database.getNameSaleMap().addObserver(o);
//REGISTER ON POLLS
this.database.getPollMap().addObserver(o);
//REGISTER ON ASSETS
this.database.getAssetMap().addObserver(o);
//REGISTER ON ORDERS
this.database.getOrderMap().addObserver(o);
//REGISTER ON ASSET FAVORITES
this.database.getAssetFavoritesSet().addObserver(o);
//SEND STATUS
int status = STATUS_LOCKED;
if(this.isUnlocked())
{
status = STATUS_UNLOCKED;
}
o.update(this, new ObserverMessage(ObserverMessage.WALLET_STATUS, status));
}
private void processTransaction(Transaction transaction)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//FOR ALL ACCOUNTS
List<Account> accounts = this.getAccounts();
List<Account> involvedAccounts = transaction.getInvolvedAccounts();
synchronized(involvedAccounts)
{
for(Account account: involvedAccounts)
{
//CHECK IF INVOLVED
if(accounts.contains(account))//
{
//System.out.println("123 " + account.getAddress());
//ADD TO ACCOUNT TRANSACTIONS
if(!this.database.getTransactionMap().add(account, transaction))
{
//UPDATE UNCONFIRMED BALANCE
BigDecimal unconfirmedBalance = this.getUnconfirmedBalance(account.getAddress()).add(transaction.getAmount(account));
this.database.getAccountMap().update(account, unconfirmedBalance);
}
}
}
}
}
private void processATTransaction( Tuple2< Tuple2< Integer, Integer >, AT_Transaction > atTx )
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//FOR ALL ACCOUNTS
List<Account> accounts = this.getAccounts();
synchronized(accounts)
{
for(Account account: accounts)
{
//CHECK IF INVOLVED
if(atTx.b.getRecipient().equalsIgnoreCase( account.getAddress() ))
{
BigDecimal unconfirmedBalance = this.getUnconfirmedBalance(account.getAddress()).add( BigDecimal.valueOf(atTx.b.getAmount(),8));
this.database.getAccountMap().update(account, unconfirmedBalance);
}
}
}
}
private void orphanTransaction(Transaction transaction)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
///FOR ALL ACCOUNTS
List<Account> accounts = this.getAccounts();
synchronized(accounts)
{
for(Account account: accounts)
{
//CHECK IF INVOLVED
if(transaction.isInvolved(account))
{
//DELETE FROM ACCOUNT TRANSACTIONS
this.database.getTransactionMap().delete(account, transaction);
//UPDATE UNCONFIRMED BALANCE
BigDecimal unconfirmedBalance = this.getUnconfirmedBalance(account.getAddress()).subtract(transaction.getAmount(account));
this.database.getAccountMap().update(account, unconfirmedBalance);
}
}
}
}
private void orphanATTransaction(Tuple2<Tuple2<Integer,Integer>, AT_Transaction> atTx)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//FOR ALL ACCOUNTS
List<Account> accounts = this.getAccounts();
synchronized(accounts)
{
for(Account account: accounts)
{
//CHECK IF INVOLVED
if(atTx.b.getRecipient().equalsIgnoreCase( account.getAddress() ))
{
BigDecimal unconfirmedBalance = this.getUnconfirmedBalance(account.getAddress()).subtract( BigDecimal.valueOf(atTx.b.getAmount(),8));
this.database.getAccountMap().update(account, unconfirmedBalance);
}
}
}
}
private void processBlock(Block block)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE NEED TO RESYNC
byte[] lastBlockSignature = this.database.getLastBlockSignature();
if(lastBlockSignature == null || !Arrays.equals(lastBlockSignature, block.getReference()))
{
Logger.getGlobal().info("Wallet not synchronized with current blockchain: synchronizing wallet.");
this.synchronize();
}
//SET AS LAST BLOCK
this.database.setLastBlockSignature(block.getSignature());
//CHECK IF WE ARE GENERATOR
if(this.accountExists(block.getGenerator().getAddress()))
{
//ADD BLOCK
this.database.getBlockMap().add(block);
//KEEP TRACK OF UNCONFIRMED BALANCE
BigDecimal unconfirmedBalance = this.getUnconfirmedBalance(block.getGenerator().getAddress()).add(block.getTotalFee());
this.database.getAccountMap().update(block.getGenerator(), unconfirmedBalance);
}
}
private void orphanBlock(Block block)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE GENERATOR
if(this.accountExists(block.getGenerator().getAddress()))
{
//DELETE BLOCK
this.database.getBlockMap().delete(block);
//KEEP TRACK OF UNCONFIRMED BALANCE
BigDecimal unconfirmedBalance = this.getUnconfirmedBalance(block.getGenerator().getAddress()).subtract(block.getTotalFee());
this.database.getAccountMap().update(block.getGenerator(), unconfirmedBalance);
}
}
private void processNameRegistration(RegisterNameTransaction nameRegistration)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE OWNER
if(this.accountExists(nameRegistration.getName().getOwner().getAddress()))
{
//ADD NAME
this.database.getNameMap().add(nameRegistration.getName());
}
}
private void orphanNameRegistration(RegisterNameTransaction nameRegistration)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE OWNER
if(this.accountExists(nameRegistration.getName().getOwner().getAddress()))
{
//DELETE NAME
this.database.getNameMap().delete(nameRegistration.getName());
}
}
private void processPollCreation(CreatePollTransaction pollCreation)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE OWNER
if(this.accountExists(pollCreation.getPoll().getCreator().getAddress()))
{
//ADD POLL
this.database.getPollMap().add(pollCreation.getPoll());
}
}
private void orphanPollCreation(CreatePollTransaction pollCreation)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE OWNER
if(this.accountExists(pollCreation.getPoll().getCreator().getAddress()))
{
//DELETE POLL
this.database.getPollMap().delete(pollCreation.getPoll());
}
}
private void processPollVote(VoteOnPollTransaction pollVote)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE OWNER
Poll poll = DBSet.getInstance().getPollMap().get(pollVote.getPoll());
if(this.accountExists(poll.getCreator().getAddress()))
{
//UPDATE POLL
this.database.getPollMap().add(poll);
}
}
private void orphanPollVote(VoteOnPollTransaction pollVote)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE OWNER
Poll poll = DBSet.getInstance().getPollMap().get(pollVote.getPoll());
if(this.accountExists(poll.getCreator().getAddress()))
{
//UPDATE POLL
this.database.getPollMap().add(poll);
}
}
private void processNameUpdate(UpdateNameTransaction nameUpdate)
{
//CHECK IF WE ARE OWNER
if(this.accountExists(nameUpdate.getOwner().getAddress()))
{
//CHECK IF OWNER CHANGED
if(!nameUpdate.getOwner().getAddress().equals(nameUpdate.getName().getOwner().getAddress()))
{
//DELETE PREVIOUS NAME
Name name = DBSet.getInstance().getUpdateNameMap().get(nameUpdate);
this.database.getNameMap().delete(nameUpdate.getOwner(), name);
}
}
//CHECK IF WE ARE NEW OWNER
if(this.accountExists(nameUpdate.getName().getOwner().getAddress()))
{
//ADD NAME
this.database.getNameMap().add(nameUpdate.getName());
}
}
private void orphanNameUpdate(UpdateNameTransaction nameUpdate)
{
//CHECK IF WE WERE OWNER
if(this.accountExists(nameUpdate.getOwner().getAddress()))
{
//CHECK IF OWNER WAS CHANGED
if(!nameUpdate.getOwner().getAddress().equals(nameUpdate.getName().getOwner().getAddress()))
{
//ADD PREVIOUS NAME
Name name = DBSet.getInstance().getNameMap().get(nameUpdate.getName().getName());
this.database.getNameMap().add(name);
}
}
//CHECK IF WE WERE NEW OWNER
if(this.accountExists(nameUpdate.getName().getOwner().getAddress()))
{
//ADD NAME
this.database.getNameMap().delete(nameUpdate.getName());
}
}
private void processNameSale(SellNameTransaction nameSaleTransaction)
{
//CHECK IF WE ARE SELLER
if(this.accountExists(nameSaleTransaction.getNameSale().getName().getOwner().getAddress()))
{
//ADD TO DATABASE
this.database.getNameSaleMap().add(nameSaleTransaction.getNameSale());
}
}
private void orphanNameSale(SellNameTransaction nameSaleTransaction)
{
//CHECK IF WE ARE SELLER
if(this.accountExists(nameSaleTransaction.getNameSale().getName().getOwner().getAddress()))
{
//REMOVE FROM DATABASE
this.database.getNameSaleMap().delete(nameSaleTransaction.getNameSale());
}
}
private void processCancelNameSale(CancelSellNameTransaction cancelNameSaleTransaction)
{
//CHECK IF WE ARE SELLER
if(this.accountExists(cancelNameSaleTransaction.getOwner().getAddress()))
{
//REMOVE FROM DATABASE
BigDecimal amount = DBSet.getInstance().getCancelSellNameMap().get(cancelNameSaleTransaction);
NameSale nameSale = new NameSale(cancelNameSaleTransaction.getName(), amount);
this.database.getNameSaleMap().delete(nameSale);
}
}
private void orphanCancelNameSale(CancelSellNameTransaction cancelNameSaleTransaction)
{
//CHECK IF WE ARE SELLER
if(this.accountExists(cancelNameSaleTransaction.getOwner().getAddress()))
{
//ADD TO DATABASE
NameSale nameSale = DBSet.getInstance().getNameExchangeMap().getNameSale(cancelNameSaleTransaction.getName());
this.database.getNameSaleMap().add(nameSale);
}
}
private void processNamePurchase(BuyNameTransaction namePurchase)
{
//CHECK IF WE ARE BUYER
if(this.accountExists(namePurchase.getBuyer().getAddress()))
{
//ADD NAME
Name name = DBSet.getInstance().getNameMap().get(namePurchase.getNameSale().getKey());
this.database.getNameMap().add(name);
}
//CHECK IF WE ARE SELLER
Account seller = namePurchase.getSeller();
if(this.accountExists(seller.getAddress()))
{
//DELETE NAMESALE
this.database.getNameSaleMap().delete(seller, namePurchase.getNameSale());
//DELETE NAME
Name name = DBSet.getInstance().getNameMap().get(namePurchase.getNameSale().getKey());
name.setOwner(seller);
this.database.getNameMap().delete(seller, name);
}
}
private void orphanNamePurchase(BuyNameTransaction namePurchase)
{
//CHECK IF WE WERE BUYER
if(this.accountExists(namePurchase.getBuyer().getAddress()))
{
//DELETE NAME
Name name = namePurchase.getNameSale().getName();
name.setOwner(namePurchase.getBuyer());
this.database.getNameMap().delete(namePurchase.getBuyer(), name);
}
//CHECK IF WE WERE SELLER
Account seller = namePurchase.getSeller();
if(this.accountExists(seller.getAddress()))
{
//ADD NAMESALE
this.database.getNameSaleMap().add(namePurchase.getNameSale());
//ADD NAME
Name name = namePurchase.getNameSale().getName();
this.database.getNameMap().add(name);
}
}
private void processAssetIssue(IssueAssetTransaction assetIssue)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE OWNER
if(this.accountExists(assetIssue.getAsset().getOwner().getAddress()))
{
//ADD POLL
this.database.getAssetMap().add(assetIssue.getAsset());
}
}
private void orphanAssetIssue(IssueAssetTransaction assetIssue)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE OWNER
if(this.accountExists(assetIssue.getAsset().getOwner().getAddress()))
{
//DELETE ASSET
this.database.getAssetMap().delete(assetIssue.getAsset());
}
}
private void processOrderCreation(CreateOrderTransaction orderCreation)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//ADD ORDER
this.addOrder(orderCreation.getOrder());
}
private void addOrder(Order order)
{
//CHECK IF WE ARE CREATOR
if(this.accountExists(order.getCreator().getAddress()))
{
//ADD ORDER
this.database.getOrderMap().add(order);
}
}
private void orphanOrderCreation(CreateOrderTransaction orderCreation)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE CREATOR
if(this.accountExists(orderCreation.getOrder().getCreator().getAddress()))
{
//DELETE ORDER
//this.database.getOrderMap().delete(orderCreation.getOrder());
}
}
private void processOrderCancel(CancelOrderTransaction orderCancel)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE CREATOR
if(this.accountExists(orderCancel.getCreator().getAddress()))
{
//DELETE ORDER
this.database.getOrderMap().delete(new Tuple2<String, BigInteger>(orderCancel.getCreator().getAddress(), orderCancel.getOrder()));
}
}
private void orphanOrderCancel(CancelOrderTransaction orderCancel)
{
//CHECK IF WALLET IS OPEN
if(!this.exists())
{
return;
}
//CHECK IF WE ARE CREATOR
if(this.accountExists(orderCancel.getCreator().getAddress()))
{
//DELETE ORDER
Order order = DBSet.getInstance().getOrderMap().get(orderCancel.getOrder());
this.database.getOrderMap().add(order);
}
}
@SuppressWarnings("unchecked")
@Override
public void update(Observable o, Object arg)
{
ObserverMessage message = (ObserverMessage) arg;
if(message.getType() == ObserverMessage.ADD_BLOCK_TYPE)
{
Block block = (Block) message.getValue();
//CHECK BLOCK
this.processBlock(block);
//CHECK TRANSACTIONS
for(Transaction transaction: block.getTransactions())
{
this.processTransaction(transaction);
//SKIP PAYMENT TRANSACTIONS
if (transaction instanceof PaymentTransaction)
{
continue;
}
//CHECK IF NAME REGISTRATION
else if(transaction instanceof RegisterNameTransaction) //false &&
{
this.processNameRegistration((RegisterNameTransaction) transaction);
}
//CHECK IF NAME UPDATE
else if(transaction instanceof UpdateNameTransaction)
{
this.processNameUpdate((UpdateNameTransaction) transaction);
}
//CHECK IF NAME SALE
else if(transaction instanceof SellNameTransaction)
{
this.processNameSale((SellNameTransaction) transaction);
}
//CHECK IF NAME SALE
else if(transaction instanceof CancelSellNameTransaction)
{
this.processCancelNameSale((CancelSellNameTransaction) transaction);
}
//CHECK IF NAME PURCHASE
else if(transaction instanceof BuyNameTransaction)
{
this.processNamePurchase((BuyNameTransaction) transaction);
}
//CHECK IF POLL CREATION
else if(transaction instanceof CreatePollTransaction)
{
this.processPollCreation((CreatePollTransaction) transaction);
}
//CHECK IF POLL VOTE
else if(transaction instanceof VoteOnPollTransaction)
{
this.processPollVote((VoteOnPollTransaction) transaction);
}
//CHECK IF ASSET ISSUE
else if(transaction instanceof IssueAssetTransaction)
{
this.processAssetIssue((IssueAssetTransaction) transaction);
}
//CHECK IF ORDER CREATION
/*if(transaction instanceof CreateOrderTransaction)
{
this.processOrderCreation((CreateOrderTransaction) transaction);
}*/
//CHECK IF ORDER CANCEL
else if(transaction instanceof CancelOrderTransaction)
{
this.processOrderCancel((CancelOrderTransaction) transaction);
}
}
}
else if(message.getType() == ObserverMessage.ADD_TRANSACTION_TYPE)
{
Transaction transaction = (Transaction) message.getValue();
this.processTransaction(transaction);
//CHECK IF PAYMENT
if (transaction instanceof PaymentTransaction)
{
}
//CHECK IF NAME REGISTRATION
else if(transaction instanceof RegisterNameTransaction)
{
this.processNameRegistration((RegisterNameTransaction) transaction);
}
//CHECK IF POLL CREATION
else if(transaction instanceof CreatePollTransaction)
{
this.processPollCreation((CreatePollTransaction) transaction);
}
//CHECK IF ASSET ISSUE
else if(transaction instanceof IssueAssetTransaction)
{
this.processAssetIssue((IssueAssetTransaction) transaction);
}
//CHECK IF ORDER CREATION
else if(transaction instanceof CreateOrderTransaction)
{
this.processOrderCreation((CreateOrderTransaction) transaction);
}
}
else if(message.getType() == ObserverMessage.REMOVE_BLOCK_TYPE)
{
Block block = (Block) message.getValue();
//CHECK BLOCK
this.orphanBlock(block);
//CHECK TRANSACTIONS
for(Transaction transaction: block.getTransactions())
{
this.orphanTransaction(transaction);
//CHECK IF NAME REGISTRATION
if(transaction instanceof RegisterNameTransaction)
{
this.orphanNameRegistration((RegisterNameTransaction) transaction);
}
//CHECK IF NAME UPDATE
else if(transaction instanceof UpdateNameTransaction)
{
this.orphanNameUpdate((UpdateNameTransaction) transaction);
}
//CHECK IF NAME SALE
else if(transaction instanceof SellNameTransaction)
{
this.orphanNameSale((SellNameTransaction) transaction);
}
//CHECK IF CANCEL NAME SALE
else if(transaction instanceof CancelSellNameTransaction)
{
this.orphanCancelNameSale((CancelSellNameTransaction) transaction);
}
//CHECK IF CANCEL NAME SALE
else if(transaction instanceof BuyNameTransaction)
{
this.orphanNamePurchase((BuyNameTransaction) transaction);
}
//CHECK IF POLL CREATION
else if(transaction instanceof CreatePollTransaction)
{
this.orphanPollCreation((CreatePollTransaction) transaction);
}
//CHECK IF POLL VOTE
else if(transaction instanceof VoteOnPollTransaction)
{
this.orphanPollVote((VoteOnPollTransaction) transaction);
}
//CHECK IF ASSET ISSUE
else if(transaction instanceof IssueAssetTransaction)
{
this.orphanAssetIssue((IssueAssetTransaction) transaction);
}
//CHECK IF ORDER CREATION
else if(transaction instanceof CreateOrderTransaction)
{
this.orphanOrderCreation((CreateOrderTransaction) transaction);
}
//CHECK IF ORDER CANCEL
else if(transaction instanceof CancelOrderTransaction)
{
this.orphanOrderCancel((CancelOrderTransaction) transaction);
}
}
}
else if(message.getType() == ObserverMessage.REMOVE_TRANSACTION_TYPE)
{
Transaction transaction = (Transaction) message.getValue();
this.orphanTransaction(transaction);
//CHECK IF PAYMENT
if (transaction instanceof PaymentTransaction)
{
}
//CHECK IF NAME REGISTRATION
else if(transaction instanceof RegisterNameTransaction)
{
this.orphanNameRegistration((RegisterNameTransaction) transaction);
}
//CHECK IF POLL CREATION
else if(transaction instanceof CreatePollTransaction)
{
this.orphanPollCreation((CreatePollTransaction) transaction);
}
//CHECK IF ASSET ISSUE
else if(transaction instanceof IssueAssetTransaction)
{
this.orphanAssetIssue((IssueAssetTransaction) transaction);
}
//CHECK IF ORDER CREATION
else if(transaction instanceof CreateOrderTransaction)
{
this.orphanOrderCreation((CreateOrderTransaction) transaction);
}
}
else if (message.getType() == ObserverMessage.ADD_AT_TX_TYPE)
{
this.processATTransaction( (Tuple2<Tuple2<Integer, Integer>, AT_Transaction>) message.getValue() );
}
else if (message.getType() == ObserverMessage.REMOVE_AT_TX)
{
this.orphanATTransaction( (Tuple2<Tuple2<Integer, Integer>, AT_Transaction>) message.getValue() );
}
//ADD ORDER
else if(message.getType() == ObserverMessage.ADD_ORDER_TYPE || message.getType() == ObserverMessage.REMOVE_ORDER_TYPE)
{
this.addOrder((Order) message.getValue());
}
}
//CLOSE
public void close()
{
if(this.database != null)
{
this.database.close();
}
if(this.secureDatabase != null)
{
this.secureDatabase.close();
}
}
public void commit()
{
if(this.database != null)
{
this.database.commit();
}
if(this.secureDatabase != null)
{
this.secureDatabase.commit();
}
}
public static class Timer2 implements Runnable {
public void run() {
int intsleep = 5;
boolean firsttime = true;
while(!done)
{
long nowTime = (System.currentTimeMillis()/1000 - startTime);
BigDecimal counterreal = BigDecimal.valueOf(counter).divide(BigDecimal.valueOf(intsleep));
if(!firsttime)
{
{
System.out.print("time: "+ nowTime + "s ");
intsleep = 5;
}
System.out.println("| tx/sec: " + counterreal.toPlainString());
}
counter = 0;
try {
Thread.sleep(intsleep*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
firsttime = false;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment