func addTxOuts(msgtx *wire.MsgTx, b balance, hash []byte, blockHeight uint32) error { anchorHash, err := prependBlockHeight(blockHeight, hash) if err != nil { anchorLog.Errorf("ScriptBuilder error: %v\n", err) } builder := txscript.NewScriptBuilder() builder.AddOp(txscript.OP_RETURN) builder.AddData(anchorHash) // latest routine from Conformal btcsuite returns 2 parameters, not 1... not sure what to do for people with the old conformal libraries :( opReturn, err := builder.Script() msgtx.AddTxOut(wire.NewTxOut(0, opReturn)) if err != nil { anchorLog.Errorf("ScriptBuilder error: %v\n", err) } amount, _ := btcutil.NewAmount(b.unspentResult.Amount) change := amount - fee // Check if there are leftover unspent outputs, and return coins back to // a new address we own. if change > 0 { // Spend change. pkScript, err := txscript.PayToAddrScript(b.address) if err != nil { return fmt.Errorf("cannot create txout script: %s", err) } msgtx.AddTxOut(wire.NewTxOut(int64(change), pkScript)) } return nil }
func initWallet() error { balances = make([]balance, 0, 200) fee, _ = btcutil.NewAmount(cfg.Btc.BtcTransFee) walletLocked = true err := updateUTXO() if err == nil && len(balances) > 0 { defaultAddress = balances[0].address } return err }
// InitAnchor inits rpc clients for factom // and load up unconfirmed DirBlockInfo from leveldb func InitAnchor(s interfaces.IState) (*Anchor, error) { anchorLog.Debug("InitAnchor") a := NewAnchor() a.state = s a.db = s.GetDB() a.minBalance, _ = btcutil.NewAmount(0.01) var err error a.dirBlockInfoSlice, err = a.db.FetchAllUnconfirmedDirBlockInfos() if err != nil { anchorLog.Error("InitAnchor error - " + err.Error()) return nil, err } anchorLog.Debug("init dirBlockInfoSlice.len=", len(a.dirBlockInfoSlice)) // this might take a while to check missing DirBlockInfo for existing DirBlocks in database //TODO: handle concurrance better go a.checkMissingDirBlockInfo() a.readConfig() if err = a.InitRPCClient(); err != nil { anchorLog.Error(err.Error()) } else { a.updateUTXO(a.minBalance) } ticker0 := time.NewTicker(time.Minute * time.Duration(1)) go func() { for _ = range ticker0.C { a.checkForAnchor() } }() ticker := time.NewTicker(time.Minute * time.Duration(a.tenMinutes)) go func() { for _ = range ticker.C { anchorLog.Info("In 10 minutes ticker...") a.readConfig() if a.dclient == nil || a.wclient == nil { if err = a.InitRPCClient(); err != nil { anchorLog.Error(err.Error()) } } if a.wclient != nil { a.checkTxConfirmations() } } }() return a, nil }
func initWallet() error { balances = make([]balance, 0, 100) fee, _ = btcutil.NewAmount(cfg.Btc.BtcTransFee) err := unlockWallet(int64(600)) if err != nil { return fmt.Errorf("%s", err) } unspentResults, err := wclient.ListUnspent() //minConf=1 if err != nil { return fmt.Errorf("cannot list unspent. %s", err) } anchorLog.Info("unspentResults.len=", len(unspentResults)) if len(unspentResults) > 0 { var i int for _, b := range unspentResults { if b.Amount > fee.ToBTC() { balances = append(balances, balance{unspentResult: b}) i++ } } } anchorLog.Info("balances.len=", len(balances)) for i, b := range balances { addr, err := btcutil.DecodeAddress(b.unspentResult.Address, &chaincfg.TestNet3Params) if err != nil { return fmt.Errorf("cannot decode address: %s", err) } balances[i].address = addr wif, err := wclient.DumpPrivKey(addr) if err != nil { return fmt.Errorf("cannot get WIF: %s", err) } balances[i].wif = wif anchorLog.Info("balance[%d]=%s", i, spew.Sdump(balances[i])) } time.Sleep(1 * time.Second) return nil }
func (a *Anchor) readConfig() { anchorLog.Info("readConfig") a.cfg = util.ReadConfig("") a.confirmationsNeeded = a.cfg.Anchor.ConfirmationsNeeded a.fee, _ = btcutil.NewAmount(a.cfg.Btc.BtcTransFee) var err error a.serverPrivKey, err = primitives.NewPrivateKeyFromHex(a.cfg.App.LocalServerPrivKey) if err != nil { panic("Cannot parse Server Private Key from configuration file: " + err.Error()) } a.serverECKey, err = primitives.NewPrivateKeyFromHex(a.cfg.Anchor.ServerECPrivKey) if err != nil { panic("Cannot parse Server EC Key from configuration file: " + err.Error()) } a.anchorChainID, err = primitives.HexToHash(a.cfg.Anchor.AnchorChainID) anchorLog.Debug("anchorChainID: ", a.anchorChainID) if err != nil || a.anchorChainID == nil { panic("Cannot parse Server AnchorChainID from configuration file: " + err.Error()) } }
func selectInputs(eligible []btcjson.ListUnspentResult, minconf int) (selected []btcjson.ListUnspentResult, out btcutil.Amount, err error) { // Iterate throguh eligible transactions, appending to outputs and // increasing out. This is finished when out is greater than the // requested amt to spend. selected = make([]btcjson.ListUnspentResult, 0, len(eligible)) for _, e := range eligible { amount, err := btcutil.NewAmount(e.Amount) if err != nil { anchorLog.Error("err in creating NewAmount") continue } selected = append(selected, e) out += amount if out >= fee { return selected, out, nil } } if out < fee { return nil, 0, fmt.Errorf("insufficient funds: transaction requires %v fee, but only %v spendable", fee, out) } return selected, out, nil }