@@ -9,8 +9,10 @@ import {
9
9
isNullInput ,
10
10
readOutput ,
11
11
TxOutput ,
12
+ Psbt ,
12
13
} from '@scrypt-inc/bitcoinjs-lib' ;
13
14
import * as tools from 'uint8array-tools' ;
15
+ import * as varuint from 'varuint-bitcoin' ;
14
16
import script_tests from './fixtures/scripts/script_tests.json' ;
15
17
import script_asset_tests from './fixtures/scripts/script_assets_test.json' ;
16
18
import tx_valid from './fixtures/scripts/tx_valid.json' ;
@@ -19,6 +21,10 @@ import { initEccLib } from '@scrypt-inc/bitcoinjs-lib';
19
21
import * as ecc from 'tiny-secp256k1' ;
20
22
import sinon from 'sinon' ;
21
23
24
+ import * as fs from 'fs' ;
25
+ import { join } from 'path' ;
26
+ import { cwd } from 'process' ;
27
+
22
28
initEccLib ( ecc ) ;
23
29
24
30
//the script string format used in bitcoind data tests
@@ -640,4 +646,76 @@ describe('Interpreter', () => {
640
646
641
647
testAllFixtures ( script_asset_tests as Array < any > ) ;
642
648
} ) ;
649
+
650
+ describe ( 'psbt tests' , function ( ) {
651
+ const psbtBase64 = fs
652
+ . readFileSync ( join ( cwd ( ) , 'test' , 'fixtures' , 'psbt' , '0.txt' ) )
653
+ . toString ( ) ;
654
+
655
+ const psbt = Psbt . fromBase64 ( psbtBase64 ) ;
656
+
657
+ assert . strictEqual ( bvmVerify ( psbt , 0 ) , true ) ;
658
+ assert . strictEqual ( bvmVerify ( psbt , 1 ) , true ) ;
659
+ } ) ;
643
660
} ) ;
661
+
662
+ function bvmVerify ( extPsbt : Psbt , inputIndex : number = 0 ) : true | string {
663
+ const prevOuts = extPsbt . data . inputs . map ( input => input . witnessUtxo ! ) ;
664
+
665
+ const interp = new Interpreter ( ) ;
666
+ const prevScript = prevOuts [ inputIndex ] . script ;
667
+ const prevSatoshi = Number ( prevOuts [ inputIndex ] . value ) ;
668
+
669
+ const finalScriptWitness =
670
+ extPsbt . data . inputs [ inputIndex ] . finalScriptWitness || Uint8Array . from ( [ ] ) ;
671
+
672
+ const witness : Uint8Array [ ] = scriptWitnessToWitnessStack ( finalScriptWitness ) ;
673
+
674
+ const flags =
675
+ Interpreter . SCRIPT_VERIFY_TAPROOT |
676
+ Interpreter . SCRIPT_VERIFY_WITNESS |
677
+ Interpreter . SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
678
+ Interpreter . SCRIPT_VERIFY_CHECKSEQUENCEVERIFY ;
679
+ const ret = interp . verify (
680
+ new Uint8Array ( 0 ) ,
681
+ prevScript ,
682
+ extPsbt . extractTransaction ( ) ,
683
+ inputIndex ,
684
+ flags ,
685
+ witness ,
686
+ prevSatoshi ,
687
+ prevOuts ,
688
+ ) ;
689
+ if ( ! ret ) {
690
+ return interp . getErr ( ) ;
691
+ }
692
+
693
+ return true ;
694
+ }
695
+
696
+ function scriptWitnessToWitnessStack ( scriptWitness : Uint8Array ) {
697
+ const witness : Uint8Array [ ] = [ ] ;
698
+ function readSlice ( buffer : Uint8Array , offset : number , len : number ) {
699
+ return buffer . slice ( offset , offset + len ) ;
700
+ }
701
+ function readVarInt ( buffer : Uint8Array , offset : number ) {
702
+ return varuint . decode ( buffer , offset ) ;
703
+ }
704
+ function readVarSlice ( buffer : Uint8Array , offset : number ) {
705
+ const { numberValue, bytes } = readVarInt ( buffer , offset ) ;
706
+ const slice = readSlice ( buffer , offset + bytes , numberValue ! ) ;
707
+ return { slice, bytes : bytes + numberValue ! } ;
708
+ }
709
+
710
+ let offset = 0 ;
711
+ const { numberValue, bytes } = readVarInt ( scriptWitness , offset ) ;
712
+
713
+ offset += bytes ;
714
+ for ( let i = 0 ; i < numberValue ! ; i ++ ) {
715
+ const { slice, bytes } = readVarSlice ( scriptWitness , offset ) ;
716
+ witness . push ( slice ) ;
717
+ offset += bytes ;
718
+ }
719
+
720
+ return witness ;
721
+ }
0 commit comments