Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: create an unblinded issuance together with an unblinded reissuance #46

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions issuance-mixed-reissuance.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env bash

# change with yor own elements-cli config
ecli="nigiri rpc --liquid"

conf_addr_for_reissuance_token=`$ecli getnewaddress`
unconf_addr_random="ert1qtz89cfq54fdgekhu9m759pn3xpr64ek7mmm5ds"

# Issue an asset with supply 0
issued_asset=`$ecli issueasset 0 0.00000001 false`
txid=`echo $issued_asset | jq -r .txid`
asset=`echo $issued_asset | jq -r .asset`
token=`echo $issued_asset | jq -r .token`
vin=`echo $issued_asset | jq -r .vin`
entropy=`echo $issued_asset | jq -r .entropy`
echo "txid: $txid"
echo "vin: $vin"
echo "asset: $asset"
echo "token: $token"
echo "entropy: $entropy"
issaunce_tx=`$ecli gettransaction $txid`
assetblinder=`echo $issaunce_tx | jq -r '.details | .[0] | .assetblinder'`
echo "assetblinder: $assetblinder"

$ecli generatetoaddress 1 $conf_addr_for_reissuance_token


# create raw transaction that sends 0.0015 BTC unblinded to someone, attaching the reissuance token already
# the vout 1 is always the reissaunce token (most of the time)
empty_tx=`$ecli createrawtransaction '[{"txid": "'$txid'", "vout": 1}]' '[{"'$conf_addr_for_reissuance_token'":0.00000001, "asset": "'$token'"}, {"'$unconf_addr_random'": 0.0015}]'`


# fund the btc input
result_funded_tx=`$ecli fundrawtransaction "$empty_tx"`
funded_tx=`echo $result_funded_tx | jq -r .hex`


# attach reissuance stuff
result_reissue_tx=`$ecli rawreissueasset "$funded_tx" '[{"asset_amount":0.0025,"asset_address":"'$unconf_addr_random'", "input_index":0, "asset_blinder":"'$assetblinder'", "entropy":"'$entropy'"}]'`
reissue_tx=`echo $result_reissue_tx | jq -r .hex`


# attach NFT issuance stuff
result_issue_tx=`$ecli rawissueasset "$reissue_tx" '[{"asset_amount":0.00000001,"asset_address":"'$conf_addr_for_reissuance_token'"}]'`
issue_tx=`echo $result_issue_tx | jq -r '.[0] | .hex'`


# blind
blind_tx=`$ecli blindrawtransaction "$issue_tx"`

# sign with wallet
result_signed_tx=`$ecli signrawtransactionwithwallet "$blind_tx"`
signed_tx=`echo $result_signed_tx | jq -r .hex`

echo "signed_tx: $signed_tx"

# broadcast
$ecli sendrawtransaction "$signed_tx"
136 changes: 136 additions & 0 deletions test/integration/issuances.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,142 @@ describe('liquidjs-lib (issuances transactions with psbt)', () => {
await broadcast(hex);
});

it.only('can create an unblinded issuance together with an unblinded reissuance', async () => {
const alice = createPayment('p2wpkh', undefined, undefined, true);
const aliceBlindingPrivkeys = alice.blindingKeys;
// btc utxo
const inputData = await getInputData(alice.payment, true, 'noredeem');

// const reissuableAssetPay = createPayment('p2wpkh', undefined, undefined, true); // unconfidential

// 1. issue the reissubale asset first
const issuePsbt = new Psbt();
issuePsbt.addInput(inputData);
issuePsbt.addIssuance({
assetAddress: alice.payment.confidentialAddress,
tokenAddress: alice.payment.confidentialAddress,
assetAmount: 0.00000001,
tokenAmount: 0.00000001,
precision: 8,
blindedIssuance: false,
});
issuePsbt.addOutputs([
{
nonce,
asset,
value: confidential.satoshiToConfidentialValue(99999500),
script: alice.payment.output,
},
{
nonce,
asset,
value: confidential.satoshiToConfidentialValue(500),
script: Buffer.alloc(0),
},
]);
// blind the token output
await issuePsbt.blindOutputsByIndex(
Psbt.ECCKeysGenerator(ecc),
new Map<number, Buffer>().set(0, aliceBlindingPrivkeys[0]),
// blind only the token output
new Map<number, Buffer>().set(
1,
fromConfidential(alice.payment.confidentialAddress).blindingKey,
),
);
// sign the issuance
issuePsbt.signAllInputs(alice.keys[0]);
const valid = issuePsbt.validateSignaturesOfAllInputs(
Psbt.ECDSASigValidator(ecc),
);
strictEqual(valid, true);

issuePsbt.finalizeAllInputs();
const hex = issuePsbt.extractTransaction().toHex();
console.log(hex)
await broadcast(hex);
// 2. reissue the asset together with an issuance
const issuanceTx = Transaction.fromHex(hex);
const issuanceInput = issuanceTx.ins[0];

if (!issuanceInput.issuance) {
throw new Error('no issuance in issuance input');
}

const entropy = issuanceEntropyFromInput(issuanceInput);

const tokenOutput = issuanceTx.outs[1];
const changeOutput = issuanceTx.outs[2];

const unblindedTokenOutput = await confidential.unblindOutputWithKey(
tokenOutput,
aliceBlindingPrivkeys[0],
);

const tokenBlinder = unblindedTokenOutput.assetBlindingFactor;

const reissuancePsbt = new Psbt()
.addInput({
hash: issuanceTx.getId(),
index: 2,
witnessUtxo: changeOutput,
})
.addOutput({
nonce,
asset,
value: confidential.satoshiToConfidentialValue(99998500),
script: alice.payment.output,
})
.addReissuance({
entropy,
tokenPrevout: { txHash: issuanceTx.getHash(false), vout: 1 },
prevoutBlinder: tokenBlinder,
witnessUtxo: tokenOutput,
assetAmount: 0.005,
tokenAmount: 0.00000001,
assetAddress: alice.payment.confidentialAddress,
tokenAddress: alice.payment.confidentialAddress,
precision: 8,
blindedIssuance: false
})
.addIssuance({
assetAddress: alice.payment.confidentialAddress,
assetAmount: 1,
tokenAmount: 0,
precision: 0,
blindedIssuance: false,
})
.addOutput({
nonce,
asset,
value: confidential.satoshiToConfidentialValue(1000),
script: Buffer.alloc(0),
});

// blind the token output
await reissuancePsbt.blindOutputsByIndex(
Psbt.ECCKeysGenerator(ecc),
new Map<number, Buffer>().set(1, aliceBlindingPrivkeys[0]),
// blind only the token output
new Map<number, Buffer>()
.set(
2,
fromConfidential(alice.payment.confidentialAddress).blindingKey,
)
);
// sign the issuance
reissuancePsbt.signAllInputs(alice.keys[0]);
const validReissuance = reissuancePsbt.validateSignaturesOfAllInputs(
Psbt.ECDSASigValidator(ecc),
);
strictEqual(validReissuance, true);

reissuancePsbt.finalizeAllInputs();
const hexReissuance = reissuancePsbt.extractTransaction().toHex();
console.log(hexReissuance);
//await broadcast(hexReissuance);
});

it('can create a confidential reissuance transaction from confidential issuance transaction', async () => {
// Issuance
const alice = createPayment('p2wpkh', undefined, undefined, true);
Expand Down