func raw_tx_from_file(fn string) *btc.Tx { d, er := ioutil.ReadFile(fn) if er != nil { fmt.Println(er.Error()) return nil } var dat []byte hexdump := is_hex_string(d) if len(hexdump) >= 2 || (len(hexdump)&1) == 1 { dat, _ = hex.DecodeString(hexdump) } else { if *verbose { fmt.Println("Assume binary transaction file") } dat = d } tx, txle := btc.NewTx(dat) if tx != nil && 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) var missinginp bool var totinp, totout uint64 s, missinginp, totinp, totout, er = DecodeTx(tx) if er != nil { return } network.TxMutex.Lock() if missinginp { network.TransactionsToSend[tx.Hash.Hash] = &network.OneTxToSend{Tx: tx, Data: txd, Own: 2, Firstseen: time.Now(), Volume: totout} } else { network.TransactionsToSend[tx.Hash.Hash] = &network.OneTxToSend{Tx: tx, Data: txd, Own: 1, Firstseen: time.Now(), Volume: totinp, Fee: totinp - totout} } network.TxMutex.Unlock() 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 }
// 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("TxTooBig") 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("TxBroken") return } if le != len(pl) { RejectTx(tid, len(pl), TX_REJECTED_LEN_MISMATCH) c.DoS("TxLenMismatch") return } if len(tx.TxIn) < 1 { RejectTx(tid, len(pl), TX_REJECTED_EMPTY_INPUT) c.DoS("TxNoInputs") return } tx.Hash = tid select { case NetTxs <- &TxRcvd{conn: c, tx: tx, raw: pl}: TransactionsPending[tid.BIdx()] = true default: common.CountSafe("NetTxsFULL") } }) }
func raw_tx_from_file(fn string) *btc.Tx { dat := utils.GetRawData(fn) if dat == nil { fmt.Println("Cannot fetch raw transaction data") return nil } tx, txle := btc.NewTx(dat) if tx != nil && txle != len(dat) { fmt.Println("WARNING: Raw transaction length mismatch", txle, len(dat)) } return tx }
func raw_tx_from_file(fn string) *btc.Tx { d, er := ioutil.ReadFile(fn) if er != nil { fmt.Println(er.Error()) return nil } dat, er := hex.DecodeString(string(d)) if er != nil { fmt.Println("hex.DecodeString failed - assume binary transaction file") dat = d } tx, txle := btc.NewTx(dat) if tx != nil && txle != len(dat) { fmt.Println("WARNING: Raw transaction length mismatch", txle, len(dat)) } return tx }
func load_tx(par string) { txd, er := hex.DecodeString(par) if er != nil { println(er.Error()) } tx, le := btc.NewTx(txd) if le != len(txd) { fmt.Println("WARNING: Tx length mismatch", le, len(txd)) } txid := btc.NewSha2Hash(txd) fmt.Println(len(tx.TxIn), "inputs:") var totinp, totout uint64 var missinginp bool for i := range tx.TxIn { fmt.Printf(" %3d %s", i, tx.TxIn[i].Input.String()) po, _ := BlockChain.Unspent.UnspentGet(&tx.TxIn[i].Input) if po != nil { totinp += po.Value fmt.Printf(" %15.8f BTC @ %s\n", float64(po.Value)/1e8, btc.NewAddrFromPkScript(po.Pk_script, AddrVersion).String()) } else { fmt.Println(" * no such unspent in the blockchain *") missinginp = true } } fmt.Println(len(tx.TxOut), "outputs:") for i := range tx.TxOut { totout += tx.TxOut[i].Value fmt.Printf(" %15.8f BTC to %s\n", float64(tx.TxOut[i].Value)/1e8, btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, AddrVersion).String()) } if missinginp { fmt.Println("WARNING: There are missing inputs, so you cannot calc input BTC amount") } else { fmt.Printf("%.8f BTC in -> %.8f BTC out, with %.8f BTC fee\n", float64(totinp)/1e8, float64(totout)/1e8, float64(totinp-totout)/1e8) } TransactionsToSend[txid.Hash] = txd fmt.Println("Transaction", txid.String(), "stored in the memory pool") fmt.Println("Execute 'stx " + txid.String() + "' to send it out") }
// Handle incomming "tx" msg func (c *OneConnection) ParseTxNet(pl []byte) { tid := btc.NewSha2Hash(pl) if uint32(len(pl)) > atomic.LoadUint32(&common.CFG.TXPool.MaxTxSize) { common.CountSafe("TxTooBig") TransactionsRejected[tid.BIdx()] = NewRejectedTx(tid, len(pl), TX_REJECTED_TOO_BIG) return } NeedThisTx(tid, func() { tx, le := btc.NewTx(pl) if tx == nil { common.CountSafe("TxParseError") TransactionsRejected[tid.BIdx()] = NewRejectedTx(tid, len(pl), TX_REJECTED_FORMAT) c.DoS() return } if le != len(pl) { common.CountSafe("TxParseLength") TransactionsRejected[tid.BIdx()] = NewRejectedTx(tid, len(pl), TX_REJECTED_LEN_MISMATCH) c.DoS() return } if len(tx.TxIn) < 1 { common.CountSafe("TxParseEmpty") TransactionsRejected[tid.BIdx()] = NewRejectedTx(tid, len(pl), TX_REJECTED_EMPTY_INPUT) c.DoS() return } tx.Hash = tid select { case NetTxs <- &TxRcvd{conn: c, tx: tx, raw: pl}: TransactionsPending[tid.Hash] = true default: common.CountSafe("NetTxsFULL") } }) }
// load the content of the "balance/" folder func load_balance() { var unknownInputs int f, e := os.Open("balance/unspent.txt") if e != nil { println(e.Error()) os.Exit(1) } rd := bufio.NewReader(f) for { l, _, e := rd.ReadLine() if len(l) == 0 && e != nil { break } if l[64] == '-' { txid := btc.NewUint256FromString(string(l[:64])) rst := strings.SplitN(string(l[65:]), " ", 2) vout, _ := strconv.ParseUint(rst[0], 10, 32) uns := new(btc.TxPrevOut) copy(uns.Hash[:], txid.Hash[:]) uns.Vout = uint32(vout) lab := "" if len(rst) > 1 { lab = rst[1] } if _, ok := loadedTxs[txid.Hash]; !ok { tf, _ := os.Open("balance/" + txid.String() + ".tx") if tf != nil { siz, _ := tf.Seek(0, os.SEEK_END) tf.Seek(0, os.SEEK_SET) buf := make([]byte, siz) tf.Read(buf) tf.Close() th := btc.Sha2Sum(buf) if bytes.Equal(th[:], txid.Hash[:]) { tx, _ := btc.NewTx(buf) if tx != nil { loadedTxs[txid.Hash] = tx } else { println("transaction is corrupt:", txid.String()) } } else { println("transaction file is corrupt:", txid.String()) os.Exit(1) } } else { println("transaction file not found:", txid.String()) os.Exit(1) } } uo := UO(uns) fnd := false for j := range publ_addrs { if publ_addrs[j].Owns(uo.Pk_script) { unspentOuts = append(unspentOuts, uns) unspentOutsLabel = append(unspentOutsLabel, lab) totBtc += UO(uns).Value fnd = true break } } if !fnd { unknownInputs++ if *verbose { fmt.Println(uns.String(), "does not belogn to your wallet - ignore it") } } } } f.Close() fmt.Printf("You have %.8f BTC in %d unspent outputs\n", float64(totBtc)/1e8, len(unspentOuts)) if unknownInputs > 0 { fmt.Printf("WARNING: Some inputs (%d) cannot be spent (-v to print them)\n", unknownInputs) } }
// load the content of the "balance/" folder func load_balance(showbalance bool) { var unknownInputs, multisigInputs int f, e := os.Open("balance/unspent.txt") if e != nil { println(e.Error()) return } rd := bufio.NewReader(f) for { l, _, e := rd.ReadLine() if len(l) == 0 && e != nil { break } if l[64] == '-' { txid := btc.NewUint256FromString(string(l[:64])) rst := strings.SplitN(string(l[65:]), " ", 2) vout, _ := strconv.ParseUint(rst[0], 10, 32) uns := new(btc.TxPrevOut) copy(uns.Hash[:], txid.Hash[:]) uns.Vout = uint32(vout) lab := "" if len(rst) > 1 { lab = rst[1] } if _, ok := loadedTxs[txid.Hash]; !ok { tf, _ := os.Open("balance/" + txid.String() + ".tx") if tf != nil { siz, _ := tf.Seek(0, os.SEEK_END) tf.Seek(0, os.SEEK_SET) buf := make([]byte, siz) tf.Read(buf) tf.Close() th := btc.Sha2Sum(buf) if bytes.Equal(th[:], txid.Hash[:]) { tx, _ := btc.NewTx(buf) if tx != nil { loadedTxs[txid.Hash] = tx } else { println("transaction is corrupt:", txid.String()) } } else { println("transaction file is corrupt:", txid.String()) os.Exit(1) } } else { println("transaction file not found:", txid.String()) os.Exit(1) } } unspentOuts = append(unspentOuts, uns) unspentOutsLabel = append(unspentOutsLabel, lab) // Sum up all the balance and check if we have private key for this input uo := UO(uns) totBtc += UO(uns).Value if !btc.IsP2SH(uo.Pk_script) { fnd := false for j := range publ_addrs { if publ_addrs[j].Owns(uo.Pk_script) { fnd = true break } } if showbalance && !fnd { unknownInputs++ if *verbose { ss := uns.String() ss = ss[:8] + "..." + ss[len(ss)-12:] fmt.Println(ss, "does not belong to your wallet (cannot sign it)") } } } else { if *verbose { ss := uns.String() ss = ss[:8] + "..." + ss[len(ss)-12:] fmt.Println(ss, "belongs to a multisig address") } multisigInputs++ } } } f.Close() fmt.Printf("You have %.8f BTC in %d unspent outputs. %d inputs are multisig type\n", float64(totBtc)/1e8, len(unspentOuts), multisigInputs) if showbalance { if unknownInputs > 0 { fmt.Printf("WARNING: Some inputs (%d) cannot be spent with this password (-v to print them)\n", unknownInputs) } } }
// load the content of the "balance/" folder func load_balance(showbalance bool) { var unknownInputs, multisigInputs int f, e := os.Open("balance/unspent.txt") if e != nil { println(e.Error()) return } rd := bufio.NewReader(f) for { l, _, e := rd.ReadLine() if len(l) == 0 && e != nil { break } if l[64] == '-' { txid := btc.NewUint256FromString(string(l[:64])) rst := strings.SplitN(string(l[65:]), " ", 2) vout, _ := strconv.ParseUint(rst[0], 10, 32) uns := new(btc.TxPrevOut) copy(uns.Hash[:], txid.Hash[:]) uns.Vout = uint32(vout) lab := "" if len(rst) > 1 { lab = rst[1] } str := string(l) if sti := strings.Index(str, "_StealthC:"); sti != -1 { c, e := hex.DecodeString(str[sti+10 : sti+10+64]) if e != nil { fmt.Println("ERROR at stealth", txid.String(), vout, e.Error()) } else { // add a new key to the wallet sec := btc.DeriveNextPrivate(first_seed[:], c) is_stealth[len(priv_keys)] = true priv_keys = append(priv_keys, sec) labels = append(labels, lab) pub_key := btc.PublicFromPrivate(sec, true) publ_addrs = append(publ_addrs, btc.NewAddrFromPubkey(pub_key, btc.AddrVerPubkey(*testnet))) compressed_key = append(compressed_key, true) // stealth keys are always compressed } } if _, ok := loadedTxs[txid.Hash]; !ok { tf, _ := os.Open("balance/" + txid.String() + ".tx") if tf != nil { siz, _ := tf.Seek(0, os.SEEK_END) tf.Seek(0, os.SEEK_SET) buf := make([]byte, siz) tf.Read(buf) tf.Close() th := btc.Sha2Sum(buf) if bytes.Equal(th[:], txid.Hash[:]) { tx, _ := btc.NewTx(buf) if tx != nil { loadedTxs[txid.Hash] = tx } else { println("transaction is corrupt:", txid.String()) } } else { println("transaction file is corrupt:", txid.String()) os.Exit(1) } } else { println("transaction file not found:", txid.String()) os.Exit(1) } } // Sum up all the balance and check if we have private key for this input uo := UO(uns) add_it := true if !btc.IsP2SH(uo.Pk_script) { fnd := false for j := range publ_addrs { if publ_addrs[j].Owns(uo.Pk_script) { fnd = true break } } if !fnd { if *onlvalid { add_it = false } if showbalance { unknownInputs++ if *verbose { ss := uns.String() ss = ss[:8] + "..." + ss[len(ss)-12:] fmt.Println(ss, "does not belong to your wallet (cannot sign it)") } } } } else { if *onlvalid { add_it = false } if *verbose { ss := uns.String() ss = ss[:8] + "..." + ss[len(ss)-12:] fmt.Println(ss, "belongs to a multisig address") } multisigInputs++ } if add_it { unspentOuts = append(unspentOuts, uns) unspentOutsLabel = append(unspentOutsLabel, lab) totBtc += UO(uns).Value } } } f.Close() fmt.Printf("You have %.8f BTC in %d unspent outputs. %d inputs are multisig type\n", float64(totBtc)/1e8, len(unspentOuts), multisigInputs) if showbalance { if unknownInputs > 0 { fmt.Printf("WARNING: Some inputs (%d) cannot be spent with this password (-v to print them)\n", unknownInputs) } } }