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());
}
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);
}
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);
}
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();
}
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());
}
Aggregations