Allocate and initialize a 'bitcoinTapEnv' from a 'rawBitcoinTapEnv', 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.) */
| 188 | * Precondition: *rawEnv is well-formed (i.e. rawEnv->pathLen <= 128.) |
| 189 | */ |
| 190 | extern bitcoinTapEnv* simplicity_bitcoin_mallocTapEnv(const rawBitcoinTapEnv* rawEnv) { |
| 191 | if (!rawEnv) return NULL; |
| 192 | if (128 < rawEnv->pathLen) return NULL; |
| 193 | |
| 194 | size_t allocationSize = sizeof(bitcoinTapEnv); |
| 195 | |
| 196 | const size_t numMidstate = rawEnv->pathLen; |
| 197 | const size_t pad1 = PADDING(sha256_midstate, allocationSize); |
| 198 | |
| 199 | if (numMidstate) { |
| 200 | if (SIZE_MAX - allocationSize < pad1) return NULL; |
| 201 | allocationSize += pad1; |
| 202 | |
| 203 | if (SIZE_MAX / sizeof(sha256_midstate) < numMidstate) return NULL; |
| 204 | if (SIZE_MAX - allocationSize < numMidstate * sizeof(sha256_midstate)) return NULL; |
| 205 | allocationSize += numMidstate * sizeof(sha256_midstate); |
| 206 | } |
| 207 | |
| 208 | char *allocation = simplicity_malloc(allocationSize); |
| 209 | if (!allocation) return NULL; |
| 210 | |
| 211 | /* Casting through void* to avoid warning about pointer alignment. |
| 212 | * Our padding is done carefully to ensure alignment. |
| 213 | */ |
| 214 | bitcoinTapEnv* const env = (bitcoinTapEnv*)(void*)allocation; |
| 215 | sha256_midstate* path = NULL; |
| 216 | sha256_midstate internalKey; |
| 217 | |
| 218 | sha256_toMidstate(internalKey.s, &rawEnv->controlBlock[1]); |
| 219 | |
| 220 | if (numMidstate) { |
| 221 | allocation += sizeof(bitcoinTapEnv) + pad1; |
| 222 | |
| 223 | if (rawEnv->pathLen) { |
| 224 | path = (sha256_midstate*)(void*)allocation; |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | *env = (bitcoinTapEnv){ .leafVersion = rawEnv->controlBlock[0] & 0xfe |
| 229 | , .internalKey = internalKey |
| 230 | , .path = path |
| 231 | , .pathLen = rawEnv->pathLen |
| 232 | }; |
| 233 | sha256_toMidstate(env->scriptCMR.s, rawEnv->scriptCMR); |
| 234 | |
| 235 | { |
| 236 | sha256_context ctx = sha256_init(env->tappathHash.s); |
| 237 | for (int i = 0; i < env->pathLen; ++i) { |
| 238 | sha256_toMidstate(path[i].s, &rawEnv->controlBlock[33+32*i]); |
| 239 | sha256_hash(&ctx, &path[i]); |
| 240 | } |
| 241 | sha256_finalize(&ctx); |
| 242 | } |
| 243 | |
| 244 | env->tapLeafHash = simplicity_bitcoin_make_tapleaf(env->leafVersion, &env->scriptCMR); |
| 245 | |
| 246 | { |
| 247 | sha256_context ctx = sha256_init(env->tapEnvHash.s); |
nothing calls this directly
no test coverage detected