import { bigIntToBitcoinVarInt , flattenBinArray , numberToBinUint32LE , } from '../../../format/format' ; /**
 * A.K.A. `sighash` flags
 */ export enum SigningSerializationFlag { /**
     * A.K.A. `SIGHASH_ALL`
     */ allOutputs = 0x01 , /**
     * A.K.A `SIGHASH_NONE`
     */ noOutputs = 0x02 , /**
     * A.K.A. `SIGHASH_SINGLE`
     */ correspondingOutput = 0x03 , forkId = 0x40 , /**
     * A.K.A `ANYONE_CAN_PAY`
     */ singleInput = 0x80 } const enum Internal { mask5Bits = 0b11111 , sha256HashByteLength = 32 } export const isDefinedSigningSerializationType = ( byte ) => { const baseType = byte & ~ ( SigningSerializationFlag . forkId | SigningSerializationFlag . singleInput ) ; return ( baseType >= SigningSerializationFlag . allOutputs && baseType <= SigningSerializationFlag . correspondingOutput ) ; } ; const match = ( type , flag ) => ( type [ 0 ] & flag ) !== 0 ; const equals = ( type , flag ) => ( type [ 0 ] & Internal . mask5Bits ) === flag ; const shouldSerializeSingleInput = ( type ) => match ( type , SigningSerializationFlag . singleInput ) ; const shouldSerializeCorrespondingOutput = ( type ) => equals ( type , SigningSerializationFlag . correspondingOutput ) ; const shouldSerializeNoOutputs = ( type ) => equals ( type , SigningSerializationFlag . noOutputs ) ; const emptyHash = ( ) => new Uint8Array ( Internal . sha256HashByteLength ) . fill ( 0 ) ; param signingSerializationType param transactionOutpoints export const hashPrevouts = ( { sha256 , signingSerializationType , transactionOutpoints , } ) => shouldSerializeSingleInput ( signingSerializationType ) ? emptyHash ( ) : sha256 . hash ( sha256 . hash ( transactionOutpoints ) ) ; param signingSerializationType param transactionSequenceNumbers export const hashSequence = ( { sha256 , signingSerializationType , transactionSequenceNumbers , } ) => ! shouldSerializeSingleInput ( signingSerializationType ) && ! shouldSerializeCorrespondingOutput ( signingSerializationType ) && ! shouldSerializeNoOutputs ( signingSerializationType ) ? sha256 . hash ( sha256 . hash ( transactionSequenceNumbers ) ) : emptyHash ( ) ; param signingSerializationType param transactionOutputs param correspondingOutput export const hashOutputs = ( { correspondingOutput , sha256 , signingSerializationType , transactionOutputs , } ) => ! shouldSerializeCorrespondingOutput ( signingSerializationType ) && ! shouldSerializeNoOutputs ( signingSerializationType ) ? sha256 . hash ( sha256 . hash ( transactionOutputs ) ) : shouldSerializeCorrespondingOutput ( signingSerializationType ) ? correspondingOutput === undefined ? emptyHash ( ) : sha256 . hash ( sha256 . hash ( correspondingOutput ) ) : emptyHash ( ) ; /**
 * Serialize the signature-protected properties of a transaction following the
 * algorithm required by the `signingSerializationType` of a signature.
 *
 * Note: this implementation re-computes all hashes each time it is called. A
 * performance-critical application could instead use memoization to avoid
 * re-computing these values when validating many signatures within a single
 * transaction. See BIP143 for details.
 */ export const generateSigningSerializationBCH = ( { correspondingOutput , coveredBytecode , forkId = new Uint8Array ( [ 0 , 0 , 0 ] ) , locktime , outpointIndex , outpointTransactionHash , outputValue , sequenceNumber , sha256 , signingSerializationType , transactionOutpoints , transactionOutputs , transactionSequenceNumbers , version , } ) => flattenBinArray ( [ numberToBinUint32LE ( version ) , hashPrevouts ( { sha256 , signingSerializationType , transactionOutpoints } ) , hashSequence ( { sha256 , signingSerializationType , transactionSequenceNumbers , } ) , outpointTransactionHash . slice ( ) . reverse ( ) , numberToBinUint32LE ( outpointIndex ) , bigIntToBitcoinVarInt ( BigInt ( coveredBytecode . length ) ) , coveredBytecode , outputValue , numberToBinUint32LE ( sequenceNumber ) , hashOutputs ( { correspondingOutput , sha256 , signingSerializationType , transactionOutputs , } ) , numberToBinUint32LE ( locktime ) , signingSerializationType , forkId , ] ) ; param signingSerializationType export const isLegacySigningSerialization = ( signingSerializationType ) => { const forkValue = signingSerializationType >> 8 ; const newForkValue = ( forkValue ^ 0xdead ) | 0xff0000 ; const sighashType = ( newForkValue << 8 ) | ( signingSerializationType & 0xff ) ; return ( sighashType & SigningSerializationFlag . forkId ) === 0 ; } ;