func (c *oneConnection) ProcessGetBlocks(pl []byte) { b := bytes.NewReader(pl) var ver uint32 e := binary.Read(b, binary.LittleEndian, &ver) if e != nil { println("ProcessGetBlocks:", e.Error(), c.addr.Ip()) return } cnt, e := btc.ReadVLen(b) if e != nil { println("ProcessGetBlocks:", e.Error(), c.addr.Ip()) return } h2get := make([]*btc.Uint256, cnt) var h [32]byte for i := 0; i < int(cnt); i++ { n, _ := b.Read(h[:]) if n != 32 { println("getblocks too short", c.addr.Ip()) return } h2get[i] = btc.NewUint256(h[:]) if dbg > 1 { println(c.addr.Ip(), "getbl", h2get[i].String()) } } n, _ := b.Read(h[:]) if n != 32 { println("getblocks does not have hash_stop", c.addr.Ip()) return } hashstop := btc.NewUint256(h[:]) var maxheight uint32 invs := make(map[[32]byte]bool, 500) for i := range h2get { BlockChain.BlockIndexAccess.Lock() if bl, ok := BlockChain.BlockIndex[h2get[i].BIdx()]; ok { if bl.Height > maxheight { maxheight = bl.Height } addInvBlockBranch(invs, bl, hashstop) } BlockChain.BlockIndexAccess.Unlock() if len(invs) >= 500 { break } } inv := new(bytes.Buffer) btc.WriteVlen(inv, uint32(len(invs))) for k, _ := range invs { binary.Write(inv, binary.LittleEndian, uint32(2)) inv.Write(k[:]) } if dbg > 1 { fmt.Println(c.addr.Ip(), "getblocks", cnt, maxheight, " ...", len(invs), "invs in resp ->", len(inv.Bytes())) } InvsSent++ c.SendRawMsg("inv", inv.Bytes()) }
func (c *OneConnection) ProcessGetData(pl []byte) { //println(c.PeerAddr.Ip(), "getdata") b := bytes.NewReader(pl) cnt, e := btc.ReadVLen(b) if e != nil { println("ProcessGetData:", e.Error(), c.PeerAddr.Ip()) return } for i := 0; i < int(cnt); i++ { var typ uint32 var h [32]byte e = binary.Read(b, binary.LittleEndian, &typ) if e != nil { println("ProcessGetData:", e.Error(), c.PeerAddr.Ip()) return } n, _ := b.Read(h[:]) if n != 32 { println("ProcessGetData: pl too short", c.PeerAddr.Ip()) return } common.CountSafe(fmt.Sprint("GetdataType", typ)) if typ == 2 { uh := btc.NewUint256(h[:]) bl, _, er := common.BlockChain.Blocks.BlockGet(uh) if er == nil { c.SendRawMsg("block", bl) } else { //println("block", uh.String(), er.Error()) } } else if typ == 1 { // transaction uh := btc.NewUint256(h[:]) TxMutex.Lock() if tx, ok := TransactionsToSend[uh.Hash]; ok && tx.Blocked == 0 { tx.SentCnt++ tx.Lastsent = time.Now() TxMutex.Unlock() c.SendRawMsg("tx", tx.Data) if common.DebugLevel > 0 { println("sent tx to", c.PeerAddr.Ip()) } } else { TxMutex.Unlock() } } else { if common.DebugLevel > 0 { println("getdata for type", typ, "not supported yet") } } } }
func send_all_tx(par string) { network.TxMutex.Lock() for k, v := range network.TransactionsToSend { if v.Own != 0 { cnt := network.NetRouteInv(1, btc.NewUint256(k[:]), nil) v.Invsentcnt += cnt fmt.Println("INV for TxID", btc.NewUint256(k[:]).String(), "sent to", cnt, "node(s)") } } network.TxMutex.Unlock() }
func (c *OneConnection) GetBlockData(h []byte) { var b [1 + 4 + 32]byte b[0] = 1 // One inv b[1] = 2 // Block copy(b[5:37], h[:32]) if common.DebugLevel > 1 { println("GetBlockData", btc.NewUint256(h).String()) } bh := btc.NewUint256(h) c.Mutex.Lock() c.GetBlockInProgress[bh.BIdx()] = &oneBlockDl{hash: bh, start: time.Now()} c.Mutex.Unlock() c.SendRawMsg("getdata", b[:]) }
func xml_balance(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } w.Header()["Content-Type"] = []string{"text/xml"} w.Write([]byte("<unspent>")) wallet.LockBal() for i := range wallet.MyBalance { w.Write([]byte("<output>")) fmt.Fprint(w, "<txid>", btc.NewUint256(wallet.MyBalance[i].TxPrevOut.Hash[:]).String(), "</txid>") fmt.Fprint(w, "<vout>", wallet.MyBalance[i].TxPrevOut.Vout, "</vout>") fmt.Fprint(w, "<value>", wallet.MyBalance[i].Value, "</value>") fmt.Fprint(w, "<inblock>", wallet.MyBalance[i].MinedAt, "</inblock>") fmt.Fprint(w, "<blocktime>", get_block_time(wallet.MyBalance[i].MinedAt), "</blocktime>") fmt.Fprint(w, "<addr>", wallet.MyBalance[i].BtcAddr.String(), "</addr>") fmt.Fprint(w, "<wallet>", html.EscapeString(wallet.MyBalance[i].BtcAddr.Extra.Wallet), "</wallet>") fmt.Fprint(w, "<label>", html.EscapeString(wallet.MyBalance[i].BtcAddr.Extra.Label), "</label>") fmt.Fprint(w, "<virgin>", fmt.Sprint(wallet.MyBalance[i].BtcAddr.Extra.Virgin), "</virgin>") w.Write([]byte("</output>")) } wallet.UnlockBal() w.Write([]byte("</unspent>")) }
func list_txs(par string) { fmt.Println("Transactions in the memory pool:") cnt := 0 network.TxMutex.Lock() for k, v := range network.TransactionsToSend { cnt++ var oe, snt string if v.Own != 0 { oe = " *OWN*" } else { oe = "" } snt = fmt.Sprintf("INV sent %d times, ", v.Invsentcnt) if v.SentCnt == 0 { snt = "TX never sent" } else { snt = fmt.Sprintf("TX sent %d times, last %s ago", v.SentCnt, time.Now().Sub(v.Lastsent).String()) } fmt.Printf("%5d) %s - %d bytes - %s%s\n", cnt, btc.NewUint256(k[:]).String(), len(v.Data), snt, oe) } network.TxMutex.Unlock() }
func list_txs(par string) { fmt.Println("Transactions in the memory pool:") cnt := 0 for k, v := range TransactionsToSend { fmt.Println(cnt, btc.NewUint256(k[:]).String(), "-", len(v), "bytes") } }
func GetBlockData(h []byte) []byte { bl, _, e := BlockChain.Blocks.BlockGet(btc.NewUint256(h)) if e == nil { return bl } println("BlockChain.Blocks.BlockGet failed") return nil }
func (c *oneConnection) ProcessGetData(pl []byte) { //println(c.addr.Ip(), "getdata") b := bytes.NewReader(pl) cnt, e := btc.ReadVLen(b) if e != nil { println("ProcessGetData:", e.Error(), c.addr.Ip()) return } for i := 0; i < int(cnt); i++ { var typ uint32 var h [32]byte e = binary.Read(b, binary.LittleEndian, &typ) if e != nil { println("ProcessGetData:", e.Error(), c.addr.Ip()) return } n, _ := b.Read(h[:]) if n != 32 { println("ProcessGetData: pl too short", c.addr.Ip()) return } if typ == 2 { uh := btc.NewUint256(h[:]) bl, _, er := BlockChain.Blocks.BlockGet(uh) if er == nil { BlockSent++ c.SendRawMsg("block", bl) } else { //println("block", uh.String(), er.Error()) } } else if typ == 1 { // transaction uh := btc.NewUint256(h[:]) if tx, ok := TransactionsToSend[uh.Hash]; ok { c.SendRawMsg("tx", tx) println("sent tx to", c.addr.Ip()) } } else { println("getdata for type", typ, "not supported yet") } } }
// Handle tx-inv notifications func (c *OneConnection) TxInvNotify(hash []byte) { if NeedThisTx(btc.NewUint256(hash), nil) { var b [1 + 4 + 32]byte b[0] = 1 // One inv b[1] = 1 // Tx copy(b[5:37], hash) c.SendRawMsg("getdata", b[:]) } }
// Call it only from the Chain thread func DumpBalance(utxt *os.File, details bool) (s string) { var sum uint64 mutex_bal.Lock() defer mutex_bal.Unlock() for i := range MyBalance { sum += MyBalance[i].Value if details { if i < 100 { s += fmt.Sprintf("%7d %s\n", 1+common.Last.Block.Height-MyBalance[i].MinedAt, MyBalance[i].String()) } else if i == 100 { s += fmt.Sprintln("List of unspent outputs truncated to 100 records") } } // update the balance/ folder if utxt != nil { po, e := common.BlockChain.Unspent.UnspentGet(&MyBalance[i].TxPrevOut) if e != nil { println("UnspentGet:", e.Error()) println("This should not happen - please, report a bug.") println("You can probably fix it by launching the client with -rescan") os.Exit(1) } txid := btc.NewUint256(MyBalance[i].TxPrevOut.Hash[:]) // Store the unspent line in balance/unspent.txt fmt.Fprintf(utxt, "%s # %.8f BTC @ %s, %d confs\n", MyBalance[i].TxPrevOut.String(), float64(MyBalance[i].Value)/1e8, MyBalance[i].BtcAddr.StringLab(), 1+common.Last.Block.Height-MyBalance[i].MinedAt) // store the entire transactiojn in balance/<txid>.tx fn := "balance/" + txid.String()[:64] + ".tx" txf, _ := os.Open(fn) if txf == nil { // Do it only once per txid txf, _ = os.Create(fn) if txf == nil { println("Cannot create ", fn) os.Exit(1) } GetRawTransaction(po.BlockHeight, txid, txf) } txf.Close() } } LastBalance = sum s += fmt.Sprintf("Total balance: %.8f BTC in %d unspent outputs\n", float64(sum)/1e8, len(MyBalance)) if utxt != nil { utxt.Close() } return }
func (c *oneConnection) GetBlockData(h []byte) { var b [1 + 4 + 32]byte b[0] = 1 // One inv b[1] = 2 // Block copy(b[5:37], h[:32]) if dbg > 1 { println("GetBlockData", btc.NewUint256(h).String()) } c.SendRawMsg("getdata", b[:]) }
func (db *unwindDb) stats() (s string) { var cnt int for i := range db.tdb { cnt += db.dbH(i).Count() } s = fmt.Sprintf("UNWIND: len:%d last:%d defrags:%d/%d\n", cnt, db.lastBlockHeight, db.defragCount, db.defragIndex) s += "Last block: " + btc.NewUint256(db.lastBlockHash[:]).String() + "\n" return }
func DecodeTx(tx *btc.Tx) (s string, missinginp bool, totinp, totout uint64, e error) { s += fmt.Sprintln("Transaction details (for your information):") s += fmt.Sprintln(len(tx.TxIn), "Input(s):") for i := range tx.TxIn { s += fmt.Sprintf(" %3d %s", i, tx.TxIn[i].Input.String()) var po *btc.TxOut inpid := btc.NewUint256(tx.TxIn[i].Input.Hash[:]) if txinmem, ok := network.TransactionsToSend[inpid.BIdx()]; ok { s += fmt.Sprint(" mempool") if int(tx.TxIn[i].Input.Vout) >= len(txinmem.TxOut) { s += fmt.Sprintf(" - Vout TOO BIG (%d/%d)!", int(tx.TxIn[i].Input.Vout), len(txinmem.TxOut)) } else { po = txinmem.TxOut[tx.TxIn[i].Input.Vout] } } else { po, _ = common.BlockChain.Unspent.UnspentGet(&tx.TxIn[i].Input) if po != nil { s += fmt.Sprintf("%8d", po.BlockHeight) } } if po != nil { ok := btc.VerifyTxScript(tx.TxIn[i].ScriptSig, po.Pk_script, i, tx, true) if !ok { s += fmt.Sprintln("\nERROR: The transacion does not have a valid signature.") e = errors.New("Invalid signature") return } totinp += po.Value s += fmt.Sprintf(" %15.8f BTC @ %s\n", float64(po.Value)/1e8, btc.NewAddrFromPkScript(po.Pk_script, common.Testnet).String()) } else { s += fmt.Sprintln(" - UNKNOWN INPUT") missinginp = true } } s += fmt.Sprintln(len(tx.TxOut), "Output(s):") for i := range tx.TxOut { totout += tx.TxOut[i].Value adr := btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, common.Testnet) if adr != nil { s += fmt.Sprintf(" %15.8f BTC to adr %s\n", float64(tx.TxOut[i].Value)/1e8, adr.String()) } else { s += fmt.Sprintf(" %15.8f BTC to scr %s\n", float64(tx.TxOut[i].Value)/1e8, hex.EncodeToString(tx.TxOut[i].Pk_script)) } } if missinginp { s += fmt.Sprintln("WARNING: There are missing inputs and we cannot calc input BTC amount.") s += fmt.Sprintln("If there is somethign wrong with this transaction, you can loose money...") } else { s += fmt.Sprintf("All OK: %.8f BTC in -> %.8f BTC out, with %.8f BTC fee\n", float64(totinp)/1e8, float64(totout)/1e8, float64(totinp-totout)/1e8) } return }
func xmp_txs2s(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } r.ParseForm() if checksid(r) && len(r.Form["del"]) > 0 { tid := btc.NewUint256FromString(r.Form["del"][0]) if tid != nil { network.TxMutex.Lock() delete(network.TransactionsToSend, tid.Hash) network.TxMutex.Unlock() } } if checksid(r) && len(r.Form["send"]) > 0 { tid := btc.NewUint256FromString(r.Form["send"][0]) if tid != nil { network.TxMutex.Lock() if ptx, ok := network.TransactionsToSend[tid.Hash]; ok { network.TxMutex.Unlock() cnt := network.NetRouteInv(1, tid, nil) ptx.Invsentcnt += cnt } } } w.Header()["Content-Type"] = []string{"text/xml"} if len(r.Form["id"]) > 0 { output_tx_xml(w, r.Form["id"][0]) return } w.Write([]byte("<txpool>")) network.TxMutex.Lock() for k, v := range network.TransactionsToSend { w.Write([]byte("<tx>")) fmt.Fprint(w, "<id>", btc.NewUint256(k[:]).String(), "</id>") fmt.Fprint(w, "<time>", v.Firstseen.Unix(), "</time>") fmt.Fprint(w, "<len>", len(v.Data), "</len>") fmt.Fprint(w, "<own>", v.Own, "</own>") fmt.Fprint(w, "<firstseen>", v.Firstseen.Unix(), "</firstseen>") fmt.Fprint(w, "<invsentcnt>", v.Invsentcnt, "</invsentcnt>") fmt.Fprint(w, "<sentcnt>", v.SentCnt, "</sentcnt>") fmt.Fprint(w, "<sentlast>", v.Lastsent.Unix(), "</sentlast>") fmt.Fprint(w, "<volume>", v.Volume, "</volume>") fmt.Fprint(w, "<fee>", v.Fee, "</fee>") fmt.Fprint(w, "<blocked>", v.Blocked, "</blocked>") w.Write([]byte("</tx>")) } network.TxMutex.Unlock() w.Write([]byte("</txpool>")) }
func (c *oneConnection) GetBlocks(lastbl []byte) { if dbg > 0 { println("GetBlocks since", btc.NewUint256(lastbl).String()) } var b [4 + 1 + 32 + 32]byte binary.LittleEndian.PutUint32(b[0:4], Version) b[4] = 1 // only one locator copy(b[5:37], lastbl) // the remaining bytes should be filled with zero c.SendRawMsg("getblocks", b[:]) }
func baned_txs(par string) { fmt.Println("Rejected transactions:") cnt := 0 network.TxMutex.Lock() for k, v := range network.TransactionsRejected { cnt++ fmt.Println("", cnt, btc.NewUint256(k[:]).String(), "-", v.Size, "bytes", "-", v.Reason, "-", time.Now().Sub(v.Time).String(), "ago") } network.TxMutex.Unlock() }
func output_tx_xml(w http.ResponseWriter, id string) { txid := btc.NewUint256FromString(id) w.Write([]byte("<tx>")) fmt.Fprint(w, "<id>", id, "</id>") if t2s, ok := network.TransactionsToSend[txid.BIdx()]; ok { w.Write([]byte("<status>OK</status>")) tx := t2s.Tx w.Write([]byte("<inputs>")) for i := range tx.TxIn { w.Write([]byte("<input>")) var po *btc.TxOut inpid := btc.NewUint256(tx.TxIn[i].Input.Hash[:]) if txinmem, ok := network.TransactionsToSend[inpid.BIdx()]; ok { if int(tx.TxIn[i].Input.Vout) < len(txinmem.TxOut) { po = txinmem.TxOut[tx.TxIn[i].Input.Vout] } } else { po, _ = common.BlockChain.Unspent.UnspentGet(&tx.TxIn[i].Input) } if po != nil { ok := btc.VerifyTxScript(tx.TxIn[i].ScriptSig, po.Pk_script, i, tx, true) if !ok { w.Write([]byte("<status>Script FAILED</status>")) } else { w.Write([]byte("<status>OK</status>")) } fmt.Fprint(w, "<value>", po.Value, "</value>") fmt.Fprint(w, "<addr>", btc.NewAddrFromPkScript(po.Pk_script, common.Testnet).String(), "</addr>") fmt.Fprint(w, "<block>", po.BlockHeight, "</block>") } else { w.Write([]byte("<status>UNKNOWN INPUT</status>")) } w.Write([]byte("</input>")) } w.Write([]byte("</inputs>")) w.Write([]byte("<outputs>")) for i := range tx.TxOut { w.Write([]byte("<output>")) fmt.Fprint(w, "<value>", tx.TxOut[i].Value, "</value>") adr := btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, common.Testnet) if adr != nil { fmt.Fprint(w, "<addr>", adr.String(), "</addr>") } else { fmt.Fprint(w, "<addr>", "scr:"+hex.EncodeToString(tx.TxOut[i].Pk_script), "</addr>") } w.Write([]byte("</output>")) } w.Write([]byte("</outputs>")) } else { w.Write([]byte("<status>Not found</status>")) } w.Write([]byte("</tx>")) }
func blockWanted(h []byte) (yes bool) { ha := btc.NewUint256(h) idx := ha.BIdx() mutex.Lock() if _, ok := receivedBlocks[idx]; !ok { yes = true } mutex.Unlock() if !yes { InvsIgnored++ } return }
func chkblock(bl *btc.Block) (er error) { // Check timestamp (must not be higher than now +2 hours) if int64(bl.BlockTime) > time.Now().Unix()+2*60*60 { er = errors.New("CheckBlock() : block timestamp too far in the future") return } if prv, pres := MemBlockChain.BlockIndex[bl.Hash.BIdx()]; pres { if prv.Parent == nil { // This is genesis block prv.Timestamp = bl.BlockTime prv.Bits = bl.Bits er = errors.New("Genesis") return } else { return } } prevblk, ok := MemBlockChain.BlockIndex[btc.NewUint256(bl.Parent).BIdx()] if !ok { er = errors.New("CheckBlock: " + bl.Hash.String() + " parent not found") return } // Check proof of work gnwr := MemBlockChain.GetNextWorkRequired(prevblk, bl.BlockTime) if bl.Bits != gnwr { if !Testnet || ((prevblk.Height+1)%2016) != 0 { er = errors.New(fmt.Sprint("CheckBlock: Incorrect proof of work at block", prevblk.Height+1)) } } cur := new(btc.BlockTreeNode) cur.BlockHash = bl.Hash cur.Parent = prevblk cur.Height = prevblk.Height + 1 cur.Bits = bl.Bits cur.Timestamp = bl.BlockTime prevblk.Childs = append(prevblk.Childs, cur) MemBlockChain.BlockIndex[cur.BlockHash.BIdx()] = cur LastBlock.Mutex.Lock() if cur.Height > LastBlock.node.Height { LastBlock.node = cur } LastBlock.Mutex.Unlock() return }
// Read VLen followed by the number of locators // parse the payload of getblocks and getheaders messages func parseLocatorsPayload(pl []byte) (h2get []*btc.Uint256, hashstop *btc.Uint256, er error) { var cnt uint64 var h [32]byte var ver uint32 b := bytes.NewReader(pl) // version if er = binary.Read(b, binary.LittleEndian, &ver); er != nil { return } // hash count cnt, er = btc.ReadVLen(b) if er != nil { return } // block locator hashes if cnt > 0 { h2get = make([]*btc.Uint256, cnt) for i := 0; i < int(cnt); i++ { if _, er = b.Read(h[:]); er != nil { return } h2get[i] = btc.NewUint256(h[:]) } } // hash_stop if _, er = b.Read(h[:]); er != nil { return } hashstop = btc.NewUint256(h[:]) return }
func p_snd(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } s := load_template("send.html") wallet.LockBal() if wallet.MyWallet != nil && len(wallet.MyBalance) > 0 { wal := load_template("send_wal.html") row_tmp := load_template("send_wal_row.html") wal = strings.Replace(wal, "{TOTAL_BTC}", fmt.Sprintf("%.8f", float64(wallet.LastBalance)/1e8), 1) wal = strings.Replace(wal, "{UNSPENT_OUTS}", fmt.Sprint(len(wallet.MyBalance)), -1) for i := range wallet.MyBalance { row := row_tmp row = strings.Replace(row, "{ADDR_LABEL}", html.EscapeString(wallet.MyBalance[i].BtcAddr.Label), 1) row = strings.Replace(row, "{ROW_NUMBER}", fmt.Sprint(i+1), -1) row = strings.Replace(row, "{MINED_IN}", fmt.Sprint(wallet.MyBalance[i].MinedAt), 1) row = strings.Replace(row, "{TX_ID}", btc.NewUint256(wallet.MyBalance[i].TxPrevOut.Hash[:]).String(), -1) row = strings.Replace(row, "{TX_VOUT}", fmt.Sprint(wallet.MyBalance[i].TxPrevOut.Vout), -1) row = strings.Replace(row, "{BTC_AMOUNT}", fmt.Sprintf("%.8f", float64(wallet.MyBalance[i].Value)/1e8), 1) row = strings.Replace(row, "{OUT_VALUE}", fmt.Sprint(wallet.MyBalance[i].Value), 1) row = strings.Replace(row, "{BTC_ADDR}", wallet.MyBalance[i].BtcAddr.String(), 1) wal = templ_add(wal, "<!--UTXOROW-->", row) } for i := range wallet.MyWallet.Addrs { op := "<option value=\"" + wallet.MyWallet.Addrs[i].Enc58str + "\">" + wallet.MyWallet.Addrs[i].Enc58str + " (" + html.EscapeString(wallet.MyWallet.Addrs[i].Label) + ")</option>" //wal = strings.Replace(wal, "<!--ONECHANGEADDR-->", op, 1) wal = templ_add(wal, "<!--ONECHANGEADDR-->", op) } s = strings.Replace(s, "<!--WALLET-->", wal, 1) } else { if wallet.MyWallet == nil { s = strings.Replace(s, "<!--WALLET-->", "You have no wallet", 1) } else { s = strings.Replace(s, "<!--WALLET-->", "Your current wallet is empty", 1) } } wallet.UnlockBal() write_html_head(w, r) w.Write([]byte(s)) write_html_tail(w) }
// Called from network threads func blockWanted(h []byte) (yes bool) { idx := btc.NewUint256(h).BIdx() MutexRcv.Lock() _, ok := ReceivedBlocks[idx] MutexRcv.Unlock() if !ok { if atomic.LoadUint32(&common.CFG.Net.MaxBlockAtOnce) == 0 || !blocksLimitReached(idx) { yes = true common.CountSafe("BlockWanted") } else { common.CountSafe("BlockInProgress") } } else { common.CountSafe("BlockUnwanted") } return }
func (c *OneConnection) ProcessInv(pl []byte) { if len(pl) < 37 { println(c.PeerAddr.Ip(), "inv payload too short", len(pl)) return } c.InvsRecieved++ cnt, of := btc.VLen(pl) if len(pl) != of+36*cnt { println("inv payload length mismatch", len(pl), of, cnt) } var blinv2ask []byte for i := 0; i < cnt; i++ { typ := binary.LittleEndian.Uint32(pl[of : of+4]) common.CountSafe(fmt.Sprint("InvGot", typ)) if typ == 2 { if blockWanted(pl[of+4 : of+36]) { blinv2ask = append(blinv2ask, pl[of+4:of+36]...) } } else if typ == 1 { if common.CFG.TXPool.Enabled { c.TxInvNotify(pl[of+4 : of+36]) } } of += 36 } if len(blinv2ask) > 0 { bu := new(bytes.Buffer) btc.WriteVlen(bu, uint32(len(blinv2ask)/32)) for i := 0; i < len(blinv2ask); i += 32 { bh := btc.NewUint256(blinv2ask[i : i+32]) c.Mutex.Lock() c.GetBlockInProgress[bh.BIdx()] = &oneBlockDl{hash: bh, start: time.Now()} c.Mutex.Unlock() binary.Write(bu, binary.LittleEndian, uint32(2)) bu.Write(bh.Hash[:]) } c.SendRawMsg("getdata", bu.Bytes()) } return }
func InvsNotify(h []byte) (need bool) { ha := btc.NewUint256(h) idx := ha.BIdx() mutex.Lock() if _, ok := pendingBlocks[idx]; ok { InvsIgnored++ } else if _, ok := receivedBlocks[idx]; ok { InvsIgnored++ } else if len(pendingFifo) < PendingFifoLen { pendingBlocks[idx] = ha pendingFifo <- idx need = true } else { FifoFullCnt++ } mutex.Unlock() return }
func (c *one_net_conn) ping_idle() { c.ping.Lock() if c.ping.inProgress { if time.Now().After(c.ping.timeSent.Add(PING_TIMEOUT)) { c.store_ping_result() c.ping.Unlock() //fmt.Println(c.peerip, "ping timeout", c.ping.seq) } else { c.ping.Unlock() time.Sleep(time.Millisecond) } } else if c.ping.now { //fmt.Println("ping", c.peerip, c.ping.seq) c.ping.inProgress = true c.ping.timeSent = time.Now() c.ping.now = false if false { rand.Read(c.ping.pattern[:]) c.ping.Unlock() c.sendmsg("ping", c.ping.pattern[:]) } else { b := new(bytes.Buffer) btc.WriteVlen(b, PING_FETCH_BLOCKS) BlocksMutex.Lock() for i := uint32(1); ; i++ { binary.Write(b, binary.LittleEndian, uint32(2)) btg := BlocksToGet[i] b.Write(btg[:]) if i == PING_FETCH_BLOCKS { c.ping.lastBlock = btc.NewUint256(btg[:]) break } } BlocksMutex.Unlock() c.ping.bytes = 0 c.ping.Unlock() c.sendmsg("getdata", b.Bytes()) //fmt.Println("ping sent", c.ping.lastBlock.String()) } } else { c.ping.Unlock() time.Sleep(10 * time.Millisecond) } }
func dl_payment(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } var err string r.ParseForm() if len(r.Form["outcnt"]) == 1 { var thisbal btc.AllUnspentTx var pay_cmd string outcnt, _ := strconv.ParseUint(r.Form["outcnt"][0], 10, 32) wallet.LockBal() for i := 1; i <= int(outcnt); i++ { is := fmt.Sprint(i) if len(r.Form["txout"+is]) == 1 && r.Form["txout"+is][0] == "on" { hash := btc.NewUint256FromString(r.Form["txid"+is][0]) if hash != nil { vout, er := strconv.ParseUint(r.Form["txvout"+is][0], 10, 32) if er == nil { var po = btc.TxPrevOut{Hash: hash.Hash, Vout: uint32(vout)} for j := range wallet.MyBalance { if wallet.MyBalance[j].TxPrevOut == po { thisbal = append(thisbal, wallet.MyBalance[j]) } } } } } } wallet.UnlockBal() for i := 1; ; i++ { is := fmt.Sprint(i) if len(r.Form["adr"+is]) != 1 { break } if len(r.Form["btc"+is]) != 1 { break } if len(r.Form["adr"+is][0]) > 1 { addr, er := btc.NewAddrFromString(r.Form["adr"+is][0]) if er == nil { am, er := strconv.ParseFloat(r.Form["btc"+is][0], 64) if er == nil && am > 0 { if pay_cmd == "" { pay_cmd = "wallet -useallinputs -send " } else { pay_cmd += "," } pay_cmd += addr.Enc58str + "=" + fmt.Sprintf("%.8f", am) } else { err = "Incorrect amount (" + r.Form["btc"+is][0] + ") for Output #" + is goto error } } else { err = "Incorrect address (" + r.Form["adr"+is][0] + ") for Output #" + is goto error } } } if pay_cmd != "" && len(r.Form["txfee"]) == 1 { pay_cmd += " -fee " + r.Form["txfee"][0] } if pay_cmd != "" && len(r.Form["change"]) == 1 && len(r.Form["change"][0]) > 1 { pay_cmd += " -change " + r.Form["change"][0] } buf := new(bytes.Buffer) zi := zip.NewWriter(buf) was_tx := make(map[[32]byte]bool, len(thisbal)) for i := range thisbal { if was_tx[thisbal[i].TxPrevOut.Hash] { continue } was_tx[thisbal[i].TxPrevOut.Hash] = true txid := btc.NewUint256(thisbal[i].TxPrevOut.Hash[:]) fz, _ := zi.Create("balance/" + txid.String() + ".tx") wallet.GetRawTransaction(thisbal[i].MinedAt, txid, fz) } fz, _ := zi.Create("balance/unspent.txt") for i := range thisbal { fmt.Fprintf(fz, "%s # %.8f BTC @ %s, %d confs\n", thisbal[i].TxPrevOut.String(), float64(thisbal[i].Value)/1e8, thisbal[i].BtcAddr.StringLab(), 1+common.Last.Block.Height-thisbal[i].MinedAt) } if pay_cmd != "" { fz, _ = zi.Create("pay_cmd.txt") fz.Write([]byte(pay_cmd)) } zi.Close() w.Header()["Content-Type"] = []string{"application/zip"} w.Write(buf.Bytes()) return } else { err = "Bad request" } error: s := load_template("send_error.html") write_html_head(w, r) s = strings.Replace(s, "<!--ERROR_MSG-->", err, 1) w.Write([]byte(s)) write_html_tail(w) }
func main() { fmt.Println("Gocoin FetchBalnace version", btc.SourcesTag) if len(os.Args) < 2 { print_help() return } var addrs []*btc.BtcAddr if len(os.Args) == 2 { fi, er := os.Stat(os.Args[1]) if er == nil && fi.Size() > 10 && !fi.IsDir() { wal := wallet.NewWallet(os.Args[1]) if wal != nil { fmt.Println("Found", len(wal.Addrs), "address(es) in", wal.FileName) addrs = wal.Addrs } } } if len(addrs) == 0 { for i := 1; i < len(os.Args); i++ { a, e := btc.NewAddrFromString(os.Args[i]) if e != nil { println(os.Args[i], ": ", e.Error()) return } else { addrs = append(addrs, a) } } } if len(addrs) == 0 { print_help() return } url := "http://blockchain.info/unspent?active=" for i := range addrs { if i > 0 { url += "|" } url += addrs[i].String() } var sum, outcnt uint64 r, er := http.Get(url) if er == nil && r.StatusCode == 200 { defer r.Body.Close() c, _ := ioutil.ReadAll(r.Body) var r restype er = json.Unmarshal(c[:], &r) if er == nil { os.RemoveAll("balance/") os.Mkdir("balance/", 0700) unsp, _ := os.Create("balance/unspent.txt") for i := 0; i < len(r.Unspent_outputs); i++ { pkscr, _ := hex.DecodeString(r.Unspent_outputs[i].Script) b58adr := "???" if pkscr != nil { ba := btc.NewAddrFromPkScript(pkscr, btc.ADDRVER_BTC) if ba != nil { b58adr = ba.String() } } txidlsb, _ := hex.DecodeString(r.Unspent_outputs[i].Tx_hash) if txidlsb != nil { txid := btc.NewUint256(txidlsb) if GetTx(txid, int(r.Unspent_outputs[i].Tx_output_n)) { fmt.Fprintf(unsp, "%s-%03d # %.8f @ %s, %d confs\n", txid.String(), r.Unspent_outputs[i].Tx_output_n, float64(r.Unspent_outputs[i].Value)/1e8, b58adr, r.Unspent_outputs[i].Confirmations) sum += r.Unspent_outputs[i].Value outcnt++ } else { fmt.Printf(" - cannot fetch %s-%03d\n", txid.String(), r.Unspent_outputs[i].Tx_output_n) } } } unsp.Close() if outcnt > 0 { fmt.Printf("Total %.8f BTC in %d unspent outputs.\n", float64(sum)/1e8, outcnt) fmt.Println("The data has been stored in 'balance' folder.") fmt.Println("Use it with the wallet app to spend any of it.") } else { fmt.Println("The fateched balance is empty.") } } else { fmt.Println("Unspent json.Unmarshal", er.Error()) } } else { if er != nil { fmt.Println("Unspent ", er.Error()) } else { fmt.Println("Unspent HTTP StatusCode", r.StatusCode) } } }
func show_cached(par string) { for _, v := range network.CachedBlocks { fmt.Printf(" * %s -> %s\n", v.Hash.String(), btc.NewUint256(v.ParentHash()).String()) } }
func main() { fmt.Println("Gocoin blockchain downloader version", btc.SourcesTag) parse_command_line() setup_runtime_vars() if !add_ip_str(SeedNode) { println("You need to specify IP address of a fast seed node.") println("For example run it like this: downloader -s 89.31.102.237") return } load_ips() // other seed nodes if len(GocoinHomeDir) > 0 && GocoinHomeDir[len(GocoinHomeDir)-1] != os.PathSeparator { GocoinHomeDir += string(os.PathSeparator) } if Testnet { GocoinHomeDir += "tstnet" + string(os.PathSeparator) Magic = [4]byte{0x0B, 0x11, 0x09, 0x07} DefaultTcpPort = 18333 GenesisBlock = btc.NewUint256FromString("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943") fmt.Println("Using testnet3") } else { GocoinHomeDir += "btcnet" + string(os.PathSeparator) } fmt.Println("GocoinHomeDir:", GocoinHomeDir) utils.LockDatabaseDir(GocoinHomeDir) defer utils.UnlockDatabaseDir() StartTime = time.Now() if open_blockchain() { fmt.Printf("Blockchain opening aborted\n") close_blockchain() return } fmt.Println("Blockchain open in", time.Now().Sub(StartTime)) go do_usif() fmt.Println("Downloading headers from the seed peer", SeedNode) download_headers() if GlobalExit { close_blockchain() return } if DoThePings { fmt.Println("Tuning to other peers and trying to find the fastest ones.") fmt.Println("Execute command 'g' to continue to block chain download.") fmt.Println("Otherwise it will auto-continue after 15 minutes.") usif_prompt() do_pings() fmt.Println("Pings done.") usif_prompt() } var HighestTrustedBlock *btc.Uint256 if LastTrustedBlock == "all" { HighestTrustedBlock = TheBlockChain.BlockTreeEnd.BlockHash fmt.Println("Assume all blocks trusted") } else if LastTrustedBlock == "auto" { if LastBlockHeight > 6 { ha := BlocksToGet[LastBlockHeight] HighestTrustedBlock = btc.NewUint256(ha[:]) fmt.Println("Assume last trusted block as", HighestTrustedBlock.String()) } else { fmt.Println("-t=auto ignored since LastBlockHeight is only", LastBlockHeight) } } else if LastTrustedBlock != "" { HighestTrustedBlock = btc.NewUint256FromString(LastTrustedBlock) } if HighestTrustedBlock != nil { for k, h := range BlocksToGet { if bytes.Equal(h[:], HighestTrustedBlock.Hash[:]) { TrustUpTo = k fmt.Println("All the blocks up to", TrustUpTo, "are assumed trusted") break } } } else { fmt.Println("None of the blocks is to be assumed trusted (it will be very slow).") } for n := TheBlockChain.BlockTreeEnd; n != nil && n.Height > TheBlockChain.BlockTreeEnd.Height-BSLEN; n = n.Parent { blocksize_update(int(n.BlockSize)) } fmt.Println("Downloading blocks - BlocksToGet:", len(BlocksToGet), " avg_size:", avg_block_size()) usif_prompt() StartTime = time.Now() get_blocks() fmt.Println("Up to block", TheBlockChain.BlockTreeEnd.Height, "in", time.Now().Sub(StartTime).String()) close_all_connections() close_blockchain() return }