import { Data , Quantity , keccak , BUFFER_EMPTY , uintToBuffer } from "@ganache/utils" ; import { EIP1559FeeMarketDatabaseTx , EIP2930AccessListDatabaseTx , LegacyDatabasePayload } from "./raw" ; import { digest , encodeRange } from "@ganache/rlp" ; import { Address } from "@ganache/ethereum-address" ; import secp256k1 from "@ganache/secp256k1" ; const intToBuffer = ( value ) => value === 0 ? BUFFER_EMPTY : uintToBuffer ( value ) ; param source param target param targetStart param length function copyOrFill ( source , target , targetStart , length ) { if ( source . byteLength > length ) throw new Error ( "Invalid signature" ) ; const numZeroes = length - source . byteLength ; const endZeroes = targetStart + numZeroes ; let i = targetStart ; for ( ; i < endZeroes ; i ++ ) { target [ i ] = 0 ; } let end = targetStart + length ; const sourceOffset = targetStart + numZeroes ; for ( ; i < end ; i ++ ) { target [ i ] = source [ i - sourceOffset ] ; } } export const isValidSigRecovery = ( recovery ) => { return recovery === 1 || recovery === 0 ; } ; param sharedBuffer param r param s param msgHash param recovery export const ecdsaRecover = ( partialRlp , sharedBuffer , v , chainId , rBuf , sBuf ) => { let data ; let recid ; const eip155V = chainId * 2 + 35 ; const isEip155 = v === eip155V || v === eip155V + 1 ; if ( isEip155 ) { const chainBuf = intToBuffer ( chainId ) ; const extras = [ chainBuf , BUFFER_EMPTY , BUFFER_EMPTY ] as const ; const epilogue = encodeRange ( extras , 0 , 3 ) ; data = digest ( [ partialRlp . output , epilogue . output ] , partialRlp . length + epilogue . length ) ; recid = v - eip155V ; } else { data = digest ( [ partialRlp . output ] , partialRlp . length ) ; recid = v - 27 ; } return _ecdsaRecover ( data , sharedBuffer , rBuf , sBuf , recid ) ; } ; function _ecdsaRecover ( data , sharedBuffer , rBuf , sBuf , recid ) { if ( ! isValidSigRecovery ( recid ) ) { throw new Error ( "Invalid signature v value" ) ; } const message = keccak ( data ) ; const signature = sharedBuffer . slice ( 0 , 64 ) ; copyOrFill ( rBuf , signature , 0 , 32 ) ; copyOrFill ( sBuf , signature , 32 , 32 ) ; const output = sharedBuffer . slice ( 0 , 33 ) ; const success = secp256k1 . ecdsaRecover ( output , signature , recid , message ) ; if ( success !== 0 ) { throw new Error ( "Invalid Signature" ) ; } return output ; } param sharedBuffer param senderPubKey export const publicKeyConvert = ( sharedBuffer , senderPubKey ) => { const publicKey = sharedBuffer . slice ( 0 , 65 ) ; const result = secp256k1 . publicKeyConvert ( publicKey , senderPubKey ) ; if ( result !== 0 ) { throw new Error ( "Invalid Signature" ) ; } return publicKey ; } ; /**
 * A Buffer that can be reused by `computeFromAddress`.
 */ const SHARED_BUFFER = Buffer . allocUnsafe ( 65 ) ; export const computeFromAddress = ( partialRlp , v , rBuf , sBuf , chainId ) => { const senderPubKey = ecdsaRecover ( partialRlp , SHARED_BUFFER , v , chainId , rBuf , sBuf ) ; const publicKey = publicKeyConvert ( SHARED_BUFFER , senderPubKey ) ; return Address . from ( keccak ( publicKey . slice ( 1 ) ) . slice ( - 20 ) ) ; } ; export const computeIntrinsicsLegacyTx = ( v , raw , chainId ) => { const encodedData = encodeRange ( raw , 0 , 6 ) ; const encodedSignature = encodeRange ( raw , 6 , 3 ) ; const serialized = digest ( [ encodedData . output , encodedSignature . output ] , encodedData . length + encodedSignature . length ) ; return { from : computeFromAddress ( encodedData , v . toNumber ( ) , raw [ 7 ] , raw [ 8 ] , chainId ) , hash : Data . from ( keccak ( serialized ) , 32 ) , serialized , encodedData , encodedSignature } ; } ; export const computeIntrinsicsAccessListTx = ( v , raw ) => { const typeBuf = raw [ 0 ] ; const encodedData = encodeRange ( raw , 1 , 8 ) ; const encodedSignature = encodeRange ( raw , 9 , 3 ) ; const serialized = Buffer . concat ( [ typeBuf , digest ( [ encodedData . output , encodedSignature . output ] , encodedData . length + encodedSignature . length ) ] ) ; const data = Buffer . concat ( [ typeBuf , digest ( [ encodedData . output ] , encodedData . length ) ] ) ; const senderPubKey = _ecdsaRecover ( data , SHARED_BUFFER , raw [ 10 ] , raw [ 11 ] , v . toNumber ( ) ) ; const publicKey = publicKeyConvert ( SHARED_BUFFER , senderPubKey ) ; const from = Address . from ( keccak ( publicKey . slice ( 1 ) ) . slice ( - 20 ) ) ; return { from : from , hash : Data . from ( keccak ( serialized ) , 32 ) , serialized , encodedData , encodedSignature } ; } ; export const computeIntrinsicsFeeMarketTx = ( v , raw ) => { const typeBuf = raw [ 0 ] ; const encodedData = encodeRange ( raw , 1 , 9 ) ; const encodedSignature = encodeRange ( raw , 10 , 3 ) ; const serialized = Buffer . concat ( [ typeBuf , digest ( [ encodedData . output , encodedSignature . output ] , encodedData . length + encodedSignature . length ) ] ) ; const data = Buffer . concat ( [ typeBuf , digest ( [ encodedData . output ] , encodedData . length ) ] ) ; const senderPubKey = _ecdsaRecover ( data , SHARED_BUFFER , raw [ 11 ] , raw [ 12 ] , v . toNumber ( ) ) ; const publicKey = publicKeyConvert ( SHARED_BUFFER , senderPubKey ) ; const from = Address . from ( keccak ( publicKey . slice ( 1 ) ) . slice ( - 20 ) ) ; return { from : from , hash : Data . from ( keccak ( serialized ) , 32 ) , serialized , encodedData , encodedSignature } ; } ;