Allocate and initialize a 'elementsTapEnv' from a 'rawElementsTapEnv', copying or hashing the data as needed. * Returns NULL if malloc fails (or if malloc cannot be called because we require an allocation larger than SIZE_MAX). * * Precondition: *rawEnv is well-formed (i.e. rawEnv->pathLen <= 128.) */
| 581 | * Precondition: *rawEnv is well-formed (i.e. rawEnv->pathLen <= 128.) |
| 582 | */ |
| 583 | extern elementsTapEnv* simplicity_elements_mallocTapEnv(const rawElementsTapEnv* rawEnv) { |
| 584 | if (!rawEnv) return NULL; |
| 585 | if (128 < rawEnv->pathLen) return NULL; |
| 586 | |
| 587 | size_t allocationSize = sizeof(elementsTapEnv); |
| 588 | |
| 589 | const size_t numMidstate = rawEnv->pathLen; |
| 590 | const size_t pad1 = PADDING(sha256_midstate, allocationSize); |
| 591 | |
| 592 | if (numMidstate) { |
| 593 | if (SIZE_MAX - allocationSize < pad1) return NULL; |
| 594 | allocationSize += pad1; |
| 595 | |
| 596 | if (SIZE_MAX / sizeof(sha256_midstate) < numMidstate) return NULL; |
| 597 | if (SIZE_MAX - allocationSize < numMidstate * sizeof(sha256_midstate)) return NULL; |
| 598 | allocationSize += numMidstate * sizeof(sha256_midstate); |
| 599 | } |
| 600 | |
| 601 | char *allocation = simplicity_malloc(allocationSize); |
| 602 | if (!allocation) return NULL; |
| 603 | |
| 604 | /* Casting through void* to avoid warning about pointer alignment. |
| 605 | * Our padding is done carefully to ensure alignment. |
| 606 | */ |
| 607 | elementsTapEnv* const env = (elementsTapEnv*)(void*)allocation; |
| 608 | sha256_midstate* path = NULL; |
| 609 | sha256_midstate internalKey; |
| 610 | |
| 611 | sha256_toMidstate(internalKey.s, &rawEnv->controlBlock[1]); |
| 612 | |
| 613 | if (numMidstate) { |
| 614 | allocation += sizeof(elementsTapEnv) + pad1; |
| 615 | |
| 616 | if (rawEnv->pathLen) { |
| 617 | path = (sha256_midstate*)(void*)allocation; |
| 618 | } |
| 619 | } |
| 620 | |
| 621 | *env = (elementsTapEnv){ .leafVersion = rawEnv->controlBlock[0] & 0xfe |
| 622 | , .internalKey = internalKey |
| 623 | , .path = path |
| 624 | , .pathLen = rawEnv->pathLen |
| 625 | }; |
| 626 | sha256_toMidstate(env->scriptCMR.s, rawEnv->scriptCMR); |
| 627 | |
| 628 | { |
| 629 | sha256_context ctx = sha256_init(env->tappathHash.s); |
| 630 | for (int i = 0; i < env->pathLen; ++i) { |
| 631 | sha256_toMidstate(path[i].s, &rawEnv->controlBlock[33+32*i]); |
| 632 | sha256_hash(&ctx, &path[i]); |
| 633 | } |
| 634 | sha256_finalize(&ctx); |
| 635 | } |
| 636 | |
| 637 | env->tapLeafHash = simplicity_make_tapleaf(env->leafVersion, &env->scriptCMR); |
| 638 | |
| 639 | { |
| 640 | sha256_context ctx = sha256_init(env->tapEnvHash.s); |