func TestScritpsValid(t *testing.T) { DBG_ERR = false dat, er := ioutil.ReadFile("../test/script_valid.json") if er != nil { t.Error(er.Error()) return } var vecs [][]string er = json.Unmarshal(dat, &vecs) if er != nil { t.Error(er.Error()) return } tot := 0 for i := range vecs { if len(vecs[i]) >= 3 { tot++ s1, e := btc.DecodeScript(vecs[i][0]) if e != nil { t.Error(tot, "error A in", vecs[i][0], "->", vecs[i][1]) return } s2, e := btc.DecodeScript(vecs[i][1]) if e != nil { t.Error(tot, "error B in", vecs[i][0], "->", vecs[i][1]) return } flags, e := decode_flags(vecs[i][2]) if e != nil { //fmt.Println("InvalidScript", tot, e.Error()) continue } res := VerifyTxScript(s1, s2, 0, mk_out_tx(s1, s2), flags) if !res { ex := "" if len(vecs[i]) > 3 { ex = "/ " + vecs[i][3] } t.Error(tot, "VerifyTxScript failed in", vecs[i][0], "->", vecs[i][1], "/", vecs[i][2], ex) } } } }
func execute_test_tx(t *testing.T, tv *testvector) bool { if len(tv.inps) == 0 { t.Error("Vector has no inputs") return false } rd, er := hex.DecodeString(tv.tx) if er != nil { t.Error(er.Error()) return false } tx, _ := btc.NewTx(rd) if tx == nil { t.Error("Canot decode tx") return false } tx.Size = uint32(len(rd)) ha := btc.Sha2Sum(rd) tx.Hash = btc.NewUint256(ha[:]) if skip_broken_tests(tx) { return false } if !tx.IsCoinBase() { for i := range tx.TxIn { if tx.TxIn[i].Input.IsNull() { return false } } } oks := 0 for i := range tx.TxIn { var j int for j = range tv.inps { if bytes.Equal(tx.TxIn[i].Input.Hash[:], tv.inps[j].txid.Hash[:]) && tx.TxIn[i].Input.Vout == uint32(tv.inps[j].vout) { break } } if j >= len(tv.inps) { t.Error("Matching input not found") continue } pk, er := btc.DecodeScript(tv.inps[j].pkscr) if er != nil { t.Error(er.Error()) continue } var ss []byte if tv.inps[j].vout >= 0 { ss = tx.TxIn[i].ScriptSig } if VerifyTxScript(ss, pk, i, tx, tv.ver_flags) { oks++ } } return oks == len(tx.TxIn) }
func TestScritpsInvalid(t *testing.T) { var vecs [][]string DBG_ERR = false dat, er := ioutil.ReadFile("../test/script_invalid.json") if er != nil { t.Error(er.Error()) return } er = json.Unmarshal(dat, &vecs) if er != nil { t.Error(er.Error()) return } tot := 0 for i := range vecs { if len(vecs[i]) >= 2 { tot++ s1, e := btc.DecodeScript(vecs[i][0]) if e != nil { t.Error(tot, "error A in", vecs[i][0], "->", vecs[i][1]) return } s2, e := btc.DecodeScript(vecs[i][1]) if e != nil { t.Error(tot, "error B in", vecs[i][0], "->", vecs[i][1]) return } res := VerifyTxScript(s1, s2, 0, dummy_tx, true) if res { t.Error(tot, "VerifyTxScript NOT failed in", vecs[i][0], "->", vecs[i][1]) return } } } }
func TestScritps(t *testing.T) { var str interface{} var vecs []*one_test_vector DBG_ERR = false dat, er := ioutil.ReadFile("../test/script_tests.json") if er != nil { t.Error(er.Error()) return } er = json.Unmarshal(dat, &str) if er != nil { t.Error(er.Error()) return } m := str.([]interface{}) for i := range m { switch mm := m[i].(type) { case []interface{}: if len(mm) < 4 { continue } var skip bool var bfield int var e error var all_good bool vec := new(one_test_vector) for ii := range mm { switch segwitdata := mm[ii].(type) { case []interface{}: for iii := range segwitdata { switch segwitdata[iii].(type) { case string: var by []byte s := segwitdata[iii].(string) by, e = hex.DecodeString(s) if e != nil { t.Error("error parsing serwit script", s) skip = true break } vec.witness = append(vec.witness, by) case float64: vec.value = uint64(1e8 * segwitdata[iii].(float64)) } } case string: s := mm[ii].(string) if bfield == 0 { vec.sigscr, e = btc.DecodeScript(s) if e != nil { t.Error("error parsing script", s) skip = true break } } else if bfield == 1 { vec.pkscr, e = btc.DecodeScript(s) if e != nil { skip = true break } } else if bfield == 2 { vec.flags, e = decode_flags(s) if e != nil { println("error parsing flag", e.Error()) skip = true break } } else if bfield == 3 { vec.exp_res = s == "OK" all_good = true } else if bfield == 4 { vec.desc = s skip = true break } bfield++ default: panic("Enexpected test vector") skip = true } if skip { break } } if all_good { vecs = append(vecs, vec) } } } tot := 0 for _, v := range vecs { tot++ /* if tot==114400 { DBG_SCR = true DBG_ERR = true }*/ flags := v.flags if (flags & VER_CLEANSTACK) != 0 { flags |= VER_P2SH flags |= VER_WITNESS } credit_tx := mk_credit_tx(v.pkscr, v.value) spend_tx := mk_spend_tx(credit_tx, v.sigscr, v.witness) if DBG_SCR { println("desc:", v, tot, v.desc) println("pkscr:", hex.EncodeToString(v.pkscr)) println("sigscr:", hex.EncodeToString(v.sigscr)) println("credit:", hex.EncodeToString(credit_tx.Serialize())) println("spend:", hex.EncodeToString(spend_tx.Serialize())) println("------------------------------ testing vector", tot, len(v.witness), v.value) } res := VerifyTxScript(v.pkscr, v.value, 0, spend_tx, flags) if res != v.exp_res { t.Error(tot, "TestScritps failed. Got:", res, " exp:", v.exp_res, v.desc) return } else { if DBG_SCR { println(tot, "ok:", res, v.desc) } } if tot == 114400 { return } } }
// Download (and re-assemble) raw transaction from blockexplorer.com func GetTxFromExplorer(txid *btc.Uint256) ([]byte, []byte) { url := "http://blockexplorer.com/rawtx/" + txid.String() r, er := http.Get(url) if er == nil && r.StatusCode == 200 { defer r.Body.Close() c, _ := ioutil.ReadAll(r.Body) var txx onetx er = json.Unmarshal(c[:], &txx) if er == nil { // This part looks weird, but this is how I solved seq=FFFFFFFF, if the field not present: for i := range txx.In { txx.In[i].Sequence = 0xffffffff } json.Unmarshal(c[:], &txx) // ... end of the weird solution tx := new(btc.Tx) tx.Version = txx.Ver tx.TxIn = make([]*btc.TxIn, len(txx.In)) for i := range txx.In { tx.TxIn[i] = new(btc.TxIn) tx.TxIn[i].Input.Hash = btc.NewUint256FromString(txx.In[i].Prev_out.Hash).Hash tx.TxIn[i].Input.Vout = txx.In[i].Prev_out.N if txx.In[i].Prev_out.N == 0xffffffff && txx.In[i].Prev_out.Hash == "0000000000000000000000000000000000000000000000000000000000000000" { tx.TxIn[i].ScriptSig, _ = hex.DecodeString(txx.In[i].Coinbase) } else { tx.TxIn[i].ScriptSig, _ = btc.DecodeScript(txx.In[i].ScriptSig) } tx.TxIn[i].Sequence = txx.In[i].Sequence } tx.TxOut = make([]*btc.TxOut, len(txx.Out)) for i := range txx.Out { am, er := btc.StringToSatoshis(txx.Out[i].Value) if er != nil { fmt.Println("Incorrect BTC amount", txx.Out[i].Value, er.Error()) return nil, nil } tx.TxOut[i] = new(btc.TxOut) tx.TxOut[i].Value = am tx.TxOut[i].Pk_script, _ = btc.DecodeScript(txx.Out[i].ScriptPubKey) } tx.Lock_time = txx.Lock_time rawtx := tx.Serialize() if txx.Size != uint(len(rawtx)) { fmt.Printf("Transaction size mismatch: %d expexted, %d decoded\n", txx.Size, len(rawtx)) return nil, rawtx } curid := btc.NewSha2Hash(rawtx) if !curid.Equal(txid) { fmt.Println("The downloaded transaction does not match its ID.", txid.String()) return nil, rawtx } return rawtx, rawtx } else { fmt.Println("json.Unmarshal:", er.Error()) } } else { if er != nil { fmt.Println("http.Get:", er.Error()) } else { fmt.Println("StatusCode=", r.StatusCode) } } return nil, nil }