Search in sources :

Example 1 with CatenaWalletExtension

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));
}
Also used : Context(org.bitcoinj.core.Context) BlockChain(org.bitcoinj.core.BlockChain) ClientWallet(org.catena.client.ClientWallet) Wallet(org.bitcoinj.wallet.Wallet) CatenaWalletExtension(org.catena.common.CatenaWalletExtension) ClientWallet(org.catena.client.ClientWallet) ECKey(org.bitcoinj.core.ECKey) WalletReorganizeEventListener(org.bitcoinj.wallet.listeners.WalletReorganizeEventListener) WalletCoinsReceivedEventListener(org.bitcoinj.wallet.listeners.WalletCoinsReceivedEventListener) Semaphore(java.util.concurrent.Semaphore) MemoryBlockStore(org.bitcoinj.store.MemoryBlockStore) SemaphoredStatementListener(org.catena.common.SemaphoredStatementListener) Coin(org.bitcoinj.core.Coin) Transaction(org.bitcoinj.core.Transaction) Before(org.junit.Before)

Example 2 with CatenaWalletExtension

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;
}
Also used : Address(org.bitcoinj.core.Address) CatenaWalletExtension(org.catena.common.CatenaWalletExtension)

Example 3 with CatenaWalletExtension

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();
    }
}
Also used : Address(org.bitcoinj.core.Address) CatenaWalletExtension(org.catena.common.CatenaWalletExtension)

Aggregations

CatenaWalletExtension (org.catena.common.CatenaWalletExtension)3 Address (org.bitcoinj.core.Address)2 Semaphore (java.util.concurrent.Semaphore)1 BlockChain (org.bitcoinj.core.BlockChain)1 Coin (org.bitcoinj.core.Coin)1 Context (org.bitcoinj.core.Context)1 ECKey (org.bitcoinj.core.ECKey)1 Transaction (org.bitcoinj.core.Transaction)1 MemoryBlockStore (org.bitcoinj.store.MemoryBlockStore)1 Wallet (org.bitcoinj.wallet.Wallet)1 WalletCoinsReceivedEventListener (org.bitcoinj.wallet.listeners.WalletCoinsReceivedEventListener)1 WalletReorganizeEventListener (org.bitcoinj.wallet.listeners.WalletReorganizeEventListener)1 ClientWallet (org.catena.client.ClientWallet)1 SemaphoredStatementListener (org.catena.common.SemaphoredStatementListener)1 Before (org.junit.Before)1