Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@bitjson
Last active November 29, 2022 20:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bitjson/12c7d7bba3b0a5d8ef83ef3b9096fede to your computer and use it in GitHub Desktop.
Save bitjson/12c7d7bba3b0a5d8ef83ef3b9096fede to your computer and use it in GitHub Desktop.
Treeless ZCE
{
"$schema": "https://ide.bitauth.com/authentication-template-v0.schema.json",
"description": "Instant, incentive-secure payments on Bitcoin Cash.\n\nThis is an alternative contract construction with better tradeoffs: bitcoincashresearch.org/t/chip-2021-08-zces-zero-confirmation-escrows/537/94#treeless-zce-1\n\nPrevious specification: github.com/bitjson/bch-zce",
"name": "Treeless Zero-Confirmation Escrows",
"entities": {
"customer": {
"description": "The individual who is sending a ZCE-secured payment to a merchant.",
"name": "Customer",
"scripts": [
"escrow_lock_1_input",
"customer_reclaim_1_input"
],
"variables": {
"reclaim_key": {
"description": "The private key that will allow the customer to reclaim his collateral in the event no double-spend attempt is seen on the network.",
"name": "Reclaim Key",
"type": "HdKey"
}
}
},
"miner": {
"description": "The miner who claims the ZCE collateral whenever 2 transactions spending an identical input used to fund the ZCE-secured transaction are seen on the BCH network.",
"name": "Miner",
"scripts": [
"miner_claim_via_input_1_1_input"
],
"variables": {
"zce_transaction_signing_serialization_hash": {
"description": "The hash of the signing serialization of the ZCE transaction; the 32-byte message signed by the covered public key.",
"name": "ZCE Transaction Signing Serialization Hash",
"type": "AddressData"
},
"fraudulent_transaction_signing_serialization_hash": {
"description": "The hash of the signing serialization of the fraudulent transaction; the 32-byte message signed by the covered public key.",
"name": "Fraudulent Transaction Signing Serialization Hash",
"type": "AddressData"
},
"zce_transaction_signature": {
"description": "The signature of the covered public key from the original ZCE-secured transaction.",
"name": "ZCE Transaction Signature",
"type": "AddressData"
},
"fraudulent_transaction_signature": {
"description": "The signature of the covered public key from the double spending transaction.",
"name": "Fraudulent Transaction Signature",
"type": "AddressData"
},
"covered_public_key": {
"description": "The public key that the miner is demonstrating was 1) among the public keys covered by the ZCE, and 2) used in an attempted double spent, entitling the miner to claim the ZCE.",
"name": "Covered Public Key",
"type": "AddressData"
},
"zce_transaction_start": {
"description": "The part of the encoded ZCE transaction occurring before the ZCE-covered public key.",
"name": "ZCE Transaction Start",
"type": "AddressData"
},
"zce_transaction_end": {
"description": "The part of the encoded ZCE transaction occurring after the ZCE-covered public key.",
"name": "ZCE Transaction End",
"type": "AddressData"
}
}
}
},
"scenarios": {
"base": {
"data": {
"bytecode": {
"zce_transaction_signing_serialization_hash": "0x66ff35a3f89e37c16a9e3b3e4d8503742b1bd56f946a3970b962a7943090281c",
"fraudulent_transaction_signing_serialization_hash": "0x25f64e88d7be06b6ac8a0a46637fde8ce5d4ea337aabc7a34266a2ff6bc96dab",
"zce_transaction_signature": "0x8e6f87f230491653157225d0180c3c1b8c024f46784d3c839099f9c5ab4385029141d4f2b4c7dae469784347de3a308af54f5d1349637068329200e6009d4333",
"fraudulent_transaction_signature": "0x4e6132855ed472fe377de7456065ce399eb0d1ddb441411d0fe9e6fb4f80dde252a2cc0da80c8f07127a24ecefe9081e9deae2e9af6dd731002f67e9a2733b2c",
"covered_public_key": "0x0376ea9e36a75d2ecf9c93a0be76885e36f822529db22acfdc761c9b5b4544f5c6",
"zce_transaction_start": "0x0376ea9e36a75d2ecf9c93a0be76885e36f822529db22acfdc761c9b5b4544f5c5",
"zce_transaction_end": "0x0376ea9e36a75d2ecf9c93a0be76885e36f822529db22acfdc761c9b5b4544f5c7"
}
},
"description": "",
"name": "Miner Claim via Second Input"
},
"miner_claim_via_input_1": {
"description": "",
"extends": "base",
"name": "Miner Claim via First Input"
},
"customer_reclaim": {
"description": "",
"extends": "base",
"name": "Customer Reclaim"
}
},
"scripts": {
"miner_claim_via_input_1_1_input": {
"estimate": "miner_claim_via_input_1",
"passes": [
"miner_claim_via_input_1"
],
"name": "Miner Claim",
"script": "<fraudulent_transaction_signature>\n<zce_transaction_signature>\n<fraudulent_transaction_signing_serialization_hash>\n<zce_transaction_signing_serialization_hash>\n<zce_transaction_start>\n<zce_transaction_end>\n<covered_public_key>",
"unlocks": "escrow_lock_1_input"
},
"customer_reclaim_1_input": {
"estimate": "miner_claim_via_input_1",
"passes": [
"miner_claim_via_input_1"
],
"name": "Customer Reclaim",
"script": "<reclaim_key.schnorr_signature.all_outputs>\n<reclaim_key.public_key>",
"unlocks": "escrow_lock_1_input"
},
"escrow_lock_1_input": {
"lockingType": "standard",
"name": "Escrow Lock (1 Input)",
"script": "// Let's check to see if this is the customer reclaiming the escrow.\nOP_DUP OP_HASH160 <$(<reclaim_key.public_key> OP_HASH160)> OP_EQUAL\nOP_IF\n // If so, let's perform a normal signature check.\n OP_CHECKSIG\nOP_ELSE\n /**\n * Since we're in the else block, this is a miner attempting\n * to confiscate the escrow by providing two signatures produced \n * by the public key of the input used to fund the ZCE-secured tx,\n * proving that the ZCE-secured payment was double spent by the\n * customer.\n */ \n OP_DUP OP_TOALTSTACK\n\n // Reconstruct the claimed ZCE-secured transaction:\n OP_SWAP OP_CAT OP_CAT\n // Get the hash of the claimed ZCE-secured transaction:\n OP_HASH256\n // Get the expected transaction hash of the ZCE transaction:\n OP_INPUTINDEX OP_OUTPOINTTXHASH /*\n OP_EQUALVERIFY */ OP_2DROP // (emulated)\n \n /**\n * Here we know that the public key provided by the miner was\n * covered by the ZCE: the transaction creating this ZCE\n * included the public key.\n * \n * On security:\n * Properly-created, ZCE-secured transactions only include public\n * keys in transaction unlocking bytecode (only P2PKH and\n * P2SH receiving addresses are allowed), so if the provided\n * 33-byte public key has signed two messages, we know either:\n * 1) a double spend was attempted from a covered public key, or\n * 2) the miner and merchant colluded to generate receiving output\n * material that includes a 33-byte public key for a known private\n * key, e.g. birthday attack over `valueSatoshis + P2PKH bytecode\n * (33 byte total), P2SH32 bytecode (35 bytes), etc. This attack\n * requires 2^128 steps (hashes or public key derivations),\n * equivalent to the work required to derive a private key from a\n * public key, making this scheme as secure as any private key.\n */\n\n // Verify that two different messages were signed:\n OP_2DUP\n OP_EQUAL <0> OP_EQUALVERIFY\n\n // Ensure both provided signatures (the honest tx and double-spend) \n // are valid.\n OP_FROMALTSTACK\n OP_DUP <4> OP_ROLL OP_2SWAP \n OP_CHECKDATASIGVERIFY\n OP_CHECKDATASIG\nOP_ENDIF\n"
}
},
"supported": [
"BCH_2022_05"
],
"version": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment