github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/script/taproot_test.go (about)

     1  package script
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"encoding/hex"
     7  	"encoding/json"
     8  	"fmt"
     9  	"github.com/piotrnar/gocoin/lib/btc"
    10  	"io/ioutil"
    11  	"testing"
    12  )
    13  
    14  type one_scr_tst struct {
    15  	Tx       string   `json:"tx"`
    16  	Prevouts []string `json:"prevouts"`
    17  	Index    int      `json:"index"`
    18  	Success  struct {
    19  		ScriptSig string   `json:"scriptSig"`
    20  		Witness   []string `json:"witness"`
    21  	} `json:"success"`
    22  	Failure struct {
    23  		ScriptSig string   `json:"scriptSig"`
    24  		Witness   []string `json:"witness"`
    25  	} `json:"failure"`
    26  	Flags   string `json:"flags"`
    27  	Final   bool   `json:"final"`
    28  	Comment string `json:"comment"`
    29  }
    30  
    31  func dump_test(tst *one_scr_tst) {
    32  	b, er := json.MarshalIndent(tst, "", "  ")
    33  	if er == nil {
    34  		fmt.Println(string(b))
    35  	}
    36  }
    37  
    38  func TestTaprootScritps(t *testing.T) {
    39  	var tests []one_scr_tst
    40  	var res bool
    41  
    42  	DBG_ERR = false
    43  	dat, er := ioutil.ReadFile("../test/bip341_script_tests.json")
    44  	if er != nil {
    45  		t.Error(er.Error())
    46  		return
    47  	}
    48  	er = json.Unmarshal(dat, &tests)
    49  	if er != nil {
    50  		t.Error(er.Error())
    51  		return
    52  	}
    53  	for i := 0; i < len(tests); i++ {
    54  		//println("+++++++++++++", i, "+++++++++++++++")
    55  		tv := tests[i]
    56  
    57  		d, e := hex.DecodeString(tv.Tx)
    58  		if e != nil {
    59  			t.Fatal(i, e.Error())
    60  		}
    61  		tx, off := btc.NewTx(d)
    62  		if tx == nil {
    63  			t.Fatal(i, "Tx decode error", off, tv.Tx)
    64  		}
    65  		if off != len(d) {
    66  			t.Fatal(i, "Tx not fully decoded", off, len(d), tv.Tx)
    67  		}
    68  
    69  		tx.Spent_outputs = make([]*btc.TxOut, len(tv.Prevouts))
    70  
    71  		/*
    72  		_b := new(bytes.Buffer)
    73  		btc.WriteVlen(_b, uint64(len(tv.Prevouts)))
    74  		outs := _b.Bytes()
    75  		*/
    76  
    77  		for i, pks := range tv.Prevouts {
    78  			d, e = hex.DecodeString(pks)
    79  			if e != nil {
    80  				t.Fatal(i, e.Error())
    81  			}
    82  			tx.Spent_outputs[i] = new(btc.TxOut)
    83  			rd := bytes.NewReader(d)
    84  			e = binary.Read(rd, binary.LittleEndian, &tx.Spent_outputs[i].Value)
    85  			if e != nil {
    86  				t.Fatal(i, e.Error())
    87  			}
    88  			le, e := btc.ReadVLen(rd)
    89  			if e != nil {
    90  				t.Fatal(i, e.Error())
    91  			}
    92  			tx.Spent_outputs[i].Pk_script = make([]byte, int(le))
    93  			_, e = rd.Read(tx.Spent_outputs[i].Pk_script)
    94  			if e != nil {
    95  				t.Fatal(i, e.Error())
    96  			}
    97  			//outs = append(outs, txout_serialize(tx.Spent_outputs[i])...)
    98  		}
    99  
   100  		idx := tv.Index
   101  		if tv.Success.ScriptSig != "" {
   102  			if d, er = hex.DecodeString(tv.Success.ScriptSig); er != nil {
   103  				t.Fatal(i, e.Error())
   104  			}
   105  			tx.TxIn[idx].ScriptSig = d
   106  		}
   107  		if len(tv.Success.Witness) > 0 {
   108  			tx.SegWit = make([][][]byte, len(tx.TxIn))
   109  			tx.SegWit[idx] = make([][]byte, len(tv.Success.Witness))
   110  			for i := range tv.Success.Witness {
   111  				tx.SegWit[idx][i], e = hex.DecodeString(tv.Success.Witness[i])
   112  				//println("wit", idx, i, hex.EncodeToString(tx.SegWit[idx][i]))
   113  				if er != nil {
   114  					t.Fatal(i, e.Error())
   115  				}
   116  			}
   117  		}
   118  		flags, er := decode_flags(tv.Flags)
   119  		if er != nil {
   120  			t.Fatal(i, er.Error())
   121  		}
   122  
   123  		//DBG_ERR = true
   124  		res = VerifyTxScript(tx.Spent_outputs[idx].Pk_script, &SigChecker{Tx: tx, Idx: idx, Amount: tx.Spent_outputs[idx].Value}, flags)
   125  
   126  		if false {
   127  			hasz := tx.TaprootSigHash(&btc.ScriptExecutionData{
   128  				M_tapleaf_hash:      btc.NewUint256FromString("b45b31b6d43e11c6e3c38b09942a7e6d8178eaa97965f387b0872b5857c6768d").Hash[:],
   129  				M_codeseparator_pos: 0xffffffff}, idx, 2, false)
   130  
   131  			println("hasz:", btc.NewUint256(hasz).String())
   132  			break
   133  		}
   134  
   135  		if !res {
   136  			//dump_test(&tv)
   137  			t.Fatal(i, "Verify Failed for", tv.Comment)
   138  		}
   139  
   140  		if tv.Failure.ScriptSig != "" || len(tv.Failure.Witness) > 0 {
   141  			if tv.Failure.ScriptSig != "" {
   142  				if d, er = hex.DecodeString(tv.Failure.ScriptSig); er != nil {
   143  					t.Fatal(i, e.Error())
   144  				}
   145  				tx.TxIn[idx].ScriptSig = d
   146  			}
   147  			if len(tv.Failure.Witness) > 0 {
   148  				tx.SegWit = make([][][]byte, len(tx.TxIn))
   149  				tx.SegWit[idx] = make([][]byte, len(tv.Failure.Witness))
   150  				for i := range tv.Failure.Witness {
   151  					tx.SegWit[idx][i], e = hex.DecodeString(tv.Failure.Witness[i])
   152  					if er != nil {
   153  						t.Fatal(i, e.Error())
   154  					}
   155  				}
   156  			}
   157  
   158  			res = VerifyTxScript(tx.Spent_outputs[idx].Pk_script, &SigChecker{Tx: tx, Idx: idx, Amount: tx.Spent_outputs[idx].Value}, flags)
   159  
   160  			if res {
   161  				dump_test(&tv)
   162  				t.Fatal(i, "Verify not Failed but should")
   163  			}
   164  		}
   165  
   166  		//break
   167  	}
   168  	//println("counters:", btc.EcdsaVerifyCnt(), btc.SchnorrVerifyCnt(), btc.CheckPay2ContractCnt())
   169  }