@secux/app-btc
Version:
SecuX Hardware Wallet BTC API
18 lines (15 loc) • 6.04 kB
JavaScript
;
/*!
Copyright 2022 SecuX Technology Inc
Copyright Chen Wei-En
Copyright Wu Tsung-Yu
Licensed under the Apache License, Version 2.0 (the License);
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an AS IS BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/Object.defineProperty(exports,"__esModule",{value:!0}),exports.taggedHash=exports.toTweakedPublickey=exports.getPublickey=exports.scriptWitnessToWitnessStack=exports.witnessStackToScriptWitness=exports.vectorSize=exports.sliceSize=exports.getDustThreshold=exports.getOutScriptSize=exports.getWitnessSize=exports.getInScriptSize=exports.getSerializer=exports.getDefaultScript=exports.getPurpose=exports.getCoinType=exports.getPayment=void 0;const secp256k1=require("secp256k1/elliptic"),varuint=require("varuint-bitcoin"),interface_1=require("./interface"),payment_1=require("./payment"),payment_bch_1=require("./payment_bch"),payment_grs_1=require("./payment_grs"),transaction_1=require("./transaction"),transaction_grs_1=require("./transaction_grs"),ow_1=require("ow"),hash_js_1=require("hash.js"),bip340_1=require("./bip340");function getCoinType(path){const bip32=path.match(/\d+/g),cointype=parseInt(bip32[1],10);for(let i=0;i<interface_1.coinmap.length;i++)if(cointype===interface_1.coinmap[i].coinType)return i;throw Error(`ArgumentError: unsupport cointype of BIP32 path, got ${path}`)}function getWitnessSize(type,sighashType=transaction_1.Transaction.SIGHASH_DEFAULT){switch(type){case interface_1.ScriptType.P2SH_P2WPKH:case interface_1.ScriptType.P2WPKH:return[72,33];case interface_1.ScriptType.P2TR:return sighashType===transaction_1.Transaction.SIGHASH_DEFAULT?[64]:[65]}return[]}function getOutScriptSize(type){switch(type){case interface_1.ScriptType.P2PKH:return 25;case interface_1.ScriptType.P2SH_P2PKH:case interface_1.ScriptType.P2SH_P2WPKH:return 23;case interface_1.ScriptType.P2WPKH:return 22;case interface_1.ScriptType.P2TR:return 34}return 0}function sliceSize(size){return varuint.encodingLength(size)+size}function getPublickey(data){(0,ow_1.default)(data,ow_1.default.any(interface_1.ow_hexString,ow_1.default.buffer));const pk="string"==typeof data?Buffer.from(data,"hex"):data;if(!secp256k1.publicKeyVerify(pk))throw Error(`ArgumentError: invalid secp256k1 publickey, got "${pk.toString("hex")}"`);return pk}exports.getPayment=function(coin){switch(coin){case interface_1.CoinType.BITCOINCASH:return payment_bch_1.PaymentBCH;case interface_1.CoinType.GROESTL:return payment_grs_1.PaymentGRS;default:return payment_1.PaymentBTC}},exports.getCoinType=getCoinType,exports.getPurpose=function(script){switch(script){case interface_1.ScriptType.P2PKH:return 44;case interface_1.ScriptType.P2SH_P2PKH:case interface_1.ScriptType.P2SH_P2WPKH:return 49;case interface_1.ScriptType.P2WPKH:return 84;case interface_1.ScriptType.P2TR:return 86}throw Error(`ArgumentError: unsupport ScriptType, got ${script}`)},exports.getDefaultScript=function(path){const bip32=path.match(/\d+/g),purpose=parseInt(bip32[0],10),coin=bip32[1]?getCoinType(path):interface_1.CoinType.BITCOIN;switch(purpose){case 44:return interface_1.ScriptType.P2PKH;case 49:return coin!==interface_1.CoinType.BITCOINCASH?interface_1.ScriptType.P2SH_P2WPKH:interface_1.ScriptType.P2SH_P2PKH;case 84:return interface_1.ScriptType.P2WPKH;case 86:return interface_1.ScriptType.P2TR}throw Error(`ArgumentError: unsupport purpose of path, got "${purpose}" from ${path}`)},exports.getSerializer=function(coin){return coin===interface_1.CoinType.GROESTL?transaction_grs_1.TransactionGRS:transaction_1.Transaction},exports.getInScriptSize=function(type){switch(type){case interface_1.ScriptType.P2PKH:case interface_1.ScriptType.P2SH_P2PKH:return 107;case interface_1.ScriptType.P2SH_P2WPKH:return 23}return 0},exports.getWitnessSize=getWitnessSize,exports.getOutScriptSize=getOutScriptSize,exports.getDustThreshold=function(output,dustRelayFee){return(8+varuint.encodingLength(1)+getOutScriptSize(output)+(0!==getWitnessSize(output).length?67:148))*dustRelayFee},exports.sliceSize=sliceSize,exports.vectorSize=function(sizes){return varuint.encodingLength(sizes.length)+sizes.reduce(((sum,size)=>sum+sliceSize(size)),0)},exports.witnessStackToScriptWitness=function(witness){let buffer=Buffer.allocUnsafe(0);const writeVarInt=i=>{const currentLen=buffer.length,varintLen=varuint.encodingLength(i);buffer=Buffer.concat([buffer,Buffer.allocUnsafe(varintLen)]),varuint.encode(i,buffer,currentLen)};writeVarInt(witness.length);for(const w of witness)writeVarInt(w.length),buffer=Buffer.concat([buffer,Buffer.from(w)]);return buffer},exports.scriptWitnessToWitnessStack=function(buffer){let offset=0;const readVarInt=()=>{const vi=varuint.decode(buffer,offset);return offset+=varuint.decode.bytes,vi},readVarSlice=()=>{const n=readVarInt();return offset+=n,buffer.slice(offset-n,offset)},count=readVarInt(),vector=[];for(let i=0;i<count;i++)vector.push(readVarSlice());return vector},exports.getPublickey=getPublickey,exports.toTweakedPublickey=function(data){const XOnlyPubkey=getPublickey(data).slice(1,33),commitHash=taggedHash("TapTweak",XOnlyPubkey);return(0,bip340_1.taprootConvert)(XOnlyPubkey,commitHash)};const TAGGED_HASH_PREFIXES=Object.fromEntries(["BIP0340/challenge","BIP0340/aux","BIP0340/nonce","TapLeaf","TapBranch","TapSighash","TapTweak","KeyAgg list","KeyAgg coefficient"].map((tag=>{const tagHash=function(tag){return Buffer.from((0,hash_js_1.sha256)().update(tag).digest())}(tag);return[tag,Buffer.concat([tagHash,tagHash])]})));function taggedHash(prefix,data){const buf=Buffer.concat([TAGGED_HASH_PREFIXES[prefix],data]);return Buffer.from((0,hash_js_1.sha256)().update(buf).digest())}exports.taggedHash=taggedHash;