Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agreement/gossip/networkFull_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func spinNetwork(t *testing.T, nodesCount int, cfg config.Local) ([]*networkImpl
break
}
}
log.Infof("network established, %d nodes connected in %s", nodesCount, time.Now().Sub(start).String())
log.Infof("network established, %d nodes connected in %s", nodesCount, time.Since(start).String())
return networkImpls, msgCounters
}

Expand Down
2 changes: 1 addition & 1 deletion catchup/universalFetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func (uf *universalBlockFetcher) fetchBlock(ctx context.Context, round basics.Ro
} else {
return nil, nil, time.Duration(0), fmt.Errorf("fetchBlock: UniversalFetcher only supports HTTPPeer and UnicastPeer")
}
downloadDuration = time.Now().Sub(blockDownloadStartTime)
downloadDuration = time.Since(blockDownloadStartTime)
block, cert, err := processBlockBytes(fetchedBuf, round, address)
if err != nil {
return nil, nil, time.Duration(0), err
Expand Down
3 changes: 1 addition & 2 deletions cmd/goal/clerk.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,7 @@ func waitForCommit(client libgoal.Client, txid string, transactionLastValidRound
}

reportInfof(infoTxPending, txid, stat.LastRound)
// WaitForRound waits until round "stat.LastRound+1" is committed
stat, err = client.WaitForRound(stat.LastRound)
stat, err = client.WaitForRound(stat.LastRound + 1)
if err != nil {
return model.PendingTransactionResponse{}, fmt.Errorf(errorRequestFail, err)
}
Expand Down
11 changes: 6 additions & 5 deletions cmd/loadgenerator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,22 +200,23 @@ func waitForRound(restClient client.RestClient, cfg config, spendingRound bool)
time.Sleep(1 * time.Second)
continue
}
if isSpendRound(cfg, nodeStatus.LastRound) == spendingRound {
lastRound := nodeStatus.LastRound
if isSpendRound(cfg, lastRound) == spendingRound {
// time to send transactions.
return
}
if spendingRound {
fmt.Printf("Last round %d, waiting for spending round %d\n", nodeStatus.LastRound, nextSpendRound(cfg, nodeStatus.LastRound))
fmt.Printf("Last round %d, waiting for spending round %d\n", lastRound, nextSpendRound(cfg, nodeStatus.LastRound))
}
for {
// wait for the next round.
nodeStatus, err = restClient.WaitForBlock(basics.Round(nodeStatus.LastRound))
err = restClient.WaitForRoundWithTimeout(lastRound + 1)
if err != nil {
fmt.Fprintf(os.Stderr, "unable to wait for next round node status : %v", err)
time.Sleep(1 * time.Second)
break
}
if isSpendRound(cfg, nodeStatus.LastRound) == spendingRound {
lastRound++
if isSpendRound(cfg, lastRound) == spendingRound {
// time to send transactions.
return
}
Expand Down
9 changes: 7 additions & 2 deletions config/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,9 @@ type ConsensusParams struct {
// occur, extra funds need to be put into the FeeSink. The bonus amount
// decays exponentially.
Bonus BonusPlan

// Heartbeat support
Heartbeat bool
}

// ProposerPayoutRules puts several related consensus parameters in one place. The same
Expand Down Expand Up @@ -1513,7 +1516,7 @@ func initConsensusProtocols() {
vFuture.LogicSigVersion = 11 // When moving this to a release, put a new higher LogicSigVersion here

vFuture.Payouts.Enabled = true
vFuture.Payouts.Percent = 75
vFuture.Payouts.Percent = 50
vFuture.Payouts.GoOnlineFee = 2_000_000 // 2 algos
vFuture.Payouts.MinBalance = 30_000_000_000 // 30,000 algos
vFuture.Payouts.MaxBalance = 70_000_000_000_000 // 70M algos
Expand All @@ -1524,7 +1527,9 @@ func initConsensusProtocols() {

vFuture.Bonus.BaseAmount = 10_000_000 // 10 Algos
// 2.9 sec rounds gives about 10.8M rounds per year.
vFuture.Bonus.DecayInterval = 250_000 // .99^(10.8/0.25) ~ .648. So 35% decay per year
vFuture.Bonus.DecayInterval = 1_000_000 // .99^(10.8M/1M) ~ .897. So ~10% decay per year

vFuture.Heartbeat = true

Consensus[protocol.ConsensusFuture] = vFuture

Expand Down
90 changes: 80 additions & 10 deletions daemon/algod/api/client/restClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"net/http"
"net/url"
"strings"
"time"

"github.com/google/go-querystring/query"

Expand All @@ -39,6 +40,8 @@ import (
"github.com/algorand/go-algorand/ledger/eval"
"github.com/algorand/go-algorand/ledger/ledgercore"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/rpcs"
"github.com/algorand/go-algorand/test/e2e-go/globals"
)

const (
Expand Down Expand Up @@ -283,12 +286,77 @@ func (client RestClient) Status() (response model.NodeStatusResponse, err error)
return
}

// WaitForBlock returns the node status after waiting for the given round.
func (client RestClient) WaitForBlock(round basics.Round) (response model.NodeStatusResponse, err error) {
// WaitForBlockAfter returns the node status after trying to wait for the given
// round+1. This REST API has the documented misfeatures of returning after 1
// minute, regardless of whether the given block has been reached.
func (client RestClient) WaitForBlockAfter(round basics.Round) (response model.NodeStatusResponse, err error) {
err = client.get(&response, fmt.Sprintf("/v2/status/wait-for-block-after/%d/", round), nil)
return
}

// WaitForRound returns the node status after waiting for the given round.
func (client RestClient) WaitForRound(round uint64, waitTime time.Duration) (status model.NodeStatusResponse, err error) {
timeout := time.NewTimer(waitTime)
for {
status, err = client.Status()
if err != nil {
return
}

if status.LastRound >= round {
return
}
select {
case <-timeout.C:
return model.NodeStatusResponse{}, fmt.Errorf("timeout waiting for round %v with last round = %v", round, status.LastRound)
case <-time.After(200 * time.Millisecond):
}
}
}

const singleRoundMaxTime = globals.MaxTimePerRound * 40

// WaitForRoundWithTimeout waits for a given round to be reached. As it
// waits, it returns early with an error if the wait time for any round exceeds
// globals.MaxTimePerRound so we can alert when we're getting "hung" waiting.
func (client RestClient) WaitForRoundWithTimeout(roundToWaitFor uint64) error {
status, err := client.Status()
if err != nil {
return err
}
lastRound := status.LastRound

// If node is already at or past target round, we're done
if lastRound >= roundToWaitFor {
return nil
}

roundComplete := make(chan error, 2)

for nextRound := lastRound + 1; lastRound < roundToWaitFor; nextRound++ {
roundStarted := time.Now()

go func(done chan error) {
stat, err := client.WaitForRound(nextRound, singleRoundMaxTime)
lastRound = stat.LastRound
done <- err
}(roundComplete)

select {
case lastError := <-roundComplete:
if lastError != nil {
close(roundComplete)
return lastError
}
case <-time.After(singleRoundMaxTime):
// we've timed out.
time := time.Since(roundStarted)
return fmt.Errorf("fixture.WaitForRound took %3.2f seconds between round %d and %d", time.Seconds(), lastRound, nextRound)
}
}
return nil
}

// HealthCheck does a health check on the potentially running node,
// returning an error if the API is down
func (client RestClient) HealthCheck() error {
Expand All @@ -301,14 +369,6 @@ func (client RestClient) ReadyCheck() error {
return client.get(nil, "/ready", nil)
}

// StatusAfterBlock waits for a block to occur then returns the StatusResponse after that block
// blocks on the node end
// Not supported
func (client RestClient) StatusAfterBlock(blockNum uint64) (response model.NodeStatusResponse, err error) {
err = client.get(&response, fmt.Sprintf("/v2/status/wait-for-block-after/%d", blockNum), nil)
return
}

type pendingTransactionsParams struct {
Max uint64 `url:"max"`
Format string `url:"format"`
Expand Down Expand Up @@ -557,6 +617,16 @@ func (client RestClient) RawBlock(round uint64) (response []byte, err error) {
return
}

// EncodedBlockCert takes a round and returns its parsed block and certificate
func (client RestClient) EncodedBlockCert(round uint64) (blockCert rpcs.EncodedBlockCert, err error) {
resp, err := client.RawBlock(round)
if err != nil {
return
}
err = protocol.Decode(resp, &blockCert)
return
}

// Shutdown requests the node to shut itself down
func (client RestClient) Shutdown() (err error) {
response := 1
Expand Down
10 changes: 0 additions & 10 deletions data/basics/userBalance.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package basics
import (
"encoding/binary"
"fmt"
"reflect"

"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/crypto"
Expand Down Expand Up @@ -586,15 +585,6 @@ func (u OnlineAccountData) KeyDilution(proto config.ConsensusParams) uint64 {
return proto.DefaultKeyDilution
}

// IsZero checks if an AccountData value is the same as its zero value.
func (u AccountData) IsZero() bool {
if u.Assets != nil && len(u.Assets) == 0 {
u.Assets = nil
}

return reflect.DeepEqual(u, AccountData{})
}

// NormalizedOnlineBalance returns a “normalized” balance for this account.
//
// The normalization compensates for rewards that have not yet been applied,
Expand Down
24 changes: 12 additions & 12 deletions data/bookkeeping/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1013,11 +1013,11 @@ func TestFirstYearsBonus(t *testing.T) {
fmt.Printf("paid %d algos\n", suma)
fmt.Printf("bonus start: %d end: %d\n", plan.BaseAmount, bonus)

// pays about 88M algos
a.InDelta(88_500_000, suma, 100_000)
// pays about 103.5M algos
a.InDelta(103_500_000, suma, 100_000)

// decline about 35%
a.InDelta(0.65, float64(bonus)/float64(plan.BaseAmount), 0.01)
// decline about 10%
a.InDelta(0.90, float64(bonus)/float64(plan.BaseAmount), 0.01)

// year 2
for i := 0; i < yearRounds; i++ {
Expand All @@ -1033,11 +1033,11 @@ func TestFirstYearsBonus(t *testing.T) {
fmt.Printf("paid %d algos after 2 years\n", sum2)
fmt.Printf("bonus end: %d\n", bonus)

// pays about 146M algos (total for 2 years)
a.InDelta(145_700_000, sum2, 100_000)
// pays about 196M algos (total for 2 years)
a.InDelta(196_300_000, sum2, 100_000)

// decline about 58%
a.InDelta(0.42, float64(bonus)/float64(plan.BaseAmount), 0.01)
// decline to about 81%
a.InDelta(0.81, float64(bonus)/float64(plan.BaseAmount), 0.01)

// year 3
for i := 0; i < yearRounds; i++ {
Expand All @@ -1053,9 +1053,9 @@ func TestFirstYearsBonus(t *testing.T) {
fmt.Printf("paid %d algos after 3 years\n", sum3)
fmt.Printf("bonus end: %d\n", bonus)

// pays about 182M algos (total for 3 years)
a.InDelta(182_600_000, sum3, 100_000)
// pays about 279M algos (total for 3 years)
a.InDelta(279_500_000, sum3, 100_000)

// declined to about 27% (but foundation funding probably gone anyway)
a.InDelta(0.27, float64(bonus)/float64(plan.BaseAmount), 0.01)
// declined to about 72% (but foundation funding probably gone anyway)
a.InDelta(0.72, float64(bonus)/float64(plan.BaseAmount), 0.01)
}
Loading
Loading