Search in sources :

Example 1 with CatenaStatement

use of org.catena.common.CatenaStatement in project catena-java by alinush.

the class WriteChainTest method testFees.

// @Test
public void testFees() throws InsufficientMoneyException, IOException, InterruptedException {
    log.info("Test: Correct TXN fee");
    String[] s1 = TestUtils.generateStatements(1, 0);
    String[] s2 = TestUtils.generateStatements(1, 1);
    // Issue a TXN with the default fee
    Coin defaultFeePerKb = Context.get().getFeePerKb();
    log.debug("Default fee per KB: " + defaultFeePerKb.toFriendlyString());
    issueStatements(s1);
    // Set the fee per KB
    Coin customFeePerKb = Coin.SATOSHI.multiply(100000);
    log.debug("Custom fee per KB: " + customFeePerKb.toFriendlyString());
    catenaServer.setFeePerKb(customFeePerKb);
    // Issue a TXN with a different fee
    issueStatements(s2);
    // Check the TXNs fee
    Iterator<CatenaStatement> it = catenaServer.getCatenaWallet().statementIterator(true);
    CatenaStatement stmt1 = it.next();
    CatenaStatement stmt2 = it.next();
    Transaction tx1 = catenaServer.getCatenaWallet().getTransaction(stmt1.getTxHash());
    Transaction tx2 = catenaServer.getCatenaWallet().getTransaction(stmt2.getTxHash());
    log.debug("Default fee TXN #1: " + tx1);
    log.debug("Custom fee TXN #1: " + tx2);
    // FIXME: This fails because bitcoinj pays the wrong fee in calculateFee (check later)
    // assertCorrectFee(defaultFeePerKb, tx1);
    // assertCorrectFee(customFeePerKb, tx2);
    // There should be no extra statements after
    assertFalse(it.hasNext());
}
Also used : CatenaStatement(org.catena.common.CatenaStatement) Coin(org.bitcoinj.core.Coin) Transaction(org.bitcoinj.core.Transaction)

Example 2 with CatenaStatement

use of org.catena.common.CatenaStatement in project catena-java by alinush.

the class WriteChainTest method testTxnSize.

@Test
public void testTxnSize() throws InsufficientMoneyException, IOException, InterruptedException {
    log.info("Test: Average TXN size");
    int numStmts = 10;
    byte[][] s = new byte[numStmts][Sha256Hash.LENGTH];
    for (int i = 0; i < numStmts; i++) {
        byte[] hash = Sha256Hash.of(new String("" + i).getBytes()).getBytes();
        assertEquals(Sha256Hash.LENGTH, hash.length);
        System.arraycopy(hash, 0, s[i], 0, hash.length);
        issueStatement(s[i]);
    }
    Iterator<CatenaStatement> it = catenaServer.getCatenaWallet().statementIterator(true);
    int i = 0;
    int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
    double avg = 0.0;
    while (it.hasNext()) {
        i++;
        CatenaStatement stmt = it.next();
        Transaction tx = catenaServer.getCatenaWallet().getTransaction(stmt.getTxHash());
        int size = tx.unsafeBitcoinSerialize().length;
        // 1000 bytes = 1 kB
        // log.debug("TXN #{} size in kB: {}", i, ((double)size)/1000.0);
        log.debug("TXN #{} size in bytes: {} (OP_RETURN data: {} bytes): {}", i, size, CatenaUtils.getCatenaTxData(tx).length, tx);
        min = min > size ? size : min;
        max = max < size ? size : max;
        avg += size;
    }
    avg = avg / numStmts;
    log.info("Min: {}, Max: {}, Avg: {}", min, max, avg);
}
Also used : CatenaStatement(org.catena.common.CatenaStatement) Transaction(org.bitcoinj.core.Transaction) Test(org.junit.Test) ClientServerTest(org.catena.common.ClientServerTest)

Example 3 with CatenaStatement

use of org.catena.common.CatenaStatement in project catena-java by alinush.

the class ReadChainTest method testRestartHelper.

public void testRestartHelper(boolean reuseWallet) throws InsufficientMoneyException, IOException, InterruptedException {
    // Issue some initial statements
    testStartAndIssue();
    // Stop the 1st client from the previous test
    log.debug("Stoping 1st Catena client...");
    log.debug("----------------------------");
    log.trace("1st client's wallet: " + CatenaUtils.summarizeWallet(catenaClient.wallet()));
    // Count the number of initial issued statements in the testReadBefore() call
    // (We'll need this to make sure that the restarted client still has the same
    // number of statements)
    int numPrevStmts = catenaClient.getCatenaWallet().getNumStatements();
    stopCatenaClient();
    // Simulate a restart: start new Catena client, with the previous wallet
    // or a new wallet, as specified in 'reuseWallet'
    Semaphore sem;
    if (reuseWallet) {
        log.debug("Rebooting the Catena client (same wallet)...");
        // We're reusing the wallet here so the statement
        // listener won't be called for the initial statements, just for
        // the extra ones we issue below.
        restartCatenaClient(true);
        // Need to get the semaphore the client was created with, so we can wait for statements using it
        sem = semAppended;
    } else {
        log.debug("Starting up a fresh 2nd Catena client (new wallet)...");
        sem = new Semaphore(0);
        createSemaphoredCatenaClient(txid, sem, null);
        // We're not reusing the wallet, but creating a new one, so
        // our statement listener will be called both for the initial statements
        // we issued in testReadBefore() and the extra statements issued below.
        // 
        // It looks like client might start without finishing full blockchain
        // download so we should wait for the initial statements here.
        log.debug("Waiting for the previous {} statements", numPrevStmts);
        waitForStatements(numPrevStmts, sem);
    }
    // Check that the restarted wallet still has the initially issued statements
    assertEquals((reuseWallet ? "restarted" : "new") + " wallet did not have all previous statements in it", numPrevStmts, catenaClient.getCatenaWallet().getNumStatements());
    log.trace("2nd client's wallet: " + CatenaUtils.summarizeWallet(catenaClient.wallet()));
    // log.trace("2nd client's wallet full description: " + catenaClient.wallet());
    // Step 2: Issue a couple of extra statements
    String[] stmts = new String[] { "extra1", "extra2" };
    issueStatements(stmts);
    // Step 3: Wait for those extra statements and possibly the initial ones too
    waitForStatements(stmts.length, sem);
    // Step 4: Check that we received the last statements correctly
    Iterator<CatenaStatement> it = catenaClient.getCatenaWallet().statementIterator(false);
    int i = stmts.length - 1;
    assertTrue(it.hasNext());
    while (it.hasNext() && i >= 0) {
        String s = it.next().getAsString();
        log.debug("Extra statement in Catena TX: " + s);
        assertEquals(s, stmts[i]);
        i--;
    }
    assertEquals("iterator did not consume all extra statemetns", -1, i);
    // Consume the other statements as well
    int count = 0;
    while (it.hasNext()) {
        String s = it.next().getAsString();
        log.debug("Initial statement in Catena TX: " + s);
        count++;
    }
    assertEquals("something went wrong while iterating over initial statements after getting extra statements", numPrevStmts, count);
}
Also used : CatenaStatement(org.catena.common.CatenaStatement) Semaphore(java.util.concurrent.Semaphore)

Example 4 with CatenaStatement

use of org.catena.common.CatenaStatement in project catena-java by alinush.

the class ClientWallet method getCatenaBuildingTxns.

/**
 * Returns an iterator over all the BUILDING Catena TXs (not sure about the order).
 */
private Iterator<Transaction> getCatenaBuildingTxns() {
    checkState(lock.isHeldByCurrentThread());
    Sha256Hash rootOfTrustTxid = getCatenaExtension().getRootOfTrustTxid();
    // We do not include root-of-trust TXN, since it cannot be double spent and we might not have the TX it spends
    // in the wallet, which will cause the calling code to fail.
    List<Transaction> buildingTxns = new ArrayList<Transaction>();
    boolean skipped = false;
    for (CatenaStatement s : bq) {
        if (!skipped && s.getTxHash().equals(rootOfTrustTxid)) {
            skipped = true;
            continue;
        }
        buildingTxns.add(getTransaction(s.getTxHash()));
    }
    return buildingTxns.iterator();
}
Also used : CatenaStatement(org.catena.common.CatenaStatement) Transaction(org.bitcoinj.core.Transaction) Sha256Hash(org.bitcoinj.core.Sha256Hash) ArrayList(java.util.ArrayList) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList)

Example 5 with CatenaStatement

use of org.catena.common.CatenaStatement in project catena-java by alinush.

the class ClientWallet method statementIterator.

/**
 * Returns an iterator over the confirmed Catena statements in order of issuance if isFwd is true and in reverse
 * otherwise. Does not include the root-of-trust TXN.
 *
 * @param isFwd
 * @return
 */
@Override
@VisibleForTesting
public Iterator<CatenaStatement> statementIterator(boolean isFwd) {
    final Vector<CatenaStatement> bqCopy;
    // WARNING: Do not call wallet() methods here as you could cause a deadlock: updateCatenaLog() has the
    // wallet lock and needs the bq lock, and this function has the bq lock and would need the wallet() lock.
    // 
    // We copy the the statements in BQ, because BQ could get modified while we iterate over it.
    lock.lock();
    try {
        // We do not count the root-of-trust TXN;
        if (bq.size() <= 1)
            return Collections.emptyIterator();
        bqCopy = new Vector<CatenaStatement>(bq.size());
        // NOTE: We ignore the root-of-trust TXN
        if (isFwd) {
            for (int i = 1; i < bq.size(); i++) bqCopy.add(bq.get(i));
        } else {
            for (int i = bq.size() - 1; i >= 1; i--) bqCopy.add(bq.get(i));
        }
    } finally {
        lock.unlock();
    }
    return Iterators.unmodifiableIterator(bqCopy.iterator());
}
Also used : CatenaStatement(org.catena.common.CatenaStatement) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Aggregations

CatenaStatement (org.catena.common.CatenaStatement)6 Transaction (org.bitcoinj.core.Transaction)4 ArrayList (java.util.ArrayList)2 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)2 Sha256Hash (org.bitcoinj.core.Sha256Hash)2 TransactionOutPoint (org.bitcoinj.core.TransactionOutPoint)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Map (java.util.Map)1 Stack (java.util.Stack)1 Semaphore (java.util.concurrent.Semaphore)1 Coin (org.bitcoinj.core.Coin)1 TransactionOutput (org.bitcoinj.core.TransactionOutput)1 ClientServerTest (org.catena.common.ClientServerTest)1 Test (org.junit.Test)1