|
| 1 | +# Witness Validation |
| 2 | + |
| 3 | +TODO: provide a description of the ledger rules relevant to this domain specific concept. |
| 4 | + |
| 5 | +## Footgun #1: Bootstrap Witnesses |
| 6 | +Alonzo introduced a [`bootstrap_witness`](https://github.com/IntersectMBO/cardano-ledger/blob/d71d7923a79cfcde8cac0b5db399a5427524d06a/eras/allegra/impl/cddl-files/allegra.cddl#L314-L319), which is a different structure for witnesses from a bootstrap address. One would, perhaps reasonably, assume that all witnesses from bootstrap addresses would be provided in this list. However, that is not an assumption that can be made. |
| 7 | + |
| 8 | +### Example: `0c22edee0ffd7c8f32d2fe4da1f144e9ef78dfb51e1678d5198493a83d6cf8ec` |
| 9 | +Consider the following [transaction](https://preprod.cexplorer.io/tx/0c22edee0ffd7c8f32d2fe4da1f144e9ef78dfb51e1678d5198493a83d6cf8ec) on Preprod. In JSON, it looks like this: |
| 10 | +```json |
| 11 | +{ |
| 12 | + "id": "0c22edee0ffd7c8f32d2fe4da1f144e9ef78dfb51e1678d5198493a83d6cf8ec", |
| 13 | + "spends": "inputs", |
| 14 | + "inputs": [ |
| 15 | + { |
| 16 | + "transaction": { |
| 17 | + "id": "4a0f0fd2ea2e91b34065e3085448b211afdcf72f9db0b2d74d1f99246e16c860" |
| 18 | + }, |
| 19 | + "index": 1 |
| 20 | + }, |
| 21 | + { |
| 22 | + "transaction": { |
| 23 | + "id": "9157ee358b91c319a2e9dd087fe612d1c3d72d34fa4104bec13c8d37fd40b854" |
| 24 | + }, |
| 25 | + "index": 1 |
| 26 | + } |
| 27 | + ], |
| 28 | + "outputs": [ |
| 29 | + { |
| 30 | + "address": "FHnt4NL7yPXtiYgxWx33wH6JXA9cYxzGAgVG1iMmaX9muBogARkHTRkUox4g4aR", |
| 31 | + "value": { |
| 32 | + "ada": { |
| 33 | + "lovelace": 4832251 |
| 34 | + } |
| 35 | + } |
| 36 | + }, |
| 37 | + { |
| 38 | + "address": "addr_test1vpfnhjud440uspylt4pewj7uy8tr0adh84sjqgmnq09xssca7lf4g", |
| 39 | + "value": { |
| 40 | + "ada": { |
| 41 | + "lovelace": 5000000 |
| 42 | + } |
| 43 | + } |
| 44 | + } |
| 45 | + ], |
| 46 | + "fee": { |
| 47 | + "ada": { |
| 48 | + "lovelace": 167749 |
| 49 | + } |
| 50 | + }, |
| 51 | + "validityInterval": {}, |
| 52 | + "treasury": {}, |
| 53 | + "signatories": [ |
| 54 | + { |
| 55 | + "key": "b1ef2a278ebe7cfd563c30f1bb642fb6b5616e040792527e6cd58f119895d657", |
| 56 | + "signature": "4110259fb4433f462512d6fa69958070f9e365831962744e7e2e7a2f6a721a707ec4f213ff736fcc195490254dc9d22e0fe0552ae1781b965fc4d05bd5ebb304" |
| 57 | + } |
| 58 | + ], |
| 59 | + "cbor": "84a300828258204a0f0fd2ea2e91b34065e3085448b211afdcf72f9db0b2d74d1f99246e16c860018258209157ee358b91c319a2e9dd087fe612d1c3d72d34fa4104bec13c8d37fd40b85401018282582e82d818582483581c533bcb8dad5fc8049f5d43974bdc21d637f5b73d6120237303ca6843a1024101001a63bbc5a61a0049bbfb82581d60533bcb8dad5fc8049f5d43974bdc21d637f5b73d6120237303ca68431a004c4b40021a00028f45a10081825820b1ef2a278ebe7cfd563c30f1bb642fb6b5616e040792527e6cd58f119895d65758404110259fb4433f462512d6fa69958070f9e365831962744e7e2e7a2f6a721a707ec4f213ff736fcc195490254dc9d22e0fe0552ae1781b965fc4d05bd5ebb304f5f6" |
| 60 | +} |
| 61 | +``` |
| 62 | + |
| 63 | +Notably, there is only one signature, and it is not in the form of a bootstrap witness. If we look at the logic that collects vkey hashes that must be present in the witness set ([`getShelleyWitsVkeyNeededNoGov`](https://github.com/IntersectMBO/cardano-ledger/blob/d71d7923a79cfcde8cac0b5db399a5427524d06a/eras/shelley/impl/src/Cardano/Ledger/Shelley/UTxO.hs#L226-L249)), we can understand why. |
| 64 | +```hs |
| 65 | +inputAuthors :: Set (KeyHash 'Witness) |
| 66 | +inputAuthors = foldr' accum Set.empty (txBody ^. spendableInputsTxBodyF) |
| 67 | + where |
| 68 | + accum txin !ans = |
| 69 | + case txinLookup txin utxo' of |
| 70 | + Just txOut -> |
| 71 | + case txOut ^. addrTxOutL of |
| 72 | + Addr _ (KeyHashObj pay) _ -> Set.insert (asWitness pay) ans |
| 73 | + AddrBootstrap bootAddr -> |
| 74 | + Set.insert (asWitness (bootstrapKeyHash bootAddr)) ans |
| 75 | + _ -> ans |
| 76 | + Nothing -> ans |
| 77 | +``` |
| 78 | + |
| 79 | +Bootstrap witnesses and vkey witnesses are combined in the same set, since they are both just hash digests of the same size. That means, if one were to construct a bootstrap address with a payload containing only the keyhash, the validation would pass with a regular vkey witness, instead of a bootstrap witness. |
| 80 | + |
| 81 | +The witnesses themselves are valdiated in isolation–just that they are valid signatures on the required data–so the presence of a boostrap address does not necessarily require the presence of a bootstrap witness. |
0 commit comments