// Seals the current open block, store it in db and create the next open block func newFactoidBlock(chain *common.FctChain) block.IFBlock { older := FactoshisPerCredit cfg := util.ReReadConfig() FactoshisPerCredit = cfg.App.ExchangeRate rate := fmt.Sprintf("Current Exchange rate is %v", strings.TrimSpace(fct.ConvertDecimal(FactoshisPerCredit))) if older != FactoshisPerCredit { orate := fmt.Sprintf("The Exchange rate was %v\n", strings.TrimSpace(fct.ConvertDecimal(older))) cp.CP.AddUpdate( "Fee", // tag "status", // Category "Entry Credit Exchange Rate Changed", // Title orate+rate, 0) } else { cp.CP.AddUpdate( "Fee", // tag "status", // Category "Entry Credit Exchange Rate", // Title rate, 0) } // acquire the last block currentBlock := chain.NextBlock if chain.NextBlockHeight != dchain.NextDBHeight { panic("Factoid Block height does not match Directory Block height:" + strconv.Itoa(int(dchain.NextDBHeight))) } chain.BlockMutex.Lock() chain.NextBlockHeight++ common.FactoidState.SetFactoshisPerEC(FactoshisPerCredit) common.FactoidState.ProcessEndOfBlock2(chain.NextBlockHeight) chain.NextBlock = common.FactoidState.GetCurrentBlock() chain.BlockMutex.Unlock() //Store the block in db db.ProcessFBlockBatch(currentBlock) procLog.Infof("Factoid chain: block " + strconv.FormatUint(uint64(currentBlock.GetDBHeight()), 10) + " created for chain: " + chain.ChainID.String()) return currentBlock }
func (b FBlock) ValidateTransaction(index int, trans fct.ITransaction) error { // Calculate the fee due. { err := trans.Validate(index) if err != nil { return err } } //Ignore coinbase transaction's signatures if len(b.Transactions) > 0 { err := trans.ValidateSignatures() if err != nil { return err } } fee, err := trans.CalculateFee(b.ExchRate) if err != nil { return err } tin, err := trans.TotalInputs() if err != nil { return err } tout, err := trans.TotalOutputs() if err != nil { return err } tec, err := trans.TotalECs() if err != nil { return err } sum, err := fct.ValidateAmounts(tout, tec, fee) if err != nil { return err } if tin < sum { return fmt.Errorf("The inputs %s do not cover the outputs %s,\n"+ "the Entry Credit outputs %s, and the required fee %s", strings.TrimSpace(fct.ConvertDecimal(tin)), strings.TrimSpace(fct.ConvertDecimal(tout)), strings.TrimSpace(fct.ConvertDecimal(tec)), strings.TrimSpace(fct.ConvertDecimal(fee))) } return nil }
func HandleGetFee(ctx *web.Context, k string) { var trans fct.ITransaction var err error key := ctx.Params["key"] fmt.Println("getfee", key) if len(key) > 0 { trans, err = getTransaction(ctx, key) if err != nil { reportResults(ctx, "Failure to locate the transaction", false) return } } fee, err := Wallet.GetFee() if err != nil { reportResults(ctx, err.Error(), false) return } if trans != nil { ufee, _ := trans.CalculateFee(uint64(fee)) fee = int64(ufee) } reportResults(ctx, fmt.Sprintf("%s", strings.TrimSpace(fct.ConvertDecimal(uint64(fee)))), true) }
func currRate(w http.ResponseWriter, r *http.Request) { v, err := GetRate(myState) if err != nil { fmt.Println(err) return } w.Write([]byte(fct.ConvertDecimal(uint64(v)))) }
func HandleFactoidSubFee(ctx *web.Context, parms string) { trans, key, _, address, _, ok := getParams_(ctx, parms, false) if !ok { return } name := ctx.Params["name"] // This is the name the user used. { ins, err := trans.TotalInputs() if err != nil { reportResults(ctx, err.Error(), false) return } outs, err := trans.TotalOutputs() if err != nil { reportResults(ctx, err.Error(), false) return } ecs, err := trans.TotalECs() if err != nil { reportResults(ctx, err.Error(), false) return } if ins != outs+ecs { msg := fmt.Sprintf( "Subfee requires that all the inputs balance the outputs.\n"+ "The total inputs of your transaction are %s\n"+ "The total outputs + ecoutputs of your transaction are %s", fct.ConvertDecimal(ins), fct.ConvertDecimal(outs+ecs)) reportResults(ctx, msg, false) return } } transfee, err := Wallet.FactoidSubFee(trans, key, address, name) if err != nil { reportResults(ctx, err.Error(), false) return } reportResults(ctx, fmt.Sprintf("Subtracted %s from %s", fct.ConvertDecimal(uint64(transfee)), name), true) return }
func GetAddresses() []byte { values := Wallet.GetAddresses() ecKeys := make([]string, 0, len(values)) fctKeys := make([]string, 0, len(values)) ecBalances := make([]string, 0, len(values)) fctBalances := make([]string, 0, len(values)) fctAddresses := make([]string, 0, len(values)) ecAddresses := make([]string, 0, len(values)) var maxlen int for _, we := range values { if len(we.GetName()) > maxlen { maxlen = len(we.GetName()) } var adr string if we.GetType() == "ec" { address, err := we.GetAddress() if err != nil { continue } adr = fct.ConvertECAddressToUserStr(address) ecAddresses = append(ecAddresses, adr) ecKeys = append(ecKeys, string(we.GetName())) bal, _ := ECBalance(adr) ecBalances = append(ecBalances, strconv.FormatInt(bal, 10)) } else { address, err := we.GetAddress() if err != nil { continue } adr = fct.ConvertFctAddressToUserStr(address) fctAddresses = append(fctAddresses, adr) fctKeys = append(fctKeys, string(we.GetName())) bal, _ := FctBalance(adr) sbal := fct.ConvertDecimal(uint64(bal)) fctBalances = append(fctBalances, sbal) } } var out bytes.Buffer if len(fctKeys) > 0 { out.WriteString("\n Factoid Addresses\n\n") } fstr := fmt.Sprintf("%s%vs %s38s %s14s\n", "%", maxlen+4, "%", "%") for i, key := range fctKeys { str := fmt.Sprintf(fstr, key, fctAddresses[i], fctBalances[i]) out.WriteString(str) } if len(ecKeys) > 0 { out.WriteString("\n Entry Credit Addresses\n\n") } for i, key := range ecKeys { str := fmt.Sprintf(fstr, key, ecAddresses[i], ecBalances[i]) out.WriteString(str) } return out.Bytes() }
func fctbalance(addr string) error { if Utility.IsValidAddress(addr) && strings.HasPrefix(addr, "EC") { fmt.Println("Not a valid Entry Credit Address") return fmt.Errorf("Not a valid Entry Credit Address") } if b, err := factom.FctBalance(addr); err != nil { fmt.Println("Address undefined or invalid: " + err.Error()) return err } else { fmt.Println("Balance of ", addr, " = ", fct.ConvertDecimal(uint64(b))) } return nil }
func fctproperties(args []string) { getproperties := fmt.Sprintf("http://%s/v1/properties/", serverFct) resp, err := http.Get(getproperties) if err != nil { fmt.Println("Get Properties failed") os.Exit(1) } body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Failed to understand response from fctwallet") os.Exit(1) } resp.Body.Close() // We pull the fee. If the fee isn't positive, or if we fail to marshal, then there is a failure type x struct { Response string Success bool } b := new(x) if err := json.Unmarshal(body, b); err != nil { fmt.Println(err) os.Exit(1) } else if !b.Success { fmt.Println(b.Response) os.Exit(1) } top := Version / 1000000 mid := (Version % 1000000) / 1000 low := Version % 1000 ret := b.Response + fmt.Sprintf("factom-cli Version: %d.%d.%d\n", top, mid, low) total, err := Utility.TotalFactoids() if err == nil { ret = ret + fmt.Sprintf(" Total Factoids: %s", strings.TrimSpace(fct.ConvertDecimal(total))) } fmt.Println(ret) }
func showFee(txKey string) []byte { ib := myState.GetFS().GetDB().GetRaw([]byte(fct.DB_BUILD_TRANS), []byte(txKey)) trans, ok := ib.(fct.ITransaction) if ib != nil && ok { v, err := GetRate(myState) if err != nil { fmt.Println(err) return []byte("...") } fee, err := trans.CalculateFee(uint64(v)) if err != nil { fmt.Println(err) return []byte("...") } return []byte(strings.TrimSpace(fct.ConvertDecimal(fee))) } else { return []byte("...") } }
func reqFee(w http.ResponseWriter, r *http.Request) { txKey := r.FormValue("key") ib := myState.GetFS().GetDB().GetRaw([]byte(fct.DB_BUILD_TRANS), []byte(txKey)) trans, ok := ib.(fct.ITransaction) if ib != nil && ok { v, err := GetRate(myState) if err != nil { fmt.Println(err) return } fee, err := trans.CalculateFee(uint64(v)) if err != nil { fmt.Println(err) return } w.Write([]byte(strings.TrimSpace(fct.ConvertDecimal(fee)))) } else { w.Write([]byte("...")) } }
func (Balance) Execute(state IState, args []string) (err error) { if len(args) != 3 { return fmt.Errorf("Wrong number of parameters") } var bal int64 switch strings.ToLower(args[1]) { case "ec": bal, err = ECBalance(state, args[2]) case "fct": bal, err = FctBalance(state, args[2]) default: return fmt.Errorf("Invalid parameters") } if err != nil { return err } if args[1] == "fct" { fmt.Println(args[2], "=", fct.ConvertDecimal(uint64(bal))) } else { fmt.Println(args[2], "=", bal) } return nil }
func GetBalances(state IState) []byte { keys, values := state.GetFS().GetDB().GetKeysValues([]byte(fct.W_NAME)) ecKeys := make([]string, 0, len(keys)) fctKeys := make([]string, 0, len(keys)) ecBalances := make([]string, 0, len(keys)) fctBalances := make([]string, 0, len(keys)) fctAddresses := make([]string, 0, len(keys)) ecAddresses := make([]string, 0, len(keys)) var maxlen int var connect = true for i, k := range keys { if len(k) > maxlen { maxlen = len(k) } we, ok := values[i].(wallet.IWalletEntry) if !ok { panic("Get Addresses finds the database corrupt. Shouldn't happen") } var adr string if we.GetType() == "ec" { address, err := we.GetAddress() if err != nil { continue } adr = fct.ConvertECAddressToUserStr(address) ecAddresses = append(ecAddresses, adr) ecKeys = append(ecKeys, string(k)) bal, err := ECBalance(state, adr) if err != nil { connect = false } if connect { ecBalances = append(ecBalances, strconv.FormatInt(bal, 10)) } else { ecBalances = append(ecBalances, "-") } } else { address, err := we.GetAddress() if err != nil { continue } adr = fct.ConvertFctAddressToUserStr(address) fctAddresses = append(fctAddresses, adr) fctKeys = append(fctKeys, string(k)) bal, err := FctBalance(state, adr) if err != nil { connect = false } sbal := fct.ConvertDecimal(uint64(bal)) if connect { fctBalances = append(fctBalances, sbal) } else { fctBalances = append(fctBalances, "-") } } } var out bytes.Buffer if len(fctKeys) > 0 { out.WriteString("\n Factoid Addresses\n\n") } fstr := fmt.Sprintf("%s%vs %s38s %s14s\n", "%", maxlen+4, "%", "%") for i, key := range fctKeys { str := fmt.Sprintf(fstr, key, fctAddresses[i], fctBalances[i]) out.WriteString(str) } if len(ecKeys) > 0 { out.WriteString("\n Entry Credit Addresses\n\n") } for i, key := range ecKeys { str := fmt.Sprintf(fstr, key, ecAddresses[i], ecBalances[i]) out.WriteString(str) } if !connect { out.WriteString("Balances are unavailable; Wallet is offline\n") } return out.Bytes() }
func (AddFee) Execute(state IState, args []string) (err error) { if len(args) != 3 && len(args) != 4 { return fmt.Errorf("Invalid Parameters") } key := args[1] adr := args[2] rate := int64(0) if len(args) == 4 { srate, err := fct.ConvertFixedPoint(args[3]) if err != nil { return fmt.Errorf("Could not parse exchange rate: %v", err) } rate, err = strconv.ParseInt(srate, 10, 64) } else { if rate, err = GetRate(state); err != nil { return fmt.Errorf("Could not reach the server to get the exchange rate") } } ib := state.GetFS().GetDB().GetRaw([]byte(fct.DB_BUILD_TRANS), []byte(key)) trans, ok := ib.(fct.ITransaction) if ib == nil || !ok { return fmt.Errorf("Unknown Transaction") } var addr fct.IAddress if fct.ValidateFUserStr(adr) { addr = fct.NewAddress(fct.ConvertUserStrToAddress(adr)) } else if Utility.IsValidHexAddress(adr) { badr, _ := hex.DecodeString(adr) addr = fct.NewAddress(badr) } else if Utility.IsValidNickname(adr) { we := state.GetFS().GetDB().GetRaw([]byte(fct.W_NAME), []byte(adr)) if we != nil { we2 := we.(wallet.IWalletEntry) addr, _ = we2.GetAddress() adr = hex.EncodeToString(addr.Bytes()) } else { return fmt.Errorf("Name is undefined.") } } fee, err := trans.CalculateFee(uint64(rate)) var tin, tout, tec uint64 if tin, err = trans.TotalInputs(); err != nil { return err } if tout, err = trans.TotalOutputs(); err != nil { return err } if tec, err = trans.TotalECs(); err != nil { return err } if tin != tout+tec { msg := fmt.Sprintf("%s Total Inputs\n", fct.ConvertDecimal(tin)) msg += fmt.Sprintf("%s Total Outputs and Entry Credits\n", fct.ConvertDecimal(tout+tec)) msg += fmt.Sprintf("\nThe Inputs must match the outputs to use AddFee to add the fee to an input") return fmt.Errorf(msg) } for _, input := range trans.GetInputs() { if bytes.Equal(input.GetAddress().Bytes(), addr.Bytes()) { input.SetAmount(input.GetAmount() + fee) fmt.Printf("Added fee of %v\n", strings.TrimSpace(fct.ConvertDecimal(fee))) break } } return nil }
func (fs *Test_state) newTransaction() fct.ITransaction { var maxBal, sum uint64 fs.inputAddresses = make([]fct.IAddress, 0, 20) for _, output := range fs.outputAddresses { bal := fs.GetBalance(output) if bal > 100000000 { fs.inputAddresses = append(fs.inputAddresses, output) sum += bal } if maxBal < bal { maxBal = bal } } avgBal := sum / uint64(len(fs.inputAddresses)) if fs.stats.transactions == 0 { fs.stats.MaxBal = maxBal fs.stats.AvgBal = avgBal } else { fs.stats.MaxBal = (fs.stats.MaxBal*uint64(fs.stats.transactions) + maxBal) / uint64(fs.stats.transactions+1) fs.stats.AvgBal = (fs.stats.AvgBal*uint64(fs.stats.transactions) + avgBal) / uint64(fs.stats.transactions+1) } cp.CP.AddUpdate( "Test max min inputs", // tag "info", // Category "Tests generation", // Title fmt.Sprintf("Input Addresses %d\n"+ "Total Max balance %15s, Average Balance %15s\n"+ "Last Max balance %15s, Average Balance %16s", len(fs.inputAddresses), strings.TrimSpace(fct.ConvertDecimal(fs.stats.MaxBal)), strings.TrimSpace(fct.ConvertDecimal(fs.stats.AvgBal)), strings.TrimSpace(fct.ConvertDecimal(maxBal)), strings.TrimSpace(fct.ConvertDecimal(avgBal))), // Msg 0) // Expire // The following code is a function that creates an array // of addresses pulled from some source array of addresses // selected randomly. var makeList = func(source []fct.IAddress, cnt int) []fct.IAddress { adrs := make([]fct.IAddress, 0, cnt) for len(adrs) < cnt { var i int if len(source) == 0 { return adrs } i = rand.Int() % len(source) adr := source[i] adrs = append(adrs, adr) } return adrs } // Get one to five inputs, and one to five outputs numInputs := fs.getRnd() numOutputs := fs.getRnd() mumECOutputs := fs.getRnd() if avgBal > 10000000000 { numOutputs = 0 } // Throw away Factoids if too much money in the system lim := len(fs.inputAddresses) - 2 if lim <= 0 { lim = 1 } numInputs = (numInputs % (lim)) + 1 // fmt.Println("inputs outputs",numInputs,numOutputs, "limits",len(fs.inputAddresses),len(fs.outputAddresses)) // Get my input and output addresses inputs := makeList(fs.inputAddresses, numInputs) outputs := makeList(fs.outputAddresses, numOutputs) ecoutputs := makeList(fs.ecoutputAddresses, mumECOutputs) var paid uint64 t := fs.twallet.CreateTransaction(fs.GetTimeMilli()) for _, adr := range inputs { balance := fs.GetBalance(adr) toPay := uint64(rand.Int63()) % (balance / 2) paid = toPay + paid fs.twallet.AddInput(t, adr, toPay) } paid = paid - fs.GetFactoshisPerEC()*uint64(len(ecoutputs)) for _, adr := range outputs { fs.twallet.AddOutput(t, adr, paid/uint64(len(outputs))) } for _, adr := range ecoutputs { fs.twallet.AddECOutput(t, adr, fs.GetFactoshisPerEC()) } fee, _ := t.CalculateFee(fs.GetFactoshisPerEC()) toPay := t.GetInputs()[0].GetAmount() fs.twallet.UpdateInput(t, 0, inputs[0], toPay+fee) valid, err1 := fs.twallet.SignInputs(t) if err1 != nil { fct.Prtln("Failed to sign transaction") } if !valid { fct.Prtln("Transaction is not valid") } if err := fs.Validate(len(fs.GetCurrentBlock().GetTransactions()), t); err != nil || err1 != nil { fs.GetDB().Put(fct.DB_BAD_TRANS, t.GetHash(), t) fs.stats.badAddresses += 1 str := []byte(err.Error())[:10] if bytes.Compare(str, []byte("The inputs")) != 0 { str = []byte(err.Error())[:30] } fs.stats.errors[string(str)] += 1 fs.stats.full[string(str)] = err.Error() return fs.newTransaction() } return t }
// Specifying a fee overrides either not being connected, or the current fee. // Params: // key (limit printout to this key) // fee (specify the transation fee) func GetTransactions(ctx *web.Context) ([]byte, error) { connected := true var _ = connected exch, err := GetFee(ctx) // The Fee will be zero if we have no connection. if err != nil { connected = false } keys, transactions, err := Wallet.GetTransactions() if err != nil { return nil, err } var out bytes.Buffer for i, trans := range transactions { fee, _ := trans.CalculateFee(uint64(exch)) cprt := "" cin, err := trans.TotalInputs() if err != nil { cprt = cprt + err.Error() } cout, err := trans.TotalOutputs() if err != nil { cprt = cprt + err.Error() } cecout, err := trans.TotalECs() if err != nil { cprt = cprt + err.Error() } if len(cprt) == 0 { v := int64(cin) - int64(cout) - int64(cecout) sign := "" if v < 0 { sign = "-" v = -v } cprt = fmt.Sprintf(" Currently will pay: %s%s", sign, strings.TrimSpace(fct.ConvertDecimal(uint64(v)))) if sign == "-" || fee > uint64(v) { cprt = cprt + "\n\nWARNING: Currently your transaction fee may be too low" } } out.WriteString(fmt.Sprintf("%s: Fee Due: %s %s\n\n%s\n", strings.TrimSpace(strings.TrimRight(string(keys[i]), "\u0000")), strings.TrimSpace(fct.ConvertDecimal(fee)), cprt, transactions[i].String())) } output := out.Bytes() // now look for the addresses, and replace them with our names. (the transactions // in flight also have a Factom address... We leave those alone. names, vs := Wallet.GetWalletNames() for i, name := range names { we, ok := vs[i].(wallet.IWalletEntry) if !ok { return nil, fmt.Errorf("Database is corrupt") } address, err := we.GetAddress() if err != nil { continue } // We shouldn't get any of these, but ignore them if we do. adrstr := []byte(hex.EncodeToString(address.Bytes())) output = bytes.Replace(output, adrstr, name, -1) } return output, nil }
func (fs *Test_state) newTransaction(maxIn, maxOut int) fct.ITransaction { var max, max2 uint64 fs.inputAddresses = make([]fct.IAddress, 0, 20) for _, output := range fs.outputAddresses { bal := fs.GetBalance(output) if bal > 1000000000 { fs.inputAddresses = append(fs.inputAddresses, output) } if max < bal { max2 = max max = bal } else { if max2 < bal { max2 = bal } } } fmt.Printf("\033[35;0H Inputs %4d, Max %20s Max2 %20s ", len(fs.inputAddresses), strings.TrimSpace(fct.ConvertDecimal(max)), strings.TrimSpace(fct.ConvertDecimal(max2))) fmt.Print("\033[40;0H") // The following code is a function that creates an array // of addresses pulled from some source array of addresses // selected randomly. var makeList = func(source []fct.IAddress, cnt int) []fct.IAddress { adrs := make([]fct.IAddress, 0, cnt) for len(adrs) < cnt { i := rand.Int() % len(source) adr := source[i] adrs = append(adrs, adr) } return adrs } mIn := maxIn mOut := maxOut joker := rand.Int() % 100 if joker < 1 { mIn = maxIn * 100 } joker = rand.Int() % 100 if joker < 1 { mOut = maxOut * 200 } // Get one to five inputs, and one to five outputs numInputs := rand.Int()%mIn + 1 numOutputs := rand.Int() % mOut mumECOutputs := rand.Int() % mOut numInputs = (numInputs % (len(fs.inputAddresses) - 2)) + 1 // fmt.Println("inputs outputs",numInputs,numOutputs, "limits",len(fs.inputAddresses),len(fs.outputAddresses)) // Get my input and output addresses inputs := makeList(fs.inputAddresses, numInputs) outputs := makeList(fs.outputAddresses, numOutputs) ecoutputs := makeList(fs.ecoutputAddresses, mumECOutputs) var paid uint64 t := fs.twallet.CreateTransaction(fs.GetTimeMilli()) for _, adr := range inputs { balance := fs.GetBalance(adr) toPay := uint64(rand.Int63()) % (balance) paid = toPay + paid fs.twallet.AddInput(t, adr, toPay) //fmt.Print("\033[10;3H") //fmt.Printf("%s %s \n",adr.String(),fct.ConvertDecimal(toPay)) //fmt.Print("\033[40;3H") } paid = paid - fs.GetFactoshisPerEC()*uint64(len(ecoutputs)) for _, adr := range outputs { fs.twallet.AddOutput(t, adr, paid/uint64(len(outputs))) } for _, adr := range ecoutputs { fs.twallet.AddECOutput(t, adr, fs.GetFactoshisPerEC()) } fee, _ := t.CalculateFee(fs.GetFactoshisPerEC()) toPay := t.GetInputs()[0].GetAmount() fs.twallet.UpdateInput(t, 0, inputs[0], toPay+fee) valid, err1 := fs.twallet.SignInputs(t) if err1 != nil { fct.Prtln("Failed to sign transaction") } if !valid { fct.Prtln("Transaction is not valid") } if err := fs.Validate(t); err != nil || err1 != nil { fs.GetDB().Put(fct.DB_BAD_TRANS, t.GetHash(), t) fs.stats.badAddresses += 1 str := []byte(err.Error())[:10] if bytes.Compare(str, []byte("The inputs")) != 0 { str = []byte(err.Error())[:30] } fs.stats.errors[string(str)] += 1 fs.stats.full[string(str)] = err.Error() fmt.Print("\033[32;0H") fmt.Println("Bad Transactions: ", fs.stats.badAddresses, "\r") fmt.Print("\033[40;0H") return fs.newTransaction(maxIn, maxOut) } return t }
func (fs *Test_state) newTransaction(maxIn, maxOut int) fct.ITransaction { var max, sum uint64 fs.inputAddresses = make([]fct.IAddress, 0, 20) for _, output := range fs.outputAddresses { bal := fs.GetBalance(output) if bal > 10000000 { fs.inputAddresses = append(fs.inputAddresses, output) sum += bal } if max < bal { max = bal } } cp.CP.AddUpdate( "Test max min inputs", // tag "info", // Category "Tests generation", // Title fmt.Sprintf("Input Addresses %d\nMax balance %s, Average Balance %s", len(fs.inputAddresses), strings.TrimSpace(fct.ConvertDecimal(max)), strings.TrimSpace(fct.ConvertDecimal(sum/uint64(len(fs.inputAddresses))))), // Msg 60) // Expire // The following code is a function that creates an array // of addresses pulled from some source array of addresses // selected randomly. var makeList = func(source []fct.IAddress, cnt int) []fct.IAddress { adrs := make([]fct.IAddress, 0, cnt) for len(adrs) < cnt { i := rand.Int() % len(source) adr := source[i] adrs = append(adrs, adr) } return adrs } mIn := maxIn mOut := maxOut mEc := maxOut // Distribute our randomness over various spaces. This doesn't // make for realistic transactions, but we don't care so much. joker := rand.Int() % 100 if joker < 1 { mIn = maxIn * 2 } if joker < 2 { mIn = maxIn * 4 } if joker < 3 { mIn = maxIn * 8 } if joker < 4 { mIn = maxIn * 16 } if joker < 5 { mIn = maxIn * 32 } if joker < 6 { mIn = maxIn * 64 } joker = rand.Int() % 100 if joker < 1 { mOut = maxOut * 2 } if joker < 2 { mOut = maxOut * 4 } if joker < 3 { mOut = maxOut * 8 } if joker < 4 { mOut = maxOut * 16 } if joker < 5 { mOut = maxOut * 32 } if joker < 6 { mOut = maxOut * 64 } joker = rand.Int() % 100 if joker < 1 { mEc = maxOut * 2 } if joker < 2 { mEc = maxOut * 4 } if joker < 3 { mEc = maxOut * 8 } if joker < 4 { mEc = maxOut * 16 } if joker < 5 { mEc = maxOut * 32 } if joker < 6 { mEc = maxOut * 64 } // Get one to five inputs, and one to five outputs numInputs := rand.Int()%mIn + 1 numOutputs := rand.Int() % mOut mumECOutputs := rand.Int() % mEc numInputs = (numInputs % (len(fs.inputAddresses) - 2)) + 1 // fmt.Println("inputs outputs",numInputs,numOutputs, "limits",len(fs.inputAddresses),len(fs.outputAddresses)) // Get my input and output addresses inputs := makeList(fs.inputAddresses, numInputs) outputs := makeList(fs.outputAddresses, numOutputs) ecoutputs := makeList(fs.ecoutputAddresses, mumECOutputs) var paid uint64 t := fs.twallet.CreateTransaction(fs.GetTimeMilli()) for _, adr := range inputs { balance := fs.GetBalance(adr) toPay := uint64(rand.Int63()) % (balance / 2) paid = toPay + paid fs.twallet.AddInput(t, adr, toPay) } paid = paid - fs.GetFactoshisPerEC()*uint64(len(ecoutputs)) for _, adr := range outputs { fs.twallet.AddOutput(t, adr, paid/uint64(len(outputs))) } for _, adr := range ecoutputs { fs.twallet.AddECOutput(t, adr, fs.GetFactoshisPerEC()) } fee, _ := t.CalculateFee(fs.GetFactoshisPerEC()) toPay := t.GetInputs()[0].GetAmount() fs.twallet.UpdateInput(t, 0, inputs[0], toPay+fee) valid, err1 := fs.twallet.SignInputs(t) if err1 != nil { fct.Prtln("Failed to sign transaction") } if !valid { fct.Prtln("Transaction is not valid") } if err := fs.Validate(len(fs.GetCurrentBlock().GetTransactions()), t); err != nil || err1 != nil { fs.GetDB().Put(fct.DB_BAD_TRANS, t.GetHash(), t) fs.stats.badAddresses += 1 str := []byte(err.Error())[:10] if bytes.Compare(str, []byte("The inputs")) != 0 { str = []byte(err.Error())[:30] } fs.stats.errors[string(str)] += 1 fs.stats.full[string(str)] = err.Error() return fs.newTransaction(maxIn, maxOut) } return t }
func craftTx(w http.ResponseWriter, r *http.Request) { txKey := r.FormValue("key") actionToDo := r.FormValue("action") // Make sure we don't already have a transaction in process with this key t := myState.GetFS().GetDB().GetRaw([]byte(fct.DB_BUILD_TRANS), []byte(txKey)) if t != nil { deleteErr := FactoidDeleteTx(txKey) if deleteErr != nil { w.Write([]byte(deleteErr.Error())) return } } // Create a transaction t = myState.GetFS().GetWallet().CreateTransaction(myState.GetFS().GetTimeMilli()) // Save it with the key myState.GetFS().GetDB().PutRaw([]byte(fct.DB_BUILD_TRANS), []byte(txKey), t) var buffer bytes.Buffer buffer.WriteString("Transaction " + txKey + ":\n\n") inputStr := r.FormValue("inputs") var inRes []inputList err := json.Unmarshal([]byte(inputStr), &inRes) if err != nil { w.Write([]byte("Error: " + err.Error())) return } outputStr := r.FormValue("outputs") var outRes []outputList json.Unmarshal([]byte(outputStr), &outRes) totalInputs := 0.0 totalOutputs := 0.0 for _, inputElement := range inRes { totalInputs += inputElement.InputSize inputFeedErr := SilentAddInput(string(txKey), string(inputElement.InputAddress), strconv.FormatFloat(inputElement.InputSize, 'f', -1, 64)) if inputFeedErr != nil { w.Write([]byte(inputFeedErr.Error() + " (INPUTS)")) return } buffer.WriteString("\tInput: " + inputElement.InputAddress + " : " + strconv.FormatFloat(inputElement.InputSize, 'f', -1, 64) + "\n") } var outputFeedErr error for _, outputElement := range outRes { totalOutputs += outputElement.OutputSize thisKey := myState.GetFS().GetDB().GetRaw([]byte(fct.W_NAME), []byte(outputElement.OutputAddress)) we, ok := thisKey.(wallet.IWalletEntry) if ok { if we.GetType() == "ec" { outputElement.OutputType = "ec" } else if we.GetType() == "fct" { outputElement.OutputType = "fct" } } if outputElement.OutputType == "fct" { outputFeedErr = SilentAddOutput(string(txKey), string(outputElement.OutputAddress), strconv.FormatFloat(outputElement.OutputSize, 'f', -1, 64)) if outputFeedErr != nil { outputFeedErr = SilentAddECOutput(string(txKey), string(outputElement.OutputAddress), strconv.FormatFloat(outputElement.OutputSize, 'f', -1, 64)) if outputFeedErr == nil { outputElement.OutputType = "ec" } } } else { outputFeedErr = SilentAddECOutput(string(txKey), string(outputElement.OutputAddress), strconv.FormatFloat(outputElement.OutputSize, 'f', -1, 64)) if outputFeedErr != nil { outputFeedErr = SilentAddOutput(string(txKey), string(outputElement.OutputAddress), strconv.FormatFloat(outputElement.OutputSize, 'f', -1, 64)) if outputFeedErr == nil { outputElement.OutputType = "fct" } } } if outputFeedErr != nil { w.Write([]byte(outputFeedErr.Error() + " (OUTPUTS)")) return } if outputElement.OutputType == "ec" { v, err := GetRate(myState) if err != nil { fmt.Println(err) } numECs := outputElement.OutputSize * float64(100000000) / float64(v) buffer.WriteString("\tOutput: " + outputElement.OutputAddress + " : " + strconv.FormatFloat(outputElement.OutputSize, 'f', -1, 64) + " (" + strconv.Itoa(int(numECs)) + " EC) \n") } else { buffer.WriteString("\tOutput: " + outputElement.OutputAddress + " : " + strconv.FormatFloat(outputElement.OutputSize, 'f', -1, 64) + "\n") } } tin, err1 := t.(fct.ITransaction).TotalInputs() tout, err2 := t.(fct.ITransaction).TotalOutputs() tec, err3 := t.(fct.ITransaction).TotalECs() if err1 == nil && err2 == nil && err3 == nil { cfee := int64(tin) - int64(tout) - int64(tec) sign := "" if cfee < 0 { sign = "-" cfee = -cfee } buffer.WriteString("\n\tFee: " + sign + strings.TrimSpace(fct.ConvertDecimal(uint64(cfee))) + "\n") } //currFee := uint64((totalInputs - totalOutputs) * 100000000) //buffer.WriteString("\n\tFee: " + strings.TrimSpace(fct.ConvertDecimal(currFee))) //buffer.WriteString("\n\tFee: " + strconv.FormatFloat(currFee, 'f', -1, 64)) switch actionToDo { case "fee": w.Write(showFee(txKey)) case "print": printTest := []string{"Print", string(txKey)} printTestErr := myState.Execute(printTest) if printTestErr != nil { w.Write([]byte("PRINTERR: " + printTestErr.Error())) } w.Write(buffer.Bytes()) case "save": fileToSaveTo := r.FormValue("fileName") if len(fileToSaveTo) < 1 { w.Write([]byte("Filename cannot be empty!\n\n")) return } if _, err := os.Stat(fileToSaveTo); os.IsNotExist(err) { signFeedString := []string{"Sign", string(txKey)} signErr := myState.Execute(signFeedString) if signErr != nil { w.Write([]byte("Error signing transaction: " + signErr.Error())) return } saveFeedString := []string{"Export", string(txKey), string(fileToSaveTo)} saveErr := myState.Execute(saveFeedString) if saveErr != nil { w.Write([]byte("Error saving transaction: " + saveErr.Error())) return } buffer.WriteString("\n\nTransaction ") buffer.WriteString(txKey) buffer.WriteString(" has been saved to file: ") buffer.WriteString(string(fileToSaveTo)) w.Write(buffer.Bytes()) } else { w.Write([]byte(string(fileToSaveTo) + " already exists, please choose another filename to save to.")) } return case "sign": signFeedString := []string{"Sign", string(txKey)} signErr := myState.Execute(signFeedString) if signErr != nil { w.Write([]byte(signErr.Error())) return } buffer.WriteString("\n\nTransaction ") buffer.WriteString(txKey) buffer.WriteString(" has been signed.") w.Write(buffer.Bytes()) case "send": testPrintTx := []string{"Print", string(txKey)} printErr := myState.Execute(testPrintTx) if printErr != nil { w.Write([]byte(printErr.Error())) return } signFeedString := []string{"Sign", string(txKey)} signErr := myState.Execute(signFeedString) if signErr != nil { w.Write([]byte(signErr.Error())) return } submitFeedString := []string{"Submit", string(txKey)} submitErr := myState.Execute(submitFeedString) if submitErr != nil { w.Write([]byte(submitErr.Error())) return } buffer.WriteString("\n\nTransaction ") buffer.WriteString(txKey) buffer.WriteString(" has been submitted to Factom.") w.Write(buffer.Bytes()) } }
func receiveAjax(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { ajax_post_data := r.FormValue("ajax_post_data") call_type := r.FormValue("call_type") switch call_type { case "balance": we := myState.GetFS().GetDB().GetRaw([]byte(fct.W_NAME), []byte(ajax_post_data)) printBal, _ := FctBalance(myState, ajax_post_data) if we != nil { if we.(wallet.IWalletEntry).GetType() == "ec" { printBal, _ := ECBalance(myState, ajax_post_data) w.Write([]byte("Entry Credit Address " + ajax_post_data + " Balance: " + strconv.Itoa(int(printBal)) + " EC")) return } } else { if printBal == 0 { printBal, _ = ECBalance(myState, ajax_post_data) if printBal != 0 || strings.HasPrefix(ajax_post_data, "EC") { w.Write([]byte("Entry Credit Address " + ajax_post_data + " Balance: " + strconv.Itoa(int(printBal)) + " EC")) return } } } w.Write([]byte("Factoid Address " + ajax_post_data + " Balance: " + strings.Trim(fct.ConvertDecimal(uint64(printBal)), " ") + " тиО")) case "balances": printBal := GetBalances(myState) testErr := myState.Execute([]string{"balances"}) if testErr != nil { fmt.Println(testErr.Error()) w.Write([]byte(testErr.Error())) return } w.Write(printBal) case "allTxs": txNames, err := GetTransactions() if err != nil { fmt.Println(err.Error()) w.Write([]byte(err.Error())) return } if len(txNames) == 0 { w.Write([]byte("No transactions to display.")) return } sliceTxNames := []byte("") for i := range txNames { sliceTxNames = append(sliceTxNames, bytes.Trim(txNames[i], "\x00")...) if i < len(txNames)-1 { sliceTxNames = append(sliceTxNames, byte('\n')) } } w.Write(sliceTxNames) case "addNewAddress": if len(ajax_post_data) > 0 { genErr := GenAddress(myState, "fct", ajax_post_data) if genErr != nil { w.Write([]byte(genErr.Error())) return } w.Write([]byte(ajax_post_data + " has been added to your wallet successfully.")) } case "addNewEC": if len(ajax_post_data) > 0 { genErr := GenAddress(myState, "ec", ajax_post_data) if genErr != nil { w.Write([]byte(genErr.Error())) return } w.Write([]byte(ajax_post_data + " has been added to your wallet successfully.")) } case "importPrivKey": addressName := r.FormValue("addressName") if len(ajax_post_data) > 0 && len(addressName) > 0 { importFeedString := []string{"ImportKey", string(addressName), string(ajax_post_data)} fmt.Println(importFeedString) importErr := myState.Execute(importFeedString) if importErr != nil { w.Write([]byte(importErr.Error())) return } w.Write([]byte("The contents of the private key have been added to " + addressName + " successfully!")) } else { w.Write([]byte("You must include a non-empty private key and name for the address to import it into.")) } case "importTwelveWords": addressName := r.FormValue("addressName") if len(ajax_post_data) > 0 && len(addressName) > 0 { twelveWords := strings.Split(string(ajax_post_data), " ") if len(twelveWords) != 12 { w.Write([]byte("Invalid Parameters")) return } else { twelveFeedString := []string{"AddressFromWords", string(addressName), twelveWords[0], twelveWords[1], twelveWords[2], twelveWords[3], twelveWords[4], twelveWords[5], twelveWords[6], twelveWords[7], twelveWords[8], twelveWords[9], twelveWords[10], twelveWords[11]} fmt.Println(twelveFeedString) twelveErr := myState.Execute(twelveFeedString) if twelveErr != nil { w.Write([]byte(twelveErr.Error())) return } w.Write([]byte("The twelve-word key has been imported to " + addressName + " successfully!")) } } else { w.Write([]byte("You must provide a valid twelve-word-key and a name for the address to import them into.")) } } } else { helpText, err := ioutil.ReadFile(staticDir + "help.txt") check(err, false) w.Write([]byte(helpText)) } }
func (Print) Execute(state IState, args []string) error { fmt.Println() for i, v := range args { if i == 0 { continue } ib := state.GetFS().GetDB().GetRaw([]byte(fct.DB_BUILD_TRANS), []byte(v)) trans, ok := ib.(fct.ITransaction) if ib != nil && ok { fmt.Println("Transaction: ", v, "\n\n", ib) v, err := GetRate(state) if err != nil { fmt.Println(err) continue } fee, err := trans.CalculateFee(uint64(v)) if err != nil { fmt.Println(err) continue } fmt.Println("Required Fee: ", strings.TrimSpace(fct.ConvertDecimal(fee))) tin, err1 := trans.TotalInputs() tout, err2 := trans.TotalOutputs() tec, err3 := trans.TotalECs() if err1 == nil && err2 == nil && err3 == nil { cfee := int64(tin) - int64(tout) - int64(tec) sign := "" if cfee < 0 { sign = "-" cfee = -cfee } fmt.Print("Fee You are paying: ", sign, strings.TrimSpace(fct.ConvertDecimal(uint64(cfee))), "\n") } else { if err1 != nil { fmt.Println("Inputs have an error: ", err1) } if err2 != nil { fmt.Println("Outputs have an error: ", err2) } if err3 != nil { fmt.Println("Entry Credit Outputs have an error: ", err2) } } binary, err := trans.MarshalBinary() if err != nil { fmt.Println(err) continue } fmt.Println("Transaction Size: ", len(binary)) continue } switch strings.ToLower(v) { case "currentblock": fmt.Println(state.GetFS().GetCurrentBlock()) case "--rate": v, err := GetRate(state) if err != nil { fmt.Println(err) continue } fmt.Println("Factoids to buy one Entry Credit: ", fct.ConvertDecimal(uint64(v))) case "height": fmt.Println("Directory block height is: ", state.GetFS().GetDBHeight()) default: fmt.Println("Unknown: ", v) } } return nil }