예제 #1
0
// 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
}
예제 #2
0
파일: scblock.go 프로젝트: conseweb/factoid
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
}
예제 #3
0
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)
}
예제 #4
0
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))))
}
예제 #5
0
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
}
예제 #6
0
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()
}
예제 #7
0
파일: balance.go 프로젝트: xbee/factom-cli
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
}
예제 #8
0
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)

}
예제 #9
0
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("...")
	}

}
예제 #10
0
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("..."))
	}

}
예제 #11
0
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
}
예제 #12
0
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()
}
예제 #13
0
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
}
예제 #14
0
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
}
예제 #15
0
// 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
}
예제 #16
0
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
}
예제 #17
0
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
}
예제 #18
0
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())
	}
}
예제 #19
0
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))
	}
}
예제 #20
0
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
}