Anthony Towns [ARCHIVE] on Nostr: 📅 Original date posted:2022-03-10 📝 Original message:On Tue, Mar 08, 2022 at ...
📅 Original date posted:2022-03-10
📝 Original message:On Tue, Mar 08, 2022 at 06:54:56PM -0800, Bram Cohen via bitcoin-dev wrote:
> On Mon, Mar 7, 2022 at 5:27 PM Anthony Towns <aj at erisian.com.au> wrote:
> > One way to match the way bitcoin do things, you could have the "list of
> > extra conditions" encoded explicitly in the transaction via the annex,
> > and then check the extra conditions when the script is executed.
> The conditions are already basically what's in transactions. I think the
> only thing missing is the assertion about one's own id, which could be
> added in by, in addition to passing the scriptpubkey the transaction it's
> part of, also passing in the index of inputs which it itself is.
To redo the singleton pattern in bitcoin's context, I think you'd have
to pass in both the full tx you're spending (to be able to get the
txid of its parent) and the full tx of its parent (to be able to get
the scriptPubKey that your utxo spent) which seems klunky but at least
possible (you'd be able to drop the witness data at least; without that
every tx would be including the entire history of the singleton).
> > > A nice side benefit of sticking with the UTXO model is that the soft fork
> > > hook can be that all unknown opcodes make the entire thing automatically
> > > pass.
> > I don't think that works well if you want to allow the spender (the
> > puzzle solution) to be able to use opcodes introduced in a soft-fork
> > (eg, for graftroot-like behaviour)?
> This is already the approach to soft forking in Bitcoin script and I don't
> see anything wrong with it.
It's fine in Bitcoin script, because the scriptPubKey already commits to
all the opcodes that can possibly be used for any particular output. With
a lisp approach, however, you could pass in additional code fragments
to execute. For example, where you currently say:
script: [pubkey] CHECKSIG
witness: [64B signature][0x83]
(where 0x83 is SINGLE|ANYONECANPAY) you might translate that to:
script: (checksig pubkey (bip342-txmsg 3) 2)
witness: signature 0x83
where "3" grabs the sighash byte, and "2" grabs the signature. But you
could also translate it to:
script: (checksig pubkey (sha256 3 (a 3)) 2)
witness: signature (bip342-txmsg 0x83)
where "a 3" takes "(bip342-txmsg 0x83)" then evaluates it, and (sha256
3 (a 3)) makes sure you've signed off on both how the message was
constructed as well as what the message was. The advantage there is that
the spender can then create their own signature hashes however they like;
even ones that hadn't been thought of when the output was created.
But what if we later softfork in a bip118-txmsg for quick and easy
ANYPREVOUT style-signatures, and want to use that instead of custom
lisp code? You can't just stick (softfork C (bip118-txmsg 0xc3)) into
the witness, because it will evaluate to nil and you won't be signing
anything. But you *could* change the script to something like:
script: (softfork C (q checksigverify pubkey (a 3) 2))
witness: signature (bip118-txmsg 0xc3)
But what happens if the witness instead has:
script: (softfork C (q checksigverify pubkey (a 3) 2))
witness: fake-signature (fakeopcode 0xff)
If softfork is just doing a best effort for whatever opcodes it knows
about, and otherwise succeeding, then it has to succeed, and your
script/output has become anyone-can-spend.
On the other hand, if you could tell the softfork op that you only wanted
ops up-to-and-including the 118 softfork, then it could reject fakeopcode
and fail the script, which I think gives the desirable behaviour.
Cheers,
aj
Published at
2023-06-07 23:05:22Event JSON
{
"id": "ec697bfaf31b350705eda91e675267ee427c7700eeca578bd2c2191834767762",
"pubkey": "f0feda6ad58ea9f486e469f87b3b9996494363a26982b864667c5d8acb0542ab",
"created_at": 1686179122,
"kind": 1,
"tags": [
[
"e",
"17a237ce59197bc5ffad96769beec5209b19830977cb935d9412190ad411e7e9",
"",
"root"
],
[
"e",
"7b6533428141c85fbbccb1239b3d8edf484712a14aad5642aad76b9ccef8dfcd",
"",
"reply"
],
[
"p",
"fb7007c42a06687e3cd3fbbb1a3b17972e2a949ae679445f6b96579114d05cd9"
]
],
"content": "📅 Original date posted:2022-03-10\n📝 Original message:On Tue, Mar 08, 2022 at 06:54:56PM -0800, Bram Cohen via bitcoin-dev wrote:\n\u003e On Mon, Mar 7, 2022 at 5:27 PM Anthony Towns \u003caj at erisian.com.au\u003e wrote:\n\u003e \u003e One way to match the way bitcoin do things, you could have the \"list of\n\u003e \u003e extra conditions\" encoded explicitly in the transaction via the annex,\n\u003e \u003e and then check the extra conditions when the script is executed.\n\u003e The conditions are already basically what's in transactions. I think the\n\u003e only thing missing is the assertion about one's own id, which could be\n\u003e added in by, in addition to passing the scriptpubkey the transaction it's\n\u003e part of, also passing in the index of inputs which it itself is.\n\nTo redo the singleton pattern in bitcoin's context, I think you'd have\nto pass in both the full tx you're spending (to be able to get the\ntxid of its parent) and the full tx of its parent (to be able to get\nthe scriptPubKey that your utxo spent) which seems klunky but at least\npossible (you'd be able to drop the witness data at least; without that\nevery tx would be including the entire history of the singleton).\n\n\u003e \u003e \u003e A nice side benefit of sticking with the UTXO model is that the soft fork\n\u003e \u003e \u003e hook can be that all unknown opcodes make the entire thing automatically\n\u003e \u003e \u003e pass.\n\u003e \u003e I don't think that works well if you want to allow the spender (the\n\u003e \u003e puzzle solution) to be able to use opcodes introduced in a soft-fork\n\u003e \u003e (eg, for graftroot-like behaviour)?\n\u003e This is already the approach to soft forking in Bitcoin script and I don't\n\u003e see anything wrong with it.\n\nIt's fine in Bitcoin script, because the scriptPubKey already commits to\nall the opcodes that can possibly be used for any particular output. With\na lisp approach, however, you could pass in additional code fragments\nto execute. For example, where you currently say:\n\n script: [pubkey] CHECKSIG\n witness: [64B signature][0x83]\n\n(where 0x83 is SINGLE|ANYONECANPAY) you might translate that to:\n\n script: (checksig pubkey (bip342-txmsg 3) 2)\n witness: signature 0x83\n\nwhere \"3\" grabs the sighash byte, and \"2\" grabs the signature. But you\ncould also translate it to:\n\n script: (checksig pubkey (sha256 3 (a 3)) 2)\n witness: signature (bip342-txmsg 0x83)\n\nwhere \"a 3\" takes \"(bip342-txmsg 0x83)\" then evaluates it, and (sha256\n3 (a 3)) makes sure you've signed off on both how the message was\nconstructed as well as what the message was. The advantage there is that\nthe spender can then create their own signature hashes however they like;\neven ones that hadn't been thought of when the output was created.\n\nBut what if we later softfork in a bip118-txmsg for quick and easy\nANYPREVOUT style-signatures, and want to use that instead of custom\nlisp code? You can't just stick (softfork C (bip118-txmsg 0xc3)) into\nthe witness, because it will evaluate to nil and you won't be signing\nanything. But you *could* change the script to something like:\n\n script: (softfork C (q checksigverify pubkey (a 3) 2))\n witness: signature (bip118-txmsg 0xc3)\n\nBut what happens if the witness instead has:\n\n script: (softfork C (q checksigverify pubkey (a 3) 2))\n witness: fake-signature (fakeopcode 0xff)\n\nIf softfork is just doing a best effort for whatever opcodes it knows\nabout, and otherwise succeeding, then it has to succeed, and your\nscript/output has become anyone-can-spend.\n\nOn the other hand, if you could tell the softfork op that you only wanted\nops up-to-and-including the 118 softfork, then it could reject fakeopcode\nand fail the script, which I think gives the desirable behaviour.\n\nCheers,\naj",
"sig": "260fc251d3e008287606ed8ee6275b2d8227df132e19366ea1404898c64f1f08b18c99742a01f78948073c133ca1946f3e8d852e40428577cadaad52e14c4900"
}