UNPKG

wowok

Version:

Wowok Blockchain TypeScript API

1 lines 5.45 kB
import{fromBase64,toBase64}from'../_deps/bcs/index.js';import{blake2b}from'@noble/hashes/blake2b';import{bytesToHex}from'@noble/hashes/utils';import{bcs}from'../bcs/index.js';import{bytesEqual,PublicKey}from'../cryptography/publickey.js';import{SIGNATURE_FLAG_TO_SCHEME,SIGNATURE_SCHEME_TO_FLAG}from'../cryptography/signature-scheme.js';import{parseSerializedSignature}from'../cryptography/signature.js';import{normalizeWowAddress}from'../utils/wow-types.js';import{publicKeyFromRawBytes}from'../verify/index.js';import{MultiSigSigner}from'./signer.js';export const MAX_SIGNER_IN_MULTISIG=0xa;export const MIN_SIGNER_IN_MULTISIG=0x1;export class MultiSigPublicKey extends PublicKey{['rawBytes'];['multisigPublicKey'];['publicKeys'];constructor(a){super();if(typeof a==='string')this['rawBytes']=fromBase64(a),this['multisigPublicKey']=bcs['MultiSigPublicKey']['parse'](this['rawBytes']);else a instanceof Uint8Array?(this['rawBytes']=a,this['multisigPublicKey']=bcs['MultiSigPublicKey']['parse'](this['rawBytes'])):(this['multisigPublicKey']=a,this['rawBytes']=bcs['MultiSigPublicKey']['serialize'](a)['toBytes']());if(this['multisigPublicKey']['threshold']<0x1)throw new Error('Invalid\x20threshold');const b=new Set();this['publicKeys']=this['multisigPublicKey']['pk_map']['map'](({pubKey:d,weight:e})=>{const [f,g]=Object['entries'](d)['filter'](([i])=>i!=='$kind')[0x0],h=Uint8Array['from'](g)['toString']();if(b['has'](h))throw new Error('Multisig\x20does\x20not\x20support\x20duplicate\x20public\x20keys');b['add'](h);if(e<0x1)throw new Error('Invalid\x20weight');return{'publicKey':publicKeyFromRawBytes(f,Uint8Array['from'](g)),'weight':e};});const c=this['publicKeys']['reduce']((d,{weight:e})=>d+e,0x0);if(this['multisigPublicKey']['threshold']>c)throw new Error('Unreachable\x20threshold');if(this['publicKeys']['length']>MAX_SIGNER_IN_MULTISIG)throw new Error('Max\x20number\x20of\x20signers\x20in\x20a\x20multisig\x20is\x20'+MAX_SIGNER_IN_MULTISIG);if(this['publicKeys']['length']<MIN_SIGNER_IN_MULTISIG)throw new Error('Min\x20number\x20of\x20signers\x20in\x20a\x20multisig\x20is\x20'+MIN_SIGNER_IN_MULTISIG);}static['fromPublicKeys']({threshold:a,publicKeys:b}){return new MultiSigPublicKey({'pk_map':b['map'](({publicKey:c,weight:d})=>{const e=SIGNATURE_FLAG_TO_SCHEME[c['flag']()];return{'pubKey':{[e]:c['toRawBytes']()},'weight':d};}),'threshold':a});}['equals'](a){return super['equals'](a);}['toRawBytes'](){return this['rawBytes'];}['getPublicKeys'](){return this['publicKeys'];}['getThreshold'](){return this['multisigPublicKey']['threshold'];}['getSigner'](...a){return new MultiSigSigner(this,a);}['toWAddress'](){const a=0x1+(0x40+0x1)*MAX_SIGNER_IN_MULTISIG+0x2,b=new Uint8Array(a);b['set']([SIGNATURE_SCHEME_TO_FLAG['MultiSig']]),b['set'](bcs['u16']()['serialize'](this['multisigPublicKey']['threshold'])['toBytes'](),0x1);let c=0x3;for(const {publicKey:d,weight:e}of this['publicKeys']){const f=d['toWBytes']();b['set'](f,c),c+=f['length'],b['set']([e],c++);}return normalizeWowAddress(bytesToHex(blake2b(b['slice'](0x0,c),{'dkLen':0x20})));}['flag'](){return SIGNATURE_SCHEME_TO_FLAG['MultiSig'];}async['verify'](a,b){const c=parseSerializedSignature(b);if(c['signatureScheme']!=='MultiSig')throw new Error('Invalid\x20signature\x20scheme');const {multisig:d}=c;let e=0x0;if(!bytesEqual(bcs['MultiSigPublicKey']['serialize'](this['multisigPublicKey'])['toBytes'](),bcs['MultiSigPublicKey']['serialize'](d['multisig_pk'])['toBytes']()))return![];for(const {publicKey:f,weight:g,signature:h}of parsePartialSignatures(d)){if(!await f['verify'](a,h))return![];e+=g;}return e>=this['multisigPublicKey']['threshold'];}['combinePartialSignatures'](a){if(a['length']>MAX_SIGNER_IN_MULTISIG)throw new Error('Max\x20number\x20of\x20signatures\x20in\x20a\x20multisig\x20is\x20'+MAX_SIGNER_IN_MULTISIG);let b=0x0;const c=new Array(a['length']);for(let g=0x0;g<a['length'];g++){const h=parseSerializedSignature(a[g]);if(h['signatureScheme']==='MultiSig')throw new Error('MultiSig\x20is\x20not\x20supported\x20inside\x20MultiSig');const k=h['publicKey'];c[g]={[h['signatureScheme']]:h['signature']};let l;for(let m=0x0;m<this['publicKeys']['length'];m++){if(bytesEqual(k,this['publicKeys'][m]['publicKey']['toRawBytes']())){if(b&0x1<<m)throw new Error('Received\x20multiple\x20signatures\x20from\x20the\x20same\x20public\x20key');l=m;break;}}if(l===undefined)throw new Error('Received\x20signature\x20from\x20unknown\x20public\x20key');b|=0x1<<l;}const d={'sigs':c,'bitmap':b,'multisig_pk':this['multisigPublicKey']},e=bcs['MultiSig']['serialize'](d,{'maxSize':0x2000})['toBytes'](),f=new Uint8Array(e['length']+0x1);return f['set']([SIGNATURE_SCHEME_TO_FLAG['MultiSig']]),f['set'](e,0x1),toBase64(f);}}export function parsePartialSignatures(a){const b=new Array(a['sigs']['length']);for(let c=0x0;c<a['sigs']['length'];c++){const [d,e]=Object['entries'](a['sigs'][c])['filter'](([l])=>l!=='$kind')[0x0],f=asIndices(a['bitmap']),g=f[c],h=a['multisig_pk']['pk_map'][g],j=Uint8Array['from'](Object['values'](h['pubKey'])[0x0]);if(d==='MultiSig')throw new Error('MultiSig\x20is\x20not\x20supported\x20inside\x20MultiSig');const k=publicKeyFromRawBytes(d,j);b[c]={'signatureScheme':d,'signature':Uint8Array['from'](e),'publicKey':k,'weight':h['weight']};}return b;}function asIndices(a){if(a<0x0||a>0x400)throw new Error('Invalid\x20bitmap');const b=[];for(let c=0x0;c<0xa;c++){(a&0x1<<c)!==0x0&&b['push'](c);}return Uint8Array['from'](b);}