Beispiel #1
0
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)
			}
		}
	}
}
Beispiel #2
0
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)
}
Beispiel #3
0
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
			}
		}
	}
}
Beispiel #4
0
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
		}
	}
}
Beispiel #5
0
// 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
}