// Download raw transaction from a web server (try one after another) func GetTxFromWeb(txid *btc.Uint256) (raw []byte) { raw = GetTxFromWebBTC(txid) if raw != nil && txid.Equal(btc.NewSha2Hash(raw)) { println("GetTxFromWebBTC - OK") return } raw = GetTxFromBlockrIo(txid) if raw != nil && txid.Equal(btc.NewSha2Hash(raw)) { println("GetTxFromBlockrIo - OK") return } raw, _ = GetTxFromExplorer(txid) if raw != nil && txid.Equal(btc.NewSha2Hash(raw)) { println("GetTxFromExplorer - OK") return } return }
func write_tx_file(tx *btc.Tx) { signedrawtx := tx.Serialize() tx.Hash = btc.NewSha2Hash(signedrawtx) hs := tx.Hash.String() fmt.Println(hs) f, _ := os.Create(hs[:8] + ".txt") if f != nil { f.Write([]byte(hex.EncodeToString(signedrawtx))) f.Close() fmt.Println("Transaction data stored in", hs[:8]+".txt") } }
func raw_tx_from_file(fn string) *btc.Tx { dat := sys.GetRawData(fn) if dat == nil { fmt.Println("Cannot fetch raw transaction data") return nil } tx, txle := btc.NewTx(dat) if tx != nil { tx.Hash = btc.NewSha2Hash(dat) if txle != len(dat) { fmt.Println("WARNING: Raw transaction length mismatch", txle, len(dat)) } } return tx }
func LoadRawTx(buf []byte) (s string) { txd, er := hex.DecodeString(string(buf)) if er != nil { txd = buf } // At this place we should have raw transaction in txd tx, le := btc.NewTx(txd) if tx == nil || le != len(txd) { s += fmt.Sprintln("Could not decode transaction file or it has some extra data") return } tx.Hash = btc.NewSha2Hash(txd) network.TxMutex.Lock() defer network.TxMutex.Unlock() if _, ok := network.TransactionsToSend[tx.Hash.BIdx()]; ok { s += fmt.Sprintln("TxID", tx.Hash.String(), "was already in the pool") return } var missinginp bool var totinp, totout uint64 s, missinginp, totinp, totout, er = DecodeTx(tx) if er != nil { return } if missinginp { network.TransactionsToSend[tx.Hash.BIdx()] = &network.OneTxToSend{Tx: tx, Data: txd, Own: 2, Firstseen: time.Now(), Volume: totout} } else { network.TransactionsToSend[tx.Hash.BIdx()] = &network.OneTxToSend{Tx: tx, Data: txd, Own: 1, Firstseen: time.Now(), Volume: totinp, Fee: totinp - totout} } s += fmt.Sprintln("Transaction added to the memory pool. Please double check its details above.") s += fmt.Sprintln("If it does what you intended, you can send it the network.\nUse TxID:", tx.Hash.String()) return }
func push_tx(rawtx string) { dat := sys.GetRawData(rawtx) if dat == nil { println("Cannot fetch the raw transaction data (specify hexdump or filename)") return } val := make(url.Values) val["rawtx"] = []string{hex.EncodeToString(dat)} r, er := http.PostForm(HOST+"txs", val) if er != nil { println(er.Error()) os.Exit(1) } if r.StatusCode == 200 { defer r.Body.Close() res, _ := ioutil.ReadAll(r.Body) if len(res) > 100 { txid := btc.NewSha2Hash(dat) fmt.Println("TxID", txid.String(), "loaded") http_get(HOST + "cfg") // get SID //fmt.Println("sid", SID) u, _ := url.Parse(HOST + "txs2s.xml") ps := url.Values{} ps.Add("sid", SID) ps.Add("send", txid.String()) u.RawQuery = ps.Encode() http_get(u.String()) } } else { println("http.Post returned code", r.StatusCode) os.Exit(1) } }
// Handle incoming "tx" msg func (c *OneConnection) ParseTxNet(pl []byte) { tid := btc.NewSha2Hash(pl) NeedThisTx(tid, func() { // This body is called with a locked TxMutex if uint32(len(pl)) > atomic.LoadUint32(&common.CFG.TXPool.MaxTxSize) { common.CountSafe("TxRejectedBig") RejectTx(tid, len(pl), TX_REJECTED_TOO_BIG) return } tx, le := btc.NewTx(pl) if tx == nil { RejectTx(tid, len(pl), TX_REJECTED_FORMAT) c.DoS("TxRejectedBroken") return } if le != len(pl) { RejectTx(tid, len(pl), TX_REJECTED_LEN_MISMATCH) c.DoS("TxRejectedLenMismatch") return } if len(tx.TxIn) < 1 { RejectTx(tid, len(pl), TX_REJECTED_EMPTY_INPUT) c.Misbehave("TxRejectedNoInputs", 100) return } tx.Hash = tid select { case NetTxs <- &TxRcvd{conn: c, tx: tx, raw: pl}: TransactionsPending[tid.BIdx()] = true default: common.CountSafe("NetTxsFULL") println("NetTxsFULL") } }) }
func main() { if len(os.Args) < 2 { fmt.Println("Specify a path to folder containig blockchain.dat and blockchain.new") fmt.Println("Output bootstrap.dat file will be written in the current folder.") return } blks := chain.NewBlockDB(os.Args[1]) if blks == nil { return } fmt.Println("Loading block index...") bidx = make(map[[32]byte]*chain.BlockTreeNode, 300e3) blks.LoadBlockIndex(nil, walk) var tail, nd *chain.BlockTreeNode var genesis_block_hash *btc.Uint256 for _, v := range bidx { if v == tail { // skip root block (should be only one) continue } par_hash := btc.NewUint256(v.BlockHeader[4:36]) par, ok := bidx[par_hash.Hash] if !ok { genesis_block_hash = par_hash } else { v.Parent = par if tail == nil || v.Height > tail.Height { tail = v } } } if genesis_block_hash == nil { println("genesis_block_hash not found") return } var magic []byte gen_bin, _ := hex.DecodeString(GenesisBitcoin) tmp := btc.NewSha2Hash(gen_bin[:80]) if genesis_block_hash.Equal(tmp) { println("Bitcoin genesis block") magic = []byte{0xF9, 0xBE, 0xB4, 0xD9} } if magic == nil { gen_bin, _ := hex.DecodeString(GenesisTestnet) tmp = btc.NewSha2Hash(gen_bin[:80]) if genesis_block_hash.Equal(tmp) { println("Testnet3 genesis block") magic = []byte{0x0B, 0x11, 0x09, 0x07} } } if magic == nil { println("Unknow genesis block", genesis_block_hash.String()) println("Aborting since cannot figure out the magic bytes") return } var total_data, curr_data int64 for nd = tail; nd.Parent != nil; { nd.Parent.Childs = []*chain.BlockTreeNode{nd} total_data += int64(nd.BlockSize) nd = nd.Parent } fmt.Println("Writting bootstrap.dat, height", tail.Height, " magic", hex.EncodeToString(magic)) f, _ := os.Create("bootstrap.dat") f.Write(magic) binary.Write(f, binary.LittleEndian, uint32(len(gen_bin))) f.Write(gen_bin) for { bl, _, _ := blks.BlockGet(nd.BlockHash) f.Write(magic) binary.Write(f, binary.LittleEndian, uint32(len(bl))) f.Write(bl) curr_data += int64(nd.BlockSize) if (nd.Height & 0xfff) == 0 { fmt.Printf("\r%.1f%%...", 100*float64(curr_data)/float64(total_data)) } if len(nd.Childs) == 0 { break } nd = nd.Childs[0] } fmt.Println("\rDone ") }
func (c *one_net_conn) block(d []byte) { atomic.AddUint64(&DlBytesDownloaded, uint64(len(d))) BlocksMutex.Lock() defer BlocksMutex.Unlock() h := btc.NewSha2Hash(d[:80]) c.Lock() c.last_blk_rcvd = time.Now() c.Unlock() bip := BlocksInProgress[h.Hash] if bip == nil || !bip.Conns[c.id] { COUNTER("BNOT") //fmt.Println(h.String(), "- already received", bip) return } //fmt.Println(h.String(), "- new", bip.Height) COUNTER("BYES") delete(bip.Conns, c.id) c.Lock() c.inprogress-- c.Unlock() blocksize_update(len(d)) bl, er := btc.NewBlock(d) if er != nil { fmt.Println(c.Ip(), "-", er.Error()) c.setbroken(true) return } bl.BuildTxList() if !bytes.Equal(btc.GetMerkel(bl.Txs), bl.MerkleRoot()) { fmt.Println(c.Ip(), " - MerkleRoot mismatch at block", bip.Height) c.setbroken(true) return } delete(BlocksToGet, bip.Height) delete(BlocksInProgress, h.Hash) if len(BlocksInProgress) == 0 { EmptyInProgressCnt++ } //println("got-", bip.Height, BlocksComplete+1) if BlocksComplete+1 == bip.Height { BlocksComplete++ BlockQueue <- bl for { bl = BlocksCached[BlocksComplete+1] if bl == nil { break } BlocksComplete++ delete(BlocksCached, BlocksComplete) BlocksCachedSize -= uint64(len(bl.Raw)) BlockQueue <- bl } } else { BlocksCached[bip.Height] = bl BlocksCachedSize += uint64(len(d)) } }
// 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 }