use of org.catena.common.CatenaWalletExtension in project catena-java by alinush.
the class ReorganizeChainTest method setUp.
@Before
public void setUp() throws Exception {
Context.propagate(new Context(params, 10000, Transaction.DEFAULT_TX_FEE, true));
semAppended = new Semaphore(0);
semWithdrawn = new Semaphore(0);
// Step 0: Catena wallet already started with a listener that signals when statements are appended and withdrawn
wallet = new ClientWallet(params);
wallet.addExtension(new CatenaWalletExtension());
// Generate a key to send mining rewards to
genCoinsKey = new ECKey();
wallet.importKey(genCoinsKey);
genCoinsAddr = genCoinsKey.toAddress(params);
// need to tell the wallet about the chain address by calling this
wallet.addWatchedAddress(genCoinsAddr);
// Generate a black hole key, where funds are send to be lost
blackholeAddr = new ECKey().toAddress(params);
// Add semaphores to wallet
wallet.addStatementListener(new SemaphoredStatementListener(wallet, semAppended, semWithdrawn));
wallet.addReorganizeEventListener(new WalletReorganizeEventListener() {
@Override
public void onReorganize(Wallet wallet) {
log.debug("Fork detected!");
}
});
// TODO: can set an onReorganize listener here
chain = new BlockChain(params, wallet, new MemoryBlockStore(params));
// Set a listener to wait for those coins
final Semaphore sem = new Semaphore(0);
wallet.addCoinsReceivedEventListener(new WalletCoinsReceivedEventListener() {
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
// log.debug("Got initial coins from mining reward: {}", newBalance);
sem.release();
}
});
// Create the first block, so we can get some coins.
lastBlock = params.getGenesisBlock().createNextBlock(genCoinsAddr);
chain.add(lastBlock);
// Bury the first block with enough blocks, so we can spend those coins
for (int i = 0; i < params.getSpendableCoinbaseDepth(); i++) {
lastBlock = lastBlock.createNextBlock(blackholeAddr);
chain.add(lastBlock);
}
log.debug("Created {} blocks.", chain.getBestChainHeight());
assertTrue("timed out waiting to receive coins from block reward", sem.tryAcquire(10, TimeUnit.SECONDS));
// Create the root-of-trust TXN
Transaction tx = issueStatement("testchain", false);
log.debug("Created root-of-trust TXN {}", tx.getHash());
// wallet.getCatenaExtension().setRootOfTrustTxid(rootOfTrustTxid); // already set by issueStatement
wallet.addChangeEventListener(Threading.SAME_THREAD, new CatenaWalletListener(wallet));
}
use of org.catena.common.CatenaWalletExtension in project catena-java by alinush.
the class ClientWallet method processRootOfTrustTxn.
/**
* Handles the root of trust TXN when received: we make sure it has the expected chain address in it (due to
* limitations of bitcoinj, we have to filter by the chainAddr and not the TXID)
*
* @param tx
* @return false if we haven't yet received the root-of-trust TXN, true if we received and validated it.
*/
protected boolean processRootOfTrustTxn(Transaction tx) {
// We don't start updating the Catena chain if the root-of-trust TX processing has failed
if (processedRootOfTrustTxn)
return true;
// See if we can find root-of-trust TXN in the wallet
CatenaWalletExtension ext = getCatenaExtension();
if (tx == null) {
// log.debug("Did not yet receive root-of-trust TXN");
return false;
}
log.debug("Processing root of trust TX {} ...", tx.getHashAsString());
if (CatenaUtils.maybeCatenaTx(tx) == false) {
log.error("Root-of-trust TXN is not a Catena TX: {}", tx);
queueOnWhistleblow(tx, "invalid root-of-trust TXN (not a Catena TX): " + tx);
return false;
}
// NOTE: We do not check the signature on this root-of-trust TX since it wouldn't give us much really.
// That's why we call this the "root-of-trust" TXN: we trust it to be unique in the blockchain.
String chainName = new String(CatenaUtils.getCatenaTxData(tx));
Address addr = tx.getOutput(0).getAddressFromP2PKHScript(getParams());
// NOTE: We're gonna get rid of this code in the future if bitcoinj
// allows us to restart the blockchain download once we obtain the
// root-of-trust TX.
Address expected = getChainAddress();
log.debug("Root-of-trust TXN chain address {} vs. expected chain addr {}", addr, expected);
if (addr.equals(expected) == false) {
log.error("Root-of-trust TXN's PK '{}' was not the expected PK '{}': {}", addr, expected, tx);
queueOnWhistleblow(tx, "The Catena chain's PK from the root-of-trust TX '" + addr + "' is different than the provided one '" + expected + "'");
return false;
}
log.debug("Saved the chain name in the wallet extension: " + chainName);
// the past.
if (ext.hasName() == false) {
ext.setName(chainName);
}
// Trigger a wallet save
saveNow();
processedRootOfTrustTxn = true;
return true;
}
use of org.catena.common.CatenaWalletExtension in project catena-java by alinush.
the class ClientWallet method isTransactionRelevant.
/**
* The client will never process the root-of-trust TX because it does not
* have its PK added to the wallet, so the TX will seem irrelevant to the
* wallet. To prevent that, we override this method.
*
* This method also adds the PK in the root-of-trust TX to the list of
* watched addresses.
*/
@Override
public boolean isTransactionRelevant(Transaction tx) throws ScriptException {
lock.lock();
try {
CatenaWalletExtension ext = getCatenaExtension();
boolean isRelevant = super.isTransactionRelevant(tx);
boolean isRootOfTrustTx = false;
if (ext.hasRootOfTrustTxid()) {
isRootOfTrustTx = ext.getRootOfTrustTxid().equals(tx.getHash());
if (isRootOfTrustTx) {
// NOTE: We save this in the wallet extension later, for now we just display them.
Address chainAddr = tx.getOutput(0).getAddressFromP2PKHScript(params);
log.debug("Identified chain address from root-of-trust TX " + tx.getHashAsString() + ": " + chainAddr);
if (ext.hasName() == false) {
log.debug("Also, identified chain name from root-of-trust TX " + tx.getHashAsString() + ": " + new String(CatenaUtils.getCatenaTxData(tx)));
}
checkState(chainAddr != null, "No P2PKH address in the root-of-trust TX's first output");
// NOTE: By the time we add the Catena chain's PK to the wallet it could be too late because bitcoinj
// might've downloaded future blocks (i.e., blocks past the root-of-trust block) and ignored Catena
// TXs in those blocks since it didn't have this PK in its Bloom filter yet. For now, this code
// doesn't have any effect until bitcoinj will handle blockchain redownloads. That's why we also pass
// the chain address to the CatenaClient constructor.
// addWatchedAddresses(ImmutableList.<Address>of(chainAddr), 1);
}
} else {
// log.trace("Too early to match root-of-trust TXN because TXID is not yet set in wallet extension.");
}
return isRelevant || isRootOfTrustTx;
} finally {
lock.unlock();
}
}
Aggregations