| 108 | } |
| 109 | |
| 110 | struct onion_payload *onion_decode(const tal_t *ctx, |
| 111 | const struct route_step *rs, |
| 112 | const struct pubkey *blinding, |
| 113 | const struct secret *blinding_ss, |
| 114 | const u64 *accepted_extra_tlvs, |
| 115 | u64 *failtlvtype, |
| 116 | size_t *failtlvpos) |
| 117 | { |
| 118 | struct onion_payload *p = tal(ctx, struct onion_payload); |
| 119 | const u8 *cursor = rs->raw_payload; |
| 120 | size_t max = tal_bytelen(cursor), len; |
| 121 | struct tlv_tlv_payload *tlv; |
| 122 | |
| 123 | /* BOLT-remove-legacy-onion #4: |
| 124 | * 1. type: `hop_payloads` |
| 125 | * 2. data: |
| 126 | * * [`bigsize`:`length`] |
| 127 | * * [`length*byte`:`payload`] |
| 128 | */ |
| 129 | len = fromwire_bigsize(&cursor, &max); |
| 130 | if (!cursor || len > max) { |
| 131 | *failtlvtype = 0; |
| 132 | *failtlvpos = tal_bytelen(rs->raw_payload); |
| 133 | goto fail_no_tlv; |
| 134 | } |
| 135 | |
| 136 | /* We do this manually so we can accept extra types, and get |
| 137 | * error off and type. */ |
| 138 | tlv = tlv_tlv_payload_new(p); |
| 139 | if (!fromwire_tlv(&cursor, &max, tlvs_tlv_tlv_payload, |
| 140 | TLVS_ARRAY_SIZE_tlv_tlv_payload, |
| 141 | tlv, &tlv->fields, accepted_extra_tlvs, |
| 142 | failtlvpos, failtlvtype)) { |
| 143 | goto fail; |
| 144 | } |
| 145 | |
| 146 | /* BOLT #4: |
| 147 | * |
| 148 | * The reader: |
| 149 | * - MUST return an error if `amt_to_forward` or |
| 150 | * `outgoing_cltv_value` are not present. |
| 151 | */ |
| 152 | if (!tlv->amt_to_forward) { |
| 153 | *failtlvtype = TLV_TLV_PAYLOAD_AMT_TO_FORWARD; |
| 154 | goto field_bad; |
| 155 | } |
| 156 | if (!tlv->outgoing_cltv_value) { |
| 157 | *failtlvtype = TLV_TLV_PAYLOAD_OUTGOING_CLTV_VALUE; |
| 158 | goto field_bad; |
| 159 | } |
| 160 | |
| 161 | p->amt_to_forward = amount_msat(*tlv->amt_to_forward); |
| 162 | p->outgoing_cltv = *tlv->outgoing_cltv_value; |
| 163 | |
| 164 | /* BOLT #4: |
| 165 | * |
| 166 | * The writer: |
| 167 | *... |
no test coverage detected