Skip to content

Commit

Permalink
improve simWallet to allow waiting for min/max balance targets
Browse files Browse the repository at this point in the history
  • Loading branch information
stackdump committed Jun 6, 2019
1 parent 03f5f1e commit b9dc914
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 20 deletions.
117 changes: 117 additions & 0 deletions longTest/ChainedTransactions_test.go
@@ -0,0 +1,117 @@
package longtest

import (
"fmt"
"testing"
"time"

"github.com/FactomProject/factom"
. "github.com/FactomProject/factomd/engine"
. "github.com/FactomProject/factomd/testHelper"
)

// FIXME: test runs > 40 min try to tune down to 10 min
// TODO: refactor to use testAccount helpers
func TestChainedTransactions(t *testing.T) {
// a genesis block address w/ funding
bankSecret := "Fs3E9gV6DXsYzf7Fqx1fVBQPQXV695eP3k5XbmHEZVRLkMdD9qCK"
bankAddress := "FA2jK2HcLnRdS94dEcU27rF3meoJfpUcZPSinpb7AwQvPRY6RL1Q"

var depositSecrets []string
var depositAddresses []string

for i := 0; i < 120; i++ {
priv, addr := RandomFctAddressPair()
depositSecrets = append(depositSecrets, priv)
depositAddresses = append(depositAddresses, addr)
}

var maxBlocks = 500
state0 := SetupSim("LAF", map[string]string{"--debuglog": "."}, maxBlocks+1, 0, 0, t)
var ecPrice uint64 = state0.GetFactoshisPerEC() //10000
var oneFct uint64 = factom.FactoidToFactoshi("1")

waitForDeposit := func(i int, amt uint64) uint64 {
balance := GetBalance(state0, depositAddresses[i])
TimeNow(state0)
fmt.Printf("%v waitForDeposit %v %v - %v = diff: %v \n", i, depositAddresses[i], balance, amt, balance-int64(amt))
var waited bool
for balance != int64(amt) {
waited = true
balance = GetBalance(state0, depositAddresses[i])
time.Sleep(time.Millisecond * 100)
}
if waited {
fmt.Printf("%v waitForDeposit %v %v - %v = diff: %v \n", i, depositAddresses[i], balance, amt, balance-int64(amt))
TimeNow(state0)
}
return uint64(balance)
}
_ = waitForDeposit

initialBalance := 10 * oneFct
fee := 12 * ecPrice

prepareTransactions := func(bal uint64) ([]func(), uint64, int) {

var transactions []func()
var i int

for i = 0; i < len(depositAddresses)-1; i += 1 {
bal -= fee

in := i
out := i + 1
send := bal

txn := func() {
SendTxn(state0, send, depositSecrets[in], depositAddresses[out], ecPrice)
}
transactions = append(transactions, txn)
}
return transactions, bal, i
}

// offset to send initial blocking transaction
offset := 1

mkTransactions := func() { // txnGenerator
// fund the start address
SendTxn(state0, initialBalance, bankSecret, depositAddresses[0], ecPrice)
WaitMinutes(state0, 1)
waitForDeposit(0, initialBalance)
transactions, finalBalance, finalAddress := prepareTransactions(initialBalance)

var sent []int
var unblocked bool = false

for i := 1; i < len(transactions); i++ {
sent = append(sent, i)
//fmt.Printf("offset: %v <=> i:%v", offset, i)
if i == offset {
fmt.Printf("\n==>TXN offset%v\n", offset)
transactions[0]() // unblock the transactions
unblocked = true
}
transactions[i]()
}
if !unblocked {
transactions[0]() // unblock the transactions
}
offset++ // next time start further in the future
fmt.Printf("send chained transations")
waitForDeposit(finalAddress, finalBalance)

// empty final address returning remaining funds to bank
SendTxn(state0, finalBalance-fee, depositSecrets[finalAddress], bankAddress, ecPrice)
waitForDeposit(finalAddress, 0)
}

for x := 1; x <= 120; x++ {
mkTransactions()
WaitBlocks(state0, 1)
}

WaitForAllNodes(state0)
ShutDownEverything(t)
}
6 changes: 3 additions & 3 deletions simTest/EntriesBeforeChain_test.go
Expand Up @@ -63,10 +63,10 @@ func TestEntriesBeforeChain(t *testing.T) {
// REVIEW is this a good enough test for holding
WaitMinutes(state0, 2) // ensure messages are reviewed in holding at least once

a.FundEC(numEntries + 11) // Chain costs 10 + 1 per k so our chain costs 11
WaitForAnyDeposit(state0, a.EcPub())
a.FundEC(uint64(numEntries + 11)) // Chain costs 10 + 1 per k so our chain costs 11
WaitForAnyEcBalance(state0, a.EcPub())

WaitForZero(state0, a.EcPub())
WaitForZeroEC(state0, a.EcPub())
ShutDownEverything(t)
WaitForAllNodes(state0)

Expand Down
10 changes: 5 additions & 5 deletions simTest/HoldingRebound_test.go
Expand Up @@ -47,11 +47,11 @@ func TestHoldingRebound(t *testing.T) {
state0.APIQueue().Enqueue(reveal)

a.FundEC(11)
WaitForAnyDeposit(state0, a.EcPub()) // EC deposit goes through
WaitForZero(state0, a.EcPub()) // Account should be drained
WaitForAnyEcBalance(state0, a.EcPub()) // EC deposit goes through
WaitForZeroEC(state0, a.EcPub()) // Account should be drained

GenerateCommitsAndRevealsInBatches(t, state0)
WaitForZero(state0, a.EcPub())
WaitForZeroEC(state0, a.EcPub())
ht := state0.GetDBHeightComplete()
WaitBlocks(state0, 2)
newHt := state0.GetDBHeightComplete()
Expand Down Expand Up @@ -116,8 +116,8 @@ func GenerateCommitsAndRevealsInBatches(t *testing.T, state0 *state.State) {
publish(x)
}

a.FundEC(numEntries)
WaitForAnyDeposit(state0, a.EcPub())
a.FundEC(uint64(numEntries))
WaitForAnyEcBalance(state0, a.EcPub())

tend := WaitForEmptyHolding(state0, fmt.Sprintf("WAIT_HOLDING_END%v", BatchID))

Expand Down
36 changes: 36 additions & 0 deletions simTest/SimWallet_test.go
@@ -0,0 +1,36 @@
package simtest

import (
"fmt"
"github.com/FactomProject/factom"
. "github.com/FactomProject/factomd/testHelper"
"testing"
)

func TestSimWallet(t *testing.T) {

a := AccountFromFctSecret("Fs31kMMKBSCDwa7tSEzjQ4EfGeXARdUS22oBEJKNSJWbLAMTsEHr")
b := AccountFromFctSecret("Fs2BNvoDgSoGJpWg4PvRUxqvLE28CQexp5FZM9X5qU6QvzFBUn6D")

fmt.Printf("A: %s", a)
fmt.Printf("B: %s", b)

state0 := SetupSim("L", map[string]string{"--debuglog": ""}, 80, 0, 0, t)

var oneFct uint64 = factom.FactoidToFactoshi("1")
a.FundFCT(10*oneFct) // fund fct from coinbase 'bank'
a.SendFCT(b, oneFct) // fund Account b from Acct a
WaitForAnyFctBalance(state0, a.FctPub()) // wait for non-zero
WaitForMaxFctBalance(state0, b.FctPub(), int64(oneFct)) // wait for at least 1 fct


a.FundEC(10) // fund EC from coinbase 'bank'
WaitForMaxEcBalance(state0, a.EcPub(), 1) // wait for at least 1 ec

b.ConvertEC(10) // fund EC from account b
WaitForAnyEcBalance(state0, b.EcPub())

WaitBlocks(state0, 1)
ShutDownEverything(t)

}
2 changes: 1 addition & 1 deletion state/stateConsensus.go
Expand Up @@ -845,6 +845,7 @@ func (s *State) MoveStateToHeight(dbheight uint32, newMinute int) {
s.LeaderPL.SortAuditServers()
s.LeaderPL.SortFedServers()

s.Hold.Review() // check for resolved dependents and cleanup new messages
}

{ // debug
Expand Down Expand Up @@ -880,7 +881,6 @@ func (s *State) MoveStateToHeight(dbheight uint32, newMinute int) {
s.EOMLimit = len(s.LeaderPL.FedServers) // We add or remove server only on block boundaries
s.DBSigLimit = s.EOMLimit // We add or remove server only on block boundaries

s.Hold.Review() // cleanup expired messages from NewHolding
s.LogPrintf("dbstateprocess", "MoveStateToHeight(%d-:-%d) leader=%v leaderPL=%p, leaderVMIndex=%d", dbheight, newMinute, s.Leader, s.LeaderPL, s.LeaderVMIndex)

}
Expand Down
109 changes: 98 additions & 11 deletions testHelper/simWallet.go
Expand Up @@ -74,11 +74,35 @@ func (d *testAccount) EcAddr() interfaces.IHash {
return x
}

func (d *testAccount) FundEC(amt int) {
// buy EC from coinbase 'bank'
func (d *testAccount) FundEC(amt uint64) {
state0 := engine.GetFnodes()[0].State
engine.FundECWallet(state0, GetBankAccount().FctPrivHash(), d.EcAddr(), uint64(amt)*state0.GetFactoshisPerEC())
}

// buy EC from account
func (d *testAccount) ConvertEC(amt uint64) {
state0 := engine.GetFnodes()[0].State
engine.FundECWallet(state0, d.FctPrivHash(), d.EcAddr(), uint64(amt)*state0.GetFactoshisPerEC())
}


// get FCT from coinbase 'bank'
func (d *testAccount) FundFCT(amt uint64) {
state0 := engine.GetFnodes()[0].State
_, err := engine.SendTxn(state0, uint64(amt), GetBankAccount().FctPriv(), d.FctPub(), state0.GetFactoshisPerEC())
if err != nil {
panic(err)
}
}

// transfer FCT from account
func (d *testAccount) SendFCT(a *testAccount, amt uint64) {
state0 := engine.GetFnodes()[0].State
engine.SendTxn(state0, uint64(amt), d.FctPriv(), a.FctPub(), state0.GetFactoshisPerEC())
}

// check EC balance
func (d *testAccount) GetECBalance() int64 {
state0 := engine.GetFnodes()[0].State
return engine.GetBalanceEC(state0, d.EcPub())
Expand Down Expand Up @@ -113,11 +137,12 @@ func AccountFromFctSecret(s string) *testAccount {
return d
}

// This account has a balance from inital coinbase
// This account has a balance from initial coinbase
func GetBankAccount() *testAccount {
return AccountFromFctSecret("Fs3E9gV6DXsYzf7Fqx1fVBQPQXV695eP3k5XbmHEZVRLkMdD9qCK")
}

// build addresses from random key
func GetRandomAccount() *testAccount {
d := new(testAccount)
d.Priv = primitives.RandomPrivateKey()
Expand Down Expand Up @@ -270,27 +295,89 @@ func ComposeChainCommit(pkey *primitives.PrivateKey, c *factom.Chain) (*messages
return m, nil
}

func WaitForAnyDeposit(s *state.State, ecPub string) int64 {
s.LogPrintf(logName, "WaitForAnyDeposit %v", ecPub)
return WaitForEcBalance(s, ecPub, 1)
// wait for non-zero EC balance
func WaitForAnyEcBalance(s *state.State, ecPub string) int64 {
//s.LogPrintf(logName, "WaitForAnyEcBalance %v", ecPub)
return WaitForMinEcBalance(s, ecPub, 1)
}

func WaitForZero(s *state.State, ecPub string) int64 {
// wait for non-zero FCT balance
func WaitForAnyFctBalance(s *state.State, fctPub string) int64 {
//s.LogPrintf(logName, "WaitForAnyEcBalance %v", fctPub)
return WaitForMinFctBalance(s, fctPub, 1)
}

// wait for exactly Zero EC balance
func WaitForZeroEC(s *state.State, ecPub string) int64 {
fmt.Println("Waiting for Zero Balance")
return WaitForEcBalance(s, ecPub, 0)
return WaitForMinEcBalance(s, ecPub, 0)
}

func WaitForEcBalance(s *state.State, ecPub string, target int64) int64 {
const balanceWaitInterval = time.Millisecond * 20

// loop until balance is >= target
func WaitForMinEcBalance(s *state.State, ecPub string, target int64) int64 {

s.LogPrintf(logName, "WaitForBalance%v: %v", target, ecPub)
//s.LogPrintf(logName, "WaitForMinEcBalance%v: %v", target, ecPub)

for {
bal := engine.GetBalanceEC(s, ecPub)
time.Sleep(time.Millisecond * 20)
time.Sleep(balanceWaitInterval)
//fmt.Printf("WaitForBalance: %v => %v\n", ecPub, bal)

if (target == 0 && bal == 0) || (target > 0 && bal >= target) {
s.LogPrintf(logName, "FoundBalance%v: %v", target, bal)
//s.LogPrintf(logName, "FoundMinEcBalance%v: %v", target, bal)
return bal
}
}
}

// loop until balance is <= target
func WaitForMaxEcBalance(s *state.State, ecPub string, target int64) int64 {

//s.LogPrintf(logName, "WaitForMaxEcBalance%v: %v", target, ecPub)

for {
bal := engine.GetBalanceEC(s, ecPub)
time.Sleep(balanceWaitInterval)
//fmt.Printf("WaitForBalance: %v => %v\n", ecPub, bal)

if (target == 0 && bal == 0) || (target > 0 && bal <= target) {
//s.LogPrintf(logName, "FoundMaxEcBalance%v: %v", target, bal)
return bal
}
}
}

// loop until balance is >= target
func WaitForMinFctBalance(s *state.State, fctPub string, target int64) int64 {

//s.LogPrintf(logName, "WaitForMinFctBalance%v: %v", target, fctPub)

for {
bal := engine.GetBalance(s, fctPub)
time.Sleep(balanceWaitInterval)
//s.LogPrintf(logName, "WaitForMinFctBalance: %v => %v\n", fctPub, bal)

if (target == 0 && bal == 0) || (target > 0 && bal >= target) {
//s.LogPrintf(logName, "FoundBalance%v: %v", target, bal)
return bal
}
}
}

// loop until balance is <= target
func WaitForMaxFctBalance(s *state.State, fctPub string, target int64) int64 {

//s.LogPrintf(logName, "WaitForMaxFctBalance%v: %v", target, fctPub)

for {
bal := engine.GetBalance(s, fctPub)
time.Sleep(balanceWaitInterval)
//s.LogPrintf(logName, "WaitForMaxFctBalance: %v => %v\n", fctPub, bal)

if (target == 0 && bal == 0) || (target > 0 && bal <= target) {
//s.LogPrintf(logName, "FoundMaxFctBalance%v: %v", target, bal)
return bal
}
}
Expand Down

0 comments on commit b9dc914

Please sign in to comment.