Decode a length-prefixed Simplicity DAG from 'stream'. * Returns 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' the length prefix's value is too large. * Returns 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' if some node's child isn't a reference to one of the preceding nodes. * Returns 'SIMPLICITY_ERR_FAIL_CODE' if the encoding of a fail expression is encountered * (all fail subexpressions ought to have been prune
| 186 | * NULL == *dag when the return value is negative. |
| 187 | */ |
| 188 | int_fast32_t simplicity_decodeMallocDag(dag_node** dag, simplicity_callback_decodeJet decodeJet, combinator_counters* census, bitstream* stream) { |
| 189 | *dag = NULL; |
| 190 | int32_t dagLen = simplicity_decodeUptoMaxInt(stream); |
| 191 | if (dagLen <= 0) return dagLen; |
| 192 | static_assert(DAG_LEN_MAX <= (uint32_t)INT32_MAX, "DAG_LEN_MAX exceeds supported parsing range."); |
| 193 | if (DAG_LEN_MAX < (uint32_t)dagLen) return SIMPLICITY_ERR_DATA_OUT_OF_RANGE; |
| 194 | static_assert(DAG_LEN_MAX <= SIZE_MAX / sizeof(dag_node), "dag array too large."); |
| 195 | static_assert(1 <= DAG_LEN_MAX, "DAG_LEN_MAX is zero."); |
| 196 | static_assert(DAG_LEN_MAX - 1 <= UINT32_MAX, "dag array index does not fit in uint32_t."); |
| 197 | *dag = simplicity_malloc((size_t)dagLen * sizeof(dag_node)); |
| 198 | if (!*dag) return SIMPLICITY_ERR_MALLOC; |
| 199 | |
| 200 | if (census) *census = (combinator_counters){0}; |
| 201 | simplicity_err error = decodeDag(*dag, decodeJet, (uint_fast32_t)dagLen, census, stream); |
| 202 | |
| 203 | if (IS_OK(error)) { |
| 204 | error = HIDDEN == (*dag)[dagLen - 1].tag |
| 205 | ? SIMPLICITY_ERR_HIDDEN_ROOT |
| 206 | : simplicity_verifyCanonicalOrder(*dag, (uint_fast32_t)(dagLen)); |
| 207 | } |
| 208 | |
| 209 | if (IS_OK(error)) { |
| 210 | return dagLen; |
| 211 | } else { |
| 212 | simplicity_free(*dag); |
| 213 | *dag = NULL; |
| 214 | return (int_fast32_t)error; |
| 215 | } |
| 216 | } |