/****************************************************************************** * Copyright © 2013-2016 The Nxt Core Developers. * * * * See the AUTHORS.txt, DEVELOPER-AGREEMENT.txt and LICENSE.txt files at * * the top-level directory of this distribution for the individual copyright * * holder information and the developer policies on copyright and licensing. * * * * Unless otherwise agreed in a custom licensing agreement, no part of the * * Nxt software, including this file, may be copied, modified, propagated, * * or distributed except according to the terms contained in the LICENSE.txt * * file. * * * * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ package nxt.http.twophased; import nxt.Account; import nxt.BlockchainTest; import nxt.Constants; import nxt.http.APICall; import nxt.util.Convert; import org.json.simple.JSONObject; import org.junit.Assert; import org.junit.Test; public class TestTrustlessAssetSwap extends BlockchainTest { @Test public void assetSwap() { // Alice and Bob each has its own asset JSONObject aliceAsset = new APICall.Builder("issueAsset"). param("secretPhrase", ALICE.getSecretPhrase()). param("name", "AliceAsset"). param("description", "AliceAssetDescription"). param("quantityQNT", 1000). param("decimals", 0). param("feeNQT", 1000 * Constants.ONE_NXT). build().invoke(); generateBlock(); JSONObject bobAsset = new APICall.Builder("issueAsset"). param("secretPhrase", BOB.getSecretPhrase()). param("name", "BobAsset"). param("description", "BobAssetDescription"). param("quantityQNT", 1000). param("decimals", 0). param("feeNQT", 2000 * Constants.ONE_NXT). build().invoke(); generateBlock(); // Alice prepares and signs a transaction #1, an asset transfer to Bob. // She does not broadcast it, but sends to Bob the unsigned bytes, the // full transaction hash, and the signature hash. String aliceAssetId = (String) aliceAsset.get("transaction"); JSONObject aliceUnsignedTransfer = new APICall.Builder("transferAsset"). param("publicKey", ALICE.getPublicKeyStr()). param("recipient", BOB.getStrId()). param("asset", aliceAssetId). param("quantityQNT", 100). param("feeNQT", Constants.ONE_NXT). build().invoke(); JSONObject aliceSignedTransfer = new APICall.Builder("signTransaction"). param("secretPhrase", ALICE.getSecretPhrase()). param("unsignedTransactionBytes", (String)aliceUnsignedTransfer.get("unsignedTransactionBytes")). build().invoke(); String aliceTransferFullHash = (String)aliceSignedTransfer.get("fullHash"); Assert.assertEquals(64, aliceTransferFullHash.length()); String aliceTransferTransactionBytes = (String)aliceSignedTransfer.get("transactionBytes"); // Bob submits transaction #2, an asset transfer to Alice, making it phased using a by-transaction voting model // with a quorum of 1 and just the full hash of #1 in the phasing transaction full hashes list. String bobAssetId = (String) bobAsset.get("transaction"); JSONObject bobTransfer = new APICall.Builder("transferAsset"). param("secretPhrase", BOB.getSecretPhrase()). param("recipient", ALICE.getStrId()). param("asset", bobAssetId). param("quantityQNT", 200). param("feeNQT", 3 * Constants.ONE_NXT). param("phased", "true"). param("phasingFinishHeight", baseHeight + 5). param("phasingVotingModel", 4). param("phasingLinkedFullHash", aliceTransferFullHash). param("phasingQuorum", 1). build().invoke(); generateBlock(); // Alice sees Bob's transaction #2 in the blockchain, waits to make sure it is confirmed irreversibly. JSONObject bobTransferValidation = new APICall.Builder("getTransaction"). param("transaction", (String) bobTransfer.get("transaction")). build().invoke(); Assert.assertEquals(bobTransfer.get("transaction"), bobTransferValidation.get("transaction")); // She then submits her transaction #1. new APICall.Builder("broadcastTransaction"). param("transactionBytes", aliceTransferTransactionBytes). build().invoke(); generateBlock(); // Both transactions have executed Assert.assertEquals(200, Account.getAssetBalanceQNT(ALICE.getId(), Convert.parseUnsignedLong(bobAssetId))); Assert.assertEquals(100, Account.getAssetBalanceQNT(BOB.getId(), Convert.parseUnsignedLong(aliceAssetId))); } }