From 5b4b972f78da1e636509bdc5a0a95e642400c73f Mon Sep 17 00:00:00 2001 From: tiero <3596602+tiero@users.noreply.github.com> Date: Fri, 18 Mar 2022 11:34:46 +0100 Subject: [PATCH 1/3] test: create an unblinded issuance together with an unblinded reissuance --- test/integration/issuances.spec.ts | 135 +++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/test/integration/issuances.spec.ts b/test/integration/issuances.spec.ts index 8cf96e11f..d1f1f831d 100644 --- a/test/integration/issuances.spec.ts +++ b/test/integration/issuances.spec.ts @@ -224,6 +224,141 @@ 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: address.fromOutputScript(alice.payment.output, regtest), + tokenAddress: address.fromOutputScript(alice.payment.output, regtest), + 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().set(0, aliceBlindingPrivkeys[0]), + // blind only the token output + new Map().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(); + 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().set(1, aliceBlindingPrivkeys[0]), + // blind only the token output + new Map() + .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); From b5ad16a5b85072944187908fde8786b165d75f62 Mon Sep 17 00:00:00 2001 From: tiero <3596602+tiero@users.noreply.github.com> Date: Fri, 18 Mar 2022 16:22:24 +0100 Subject: [PATCH 2/3] replicate issue with bash --- issuance-mixed-reissuance.sh | 58 ++++++++++++++++++++++++++++++ test/integration/issuances.spec.ts | 7 ++-- 2 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 issuance-mixed-reissuance.sh diff --git a/issuance-mixed-reissuance.sh b/issuance-mixed-reissuance.sh new file mode 100644 index 000000000..04f144037 --- /dev/null +++ b/issuance-mixed-reissuance.sh @@ -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 --liquid 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":"'$unconf_addr_random'"}]'` +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" \ No newline at end of file diff --git a/test/integration/issuances.spec.ts b/test/integration/issuances.spec.ts index d1f1f831d..9898acbaf 100644 --- a/test/integration/issuances.spec.ts +++ b/test/integration/issuances.spec.ts @@ -236,8 +236,8 @@ describe('liquidjs-lib (issuances transactions with psbt)', () => { const issuePsbt = new Psbt(); issuePsbt.addInput(inputData); issuePsbt.addIssuance({ - assetAddress: address.fromOutputScript(alice.payment.output, regtest), - tokenAddress: address.fromOutputScript(alice.payment.output, regtest), + assetAddress: alice.payment.confidentialAddress, + tokenAddress: alice.payment.confidentialAddress, assetAmount: 0.00000001, tokenAmount: 0.00000001, precision: 8, @@ -276,6 +276,7 @@ describe('liquidjs-lib (issuances transactions with psbt)', () => { 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); @@ -356,7 +357,7 @@ describe('liquidjs-lib (issuances transactions with psbt)', () => { reissuancePsbt.finalizeAllInputs(); const hexReissuance = reissuancePsbt.extractTransaction().toHex(); console.log(hexReissuance); - await broadcast(hexReissuance); + //await broadcast(hexReissuance); }); it('can create a confidential reissuance transaction from confidential issuance transaction', async () => { From fc42b23941c49392723183f75617046c34740c79 Mon Sep 17 00:00:00 2001 From: tiero <3596602+tiero@users.noreply.github.com> Date: Sat, 19 Mar 2022 22:12:03 +0100 Subject: [PATCH 3/3] fix bash script --liquid --- issuance-mixed-reissuance.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/issuance-mixed-reissuance.sh b/issuance-mixed-reissuance.sh index 04f144037..931ad2f52 100644 --- a/issuance-mixed-reissuance.sh +++ b/issuance-mixed-reissuance.sh @@ -7,7 +7,7 @@ conf_addr_for_reissuance_token=`$ecli getnewaddress` unconf_addr_random="ert1qtz89cfq54fdgekhu9m759pn3xpr64ek7mmm5ds" # Issue an asset with supply 0 -issued_asset=`$ecli --liquid issueasset 0 0.00000001 false` +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` @@ -41,7 +41,7 @@ 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":"'$unconf_addr_random'"}]'` +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'`