Contract newContract = result.splitValue(fieldName, sum.subtract(value));
/** * Implementing split procedure for token-type contracts. * <br><br> * Service create new revision of given contract, split it to a pair of contracts with split amount. * <br><br> * Given contract should have splitjoin permission for given keys. * <br><br> * * @param c is contract should split be * @param amount is value that should be split from given contract * @param fieldName is name of field that should be split * @param keys is keys from owner of c * @param andSetCreator if true set owners as creator in both contarcts * @return working contract that should be register in the Universa to finish procedure. */ public synchronized static Contract createSplit(Contract c, BigDecimal amount, String fieldName, Set<PrivateKey> keys, boolean andSetCreator) { Contract splitFrom = c.createRevision(); Contract splitTo = splitFrom.splitValue(fieldName, new Decimal(amount)); for (PrivateKey key : keys) { splitFrom.addSignerKey(key); } if (andSetCreator) { splitTo.createRole("creator", splitTo.getRole("owner")); splitFrom.createRole("creator", splitFrom.getRole("owner")); } splitTo.seal(); splitFrom.seal(); return splitFrom; }
@Test public void shouldNotSplitWithAnotherIssuerSerialize() throws Exception { Contract c = createCoin(); c.addSignerKeyFromFile(PRIVATE_KEY_PATH); sealCheckTrace(c, true); Contract c2 = c.splitValue(FIELD_NAME, new Decimal(50)); c2.setIssuerKeys(ownerKey1.getPublicKey()); sealCheckTrace(c2, false); }
@Test public void splitLessThanMinValue() throws Exception { Contract root = createCoinWithAmount("200", FIELD_NAME); root = root.createRevision(); root.addSignerKeyFromFile(PRIVATE_KEY_PATH); Contract c1 = root.splitValue(FIELD_NAME, new Decimal("0.00001")); root.addSignerKey(ownerKey2); c1.addSignerKey(ownerKey2); sealCheckTrace(c1, false); sealCheckTrace(root, false); }
for (int i = 0; i < 6; i++) { contract = contract.createRevision(); Contract splitted = contract.splitValue(FIELD_NAME, new Decimal(15)); splitted.seal(); contract.addSignerKeyFromFile(privateKeyPath); } else { Contract splitting = splittedList.get(i).createRevision(); splittedChanges = splitting.splitValue(FIELD_NAME, new Decimal(5)); splittedChanges.seal(); splitting.addSignerKeyFromFile(privateKeyPath);
@Test public void splitJoinHasNotEnoughSumRevoking() throws Exception { Contract root = createCoinWithAmount("200", FIELD_NAME); Contract c1 = root.splitValue(FIELD_NAME, new Decimal(100)); sealCheckTrace(c1, true); // c1 split 50 50 c1 = c1.createRevision(ownerKey2); c1.seal(); Contract c50_1 = c1.splitValue(FIELD_NAME, new Decimal(50)); sealCheckTrace(c50_1, true); //set wrong revoking with the same amount root = root.createRevision(ownerKey2); root.seal(); // c1 split 45 5 c1 = c50_1.createRevision(ownerKey2); c1.seal(); Contract c5 = c1.splitValue(FIELD_NAME, new Decimal(5)); sealCheckTrace(c5, true); // coin amount: 200 (revoking: 100 and 50 and 5) root.getStateData().set(FIELD_NAME, new Decimal(200)); root.addRevokingItems(c50_1); root.addRevokingItems(c5); sealCheckTrace(root, false); }
@Test @Ignore("it is snatch test") public void splitSnatch() throws Exception { PrivateKey key = new PrivateKey(Do.read(ROOT_PATH + "_xer0yfe2nn1xthc.private.unikey")); Contract c1 = Contract.fromDslFile(ROOT_PATH + "coin100.yml"); c1.addSignerKey(key); assertTrue(c1.check()); c1.seal(); registerAndCheckApproved(c1); // Contract c1copy = new Contract(c1.getLastSealedBinary()); System.out.println("money before split (c1): " + c1.getStateData().getIntOrThrow("amount")); Contract c2 = c1.splitValue("amount", new Decimal(50)); System.out.println("money after split (c1): " + c1.getStateData().getIntOrThrow("amount")); System.out.println("money after split (c2): " + c2.getStateData().getIntOrThrow("amount")); // c2.addRevokingItems(c1copy); c2.getStateData().set("amount", 9000);//150); c2.seal(); System.out.println("money after snatch (c2): " + c2.getStateData().getIntOrThrow("amount")); System.out.println("check after snatch (c2): " + c2.check()); registerAndCheckDeclined(c2); }
@Test public void shouldSplitJoinHasEnoughSumRevoking() throws Exception { // 2 coins: 1st v: 50 (r: 50 and 50), 2nd v: 50 (r: 50 and 50) Contract root = createCoinWithAmount("200", FIELD_NAME); Contract c1 = root.splitValue(FIELD_NAME, new Decimal(100)); sealCheckTrace(c1, true); // c1 split 50 50 c1 = c1.createRevision(ownerKey2); c1.seal(); Contract c50_1 = c1.splitValue(FIELD_NAME, new Decimal(50)); sealCheckTrace(c50_1, true); //good join Contract finalC = c50_1.createRevision(ownerKey2); finalC.seal(); finalC.getStateData().set(FIELD_NAME, new Decimal(100)); finalC.addRevokingItems(c50_1); finalC.addRevokingItems(c1); sealCheckTrace(finalC, true); }
@Test public void splitJoinHasTwoDifferentCoinTypes() throws Exception { Contract root = createCoinWithAmount("200", FIELD_NAME); Contract c1 = root.splitValue(FIELD_NAME, new Decimal(100)); sealCheckTrace(c1, true); // c1 split 50 50 c1 = c1.createRevision(ownerKey2); c1.seal(); Contract c50_1 = c1.splitValue(FIELD_NAME, new Decimal(50)); sealCheckTrace(c50_1, true); //set wrong revoking with the same amount root = root.createRevision(ownerKey2); root.seal(); Contract cr50 = createCoinWithAmount("50", FIELD_NAME); // coin amount: 200 (revoking: 100 and 50 and 50 another different coin) root.getStateData().set(FIELD_NAME, new Decimal(200)); root.addRevokingItems(c50_1); root.addRevokingItems(cr50); sealCheckTrace(root, false); }
Contract c2 = c1.splitValue("amount", new Decimal(60)); System.out.println("money after split (c1): " + c1.getStateData().getIntOrThrow("amount")); System.out.println("money after split (c2): " + c2.getStateData().getIntOrThrow("amount"));
@Test public void shouldNotJoinWithWrongParent() throws Exception { Contract c = createCoin(); c.addSignerKeyFromFile(PRIVATE_KEY_PATH); Contract c1 = c.splitValue(FIELD_NAME, new Decimal(1)); Contract.ContractDev dev = c1.new ContractDev(c1); //Check after split. sealCheckTrace(c, true); //Set wrong parent HashId parent = HashId.withDigest(Do.randomNegativeBytes(64)); HashId origin = HashId.withDigest(Do.randomNegativeBytes(64)); dev.setParent(parent); dev.setOrigin(origin); c.getRevokingItems().add(dev.getContract()); sealCheckTrace(c, false); }
Contract splitted = forSplit.splitValue(FIELD_NAME, new Decimal(20)); splitted.seal(); forSplit.addSignerKeyFromFile(PRIVATE_KEY_PATH);
@Test public void shouldSplitWithChangedOwnerAndNewValueSerialize() throws Exception { int defaultValue = 1000000; int valueForSplit = 85; Contract c = createCoin(); c.addSignerKeyFromFile(PRIVATE_KEY_PATH); Binder d = c.getStateData(); sealCheckTrace(c, true); Contract c2 = c.splitValue(FIELD_NAME, new Decimal(valueForSplit)); c2.addSignerKey(ownerKey2); Binder d2 = c2.getStateData(); sealCheckTrace(c2, true); assertEquals(defaultValue - valueForSplit, d.getIntOrThrow(FIELD_NAME)); assertEquals(valueForSplit, d2.getIntOrThrow(FIELD_NAME)); }
@Test public void overSpending() throws Exception { Contract root = createCoinWithAmount("200", FIELD_NAME); root = root.createRevision(); root.addSignerKeyFromFile(PRIVATE_KEY_PATH); Contract c1 = root.splitValue(FIELD_NAME, new Decimal(100)); root.addSignerKey(ownerKey2); c1.addSignerKey(ownerKey2); sealCheckTrace(c1, true); sealCheckTrace(root, true); // c1 == 100 // now reset root to 200: root.getStateData().set(FIELD_NAME, new Decimal(200)); // total now is 300 (200 + 100) - and must be rejected sealCheckTrace(root, false); }
Contract c1 = root.splitValue(FIELD_NAME, new Decimal(100)); c1.seal(); assertTrue(root.check()); Contract c50_1 = c1.splitValue(FIELD_NAME, new Decimal(50)); c50_1.seal(); assertTrue(c50_1.isOk());
@Test public void shouldNotJoinWithWrongAmount() throws Exception { int amount = 1000000; int v = 1; Contract c = createCoin(); c.addSignerKeyFromFile(PRIVATE_KEY_PATH); sealCheckTrace(c, true); // Split with 1 Contract c2 = c.splitValue(FIELD_NAME, new Decimal(v)); assertEquals(amount - v, c.getStateData().getIntOrThrow(FIELD_NAME)); assertEquals(v, c2.getStateData().getIntOrThrow(FIELD_NAME)); sealCheckTrace(c2, true); Contract c3 = c.createRevision(ownerKey2); c3.getRevokingItems().add(c2); //Trying to hack the join and get bigger amount c3.getStateData().set(FIELD_NAME, new Decimal(v + 1)); assertEquals(amount - v, c.getStateData().getIntOrThrow(FIELD_NAME)); assertEquals(v + 1, c3.getStateData().getIntOrThrow(FIELD_NAME)); sealCheckTrace(c3, false); }
Contract splitted = forSplit.splitValue(FIELD_NAME, new Decimal(20)); splitted.seal(); forSplit.addSignerKeyFromFile(PRIVATE_KEY_PATH);
@Test public void testJoinSum() throws Exception { Contract c = createCoin(); c.addSignerKeyFromFile(PRIVATE_KEY_PATH); Binder d = c.getStateData(); int a = 1000000; assertEquals(a, d.getIntOrThrow(FIELD_NAME)); c.seal(); c.check(); c.traceErrors(); assertTrue(c.check()); // bad split: no changes Contract c1 = c.createRevision(ownerKey2); sealCheckTrace(c1, false); // Good split Contract c2 = c1.splitValue(FIELD_NAME, new Decimal(500)); assertEquals(a - 500, c1.getStateData().getIntOrThrow(FIELD_NAME)); assertEquals(500, c2.getStateData().getIntOrThrow(FIELD_NAME)); c1.getErrors().clear(); sealCheckTrace(c1, true); Contract c3 = c1.createRevision(ownerKey2); c3.getRevokingItems().add(c2); c3.getStateData().set(FIELD_NAME, new Decimal(a)); sealCheckTrace(c3, true); }
@Test public void cheatCreateValue() throws Exception { Contract c = createCoin(); c.addSignerKeyFromFile(PRIVATE_KEY_PATH); Binder d = c.getStateData(); int a = 1000000; assertEquals(a, d.getIntOrThrow(FIELD_NAME)); c.seal(); assertTrue(c.check()); Contract c1 = c.createRevision(ownerKey2); // Good split but wrong amount Contract c2 = c1.splitValue(FIELD_NAME, new Decimal(500)); assertEquals(a - 500, c1.getStateData().getIntOrThrow(FIELD_NAME)); assertEquals(500, c2.getStateData().getIntOrThrow(FIELD_NAME)); c2.getStateData().set(FIELD_NAME, "500.00000001"); sealCheckTrace(c1, false); }
Contract c2 = c1.splitValue(FIELD_NAME, new Decimal(500)); assertEquals(a - 500, c1.getStateData().getIntOrThrow(FIELD_NAME)); assertEquals(500, c2.getStateData().getIntOrThrow(FIELD_NAME));