github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/script/script_test.go (about) 1 package script 2 3 import ( 4 //"os" 5 //"fmt" 6 "encoding/hex" 7 "encoding/json" 8 "errors" 9 "io/ioutil" 10 "strings" 11 "testing" 12 13 "github.com/piotrnar/gocoin/lib/btc" 14 ) 15 16 type one_test_vector struct { 17 sigscr, pkscr []byte 18 flags uint32 19 exp_res bool 20 desc string 21 22 witness [][]byte 23 value uint64 24 } 25 26 func TestScritps(t *testing.T) { 27 var str interface{} 28 var vecs []*one_test_vector 29 30 DBG_ERR = false 31 dat, er := ioutil.ReadFile("../test/script_tests.json") 32 if er != nil { 33 t.Error(er.Error()) 34 return 35 } 36 er = json.Unmarshal(dat, &str) 37 if er != nil { 38 t.Error(er.Error()) 39 return 40 } 41 42 m := str.([]interface{}) 43 for i := range m { 44 switch mm := m[i].(type) { 45 case []interface{}: 46 if len(mm) < 4 { 47 continue 48 } 49 50 var skip bool 51 var bfield int 52 var e error 53 var all_good bool 54 55 vec := new(one_test_vector) 56 for ii := range mm { 57 switch segwitdata := mm[ii].(type) { 58 case []interface{}: 59 for iii := range segwitdata { 60 switch segwitdata[iii].(type) { 61 case string: 62 var by []byte 63 s := segwitdata[iii].(string) 64 by, e = hex.DecodeString(s) 65 if e != nil { 66 t.Error("error parsing serwit script", s) 67 skip = true 68 break 69 } 70 vec.witness = append(vec.witness, by) 71 72 case float64: 73 vec.value = uint64(1e8 * segwitdata[iii].(float64)) 74 } 75 } 76 77 case string: 78 s := mm[ii].(string) 79 if bfield == 0 { 80 vec.sigscr, e = btc.DecodeScript(s) 81 if e != nil { 82 t.Error("error parsing script", s) 83 skip = true 84 break 85 } 86 } else if bfield == 1 { 87 vec.pkscr, e = btc.DecodeScript(s) 88 if e != nil { 89 skip = true 90 break 91 } 92 } else if bfield == 2 { 93 vec.flags, e = decode_flags(s) 94 if e != nil { 95 println("error parsing flag", e.Error()) 96 skip = true 97 break 98 } 99 } else if bfield == 3 { 100 vec.exp_res = s == "OK" 101 all_good = true 102 } else if bfield == 4 { 103 vec.desc = s 104 skip = true 105 break 106 } 107 bfield++ 108 109 default: 110 panic("Unexpected test vector") 111 } 112 if skip { 113 break 114 } 115 } 116 if all_good { 117 vecs = append(vecs, vec) 118 } 119 } 120 } 121 122 tot := 0 123 for _, v := range vecs { 124 tot++ 125 126 /* 127 if tot==114400 { 128 DBG_SCR = true 129 DBG_ERR = true 130 }*/ 131 132 flags := v.flags 133 if (flags & VER_CLEANSTACK) != 0 { 134 flags |= VER_P2SH 135 flags |= VER_WITNESS 136 } 137 138 credit_tx := mk_credit_tx(v.pkscr, v.value) 139 spend_tx := mk_spend_tx(credit_tx, v.sigscr, v.witness) 140 spend_tx.Raw = spend_tx.SerializeNew() 141 142 if DBG_SCR { 143 println("desc:", v, tot, v.desc) 144 println("pkscr:", hex.EncodeToString(v.pkscr)) 145 println("sigscr:", hex.EncodeToString(v.sigscr)) 146 println("credit:", hex.EncodeToString(credit_tx.Serialize())) 147 println("spend:", hex.EncodeToString(spend_tx.Serialize())) 148 println("------------------------------ testing vector", tot, len(v.witness), v.value) 149 } 150 res := VerifyTxScript(v.pkscr, &SigChecker{Amount: v.value, Idx: 0, Tx: spend_tx}, flags) 151 152 if res != v.exp_res { 153 t.Error(tot, "TestScritps failed. Got:", res, " exp:", v.exp_res, v.desc) 154 return 155 } else { 156 if DBG_SCR { 157 println(tot, "ok:", res, v.desc) 158 } 159 } 160 161 if tot == 114400 { 162 return 163 } 164 } 165 } 166 167 func decode_flags(s string) (fl uint32, e error) { 168 ss := strings.Split(s, ",") 169 for i := range ss { 170 switch ss[i] { 171 case "": // ignore 172 case "NONE": // ignore 173 break 174 case "P2SH": 175 fl |= VER_P2SH 176 case "STRICTENC": 177 fl |= VER_STRICTENC 178 case "DERSIG": 179 fl |= VER_DERSIG 180 case "LOW_S": 181 fl |= VER_LOW_S 182 case "NULLDUMMY": 183 fl |= VER_NULLDUMMY 184 case "SIGPUSHONLY": 185 fl |= VER_SIGPUSHONLY 186 case "MINIMALDATA": 187 fl |= VER_MINDATA 188 case "DISCOURAGE_UPGRADABLE_NOPS": 189 fl |= VER_BLOCK_OPS 190 case "CLEANSTACK": 191 fl |= VER_CLEANSTACK 192 case "CHECKLOCKTIMEVERIFY": 193 fl |= VER_CLTV 194 case "CHECKSEQUENCEVERIFY": 195 fl |= VER_CSV 196 case "WITNESS": 197 fl |= VER_WITNESS 198 case "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM": 199 fl |= VER_WITNESS_PROG 200 case "MINIMALIF": 201 fl |= VER_MINIMALIF 202 case "NULLFAIL": 203 fl |= VER_NULLFAIL 204 case "WITNESS_PUBKEYTYPE": 205 fl |= VER_WITNESS_PUBKEY 206 case "CONST_SCRIPTCODE": 207 fl |= VER_CONST_SCRIPTCODE 208 case "TAPROOT": 209 fl |= VER_TAPROOT 210 default: 211 e = errors.New("Unsupported flag " + ss[i]) 212 return 213 } 214 } 215 return 216 } 217 218 func mk_credit_tx(pk_scr []byte, value uint64) (input_tx *btc.Tx) { 219 // We build input_tx only to calculate it's hash for output_tx 220 input_tx = new(btc.Tx) 221 input_tx.Version = 1 222 input_tx.TxIn = []*btc.TxIn{{Input: btc.TxPrevOut{Vout: 0xffffffff}, 223 ScriptSig: []byte{0, 0}, Sequence: 0xffffffff}} 224 input_tx.TxOut = []*btc.TxOut{{Pk_script: pk_scr, Value: value}} 225 // Lock_time = 0 226 input_tx.SetHash(input_tx.Serialize()) 227 return 228 } 229 230 func mk_spend_tx(input_tx *btc.Tx, sig_scr []byte, witness [][]byte) (output_tx *btc.Tx) { 231 output_tx = new(btc.Tx) 232 output_tx.Version = 1 233 output_tx.TxIn = []*btc.TxIn{{Input: btc.TxPrevOut{Hash: btc.Sha2Sum(input_tx.Serialize()), Vout: 0}, 234 ScriptSig: sig_scr, Sequence: 0xffffffff}} 235 output_tx.TxOut = []*btc.TxOut{{Value: input_tx.TxOut[0].Value}} 236 // Lock_time = 0 237 238 if len(witness) > 0 { 239 output_tx.SegWit = make([][][]byte, 1) 240 output_tx.SegWit[0] = witness 241 if DBG_SCR { 242 println("tx has", len(witness), "ws") 243 for xx := range witness { 244 println("", xx, hex.EncodeToString(witness[xx])) 245 } 246 } 247 } 248 output_tx.SetHash(output_tx.Serialize()) 249 return 250 }