diff --git a/.gitignore b/.gitignore
index 71617a4836..44bec0113d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,3 +51,6 @@ crypto/libsodium-fork/build-aux/
# doc intermediates
data/transactions/logic/*.md
+
+*.pem
+
diff --git a/.travis.yml b/.travis.yml
index a2546e93f8..f6395fe782 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,4 @@
-dist: xenial
+dist: bionic
go:
- "1.12"
go_import_path: github.com/algorand/go-algorand
@@ -17,14 +17,16 @@ stages:
if: branch =~ /^rel\// AND type != pull_request
- name: deploy
if: branch =~ /^rel\// AND type != pull_request
+ - name: post_deploy
+ if: branch =~ /^rel\// AND type != pull_request
jobs:
allow_failures:
- - name: External ARM64 Build
- name: External ARM64 Deploy
- name: External ARM64 Integration Test
- name: External ARM Build
- name: External ARM Deploy
+ - name: Test Release Builds
include:
- stage: build_commit
os: linux
@@ -110,7 +112,9 @@ jobs:
- stage: deploy
name: Ubuntu Deploy
os: linux
- script: scripts/travis/deploy_packages.sh
+ script:
+ - scripts/travis/deploy_packages.sh
+ - scripts/travis/test_release.sh
- # same stage, parallel job
name: MacOS Deploy
os: osx
diff --git a/Makefile b/Makefile
index 935b24e332..2ed6b6b8b9 100644
--- a/Makefile
+++ b/Makefile
@@ -15,11 +15,21 @@ BUILDCHANNEL ?= $(shell ./scripts/compute_branch_channel.sh $(BUILDBRANCH))
DEFAULTNETWORK ?= $(shell ./scripts/compute_branch_network.sh $(BUILDBRANCH))
DEFAULT_DEADLOCK ?= $(shell ./scripts/compute_branch_deadlock_default.sh $(BUILDBRANCH))
+GOTAGSLIST := sqlite_unlock_notify sqlite_omit_load_extension
+
ifeq ($(UNAME), Linux)
EXTLDFLAGS := -static-libstdc++ -static-libgcc
+ifeq ($(ARCH), amd64)
+# the following predicate is abit misleading; it tests if we're not in centos.
+ifeq (,$(wildcard /etc/centos-release))
+EXTLDFLAGS += -static
+endif
+GOTAGSLIST += osusergo netgo static_build
+GOBUILDMODE := -buildmode pie
+endif
endif
-GOTAGS := --tags "sqlite_unlock_notify sqlite_omit_load_extension"
+GOTAGS := --tags "$(GOTAGSLIST)"
GOTRIMPATH := $(shell go help build | grep -q .-trimpath && echo -trimpath)
GOLDFLAGS_BASE := -X github.com/algorand/go-algorand/config.BuildNumber=$(BUILDNUMBER) \
@@ -56,6 +66,9 @@ vet:
check_license:
./scripts/check_license.sh
+check_shell:
+ find . -type f -name "*.sh" -exec shellcheck {} +
+
sanity: vet fix lint fmt check_license
cover:
@@ -127,7 +140,7 @@ $(KMD_API_SWAGGER_INJECT): $(KMD_API_SWAGGER_SPEC) $(KMD_API_SWAGGER_SPEC).valid
build: buildsrc gen
buildsrc: crypto/lib/libsodium.a node_exporter NONGO_BIN deps $(ALGOD_API_SWAGGER_INJECT) $(KMD_API_SWAGGER_INJECT)
- go install $(GOTRIMPATH) $(GOTAGS) -ldflags="$(GOLDFLAGS)" ./...
+ go install $(GOTRIMPATH) $(GOTAGS) $(GOBUILDMODE) -ldflags="$(GOLDFLAGS)" ./...
SOURCES_RACE := github.com/algorand/go-algorand/cmd/kmd
@@ -243,4 +256,4 @@ dump: $(addprefix gen/,$(addsuffix /genesis.dump, $(NETWORKS)))
install: build
scripts/dev_install.sh -p $(GOPATH1)/bin
-.PHONY: default fmt vet lint check_license sanity cover prof deps build test fulltest shorttest clean cleango deploy node_exporter install %gen gen NONGO_BIN
+.PHONY: default fmt vet lint check_license check_shell sanity cover prof deps build test fulltest shorttest clean cleango deploy node_exporter install %gen gen NONGO_BIN
diff --git a/README.md b/README.md
index 9de4bb535e..2a4d16535e 100644
--- a/README.md
+++ b/README.md
@@ -189,6 +189,6 @@ A number of packages provide utilities for the various components:
Please see the [COPYING_FAQ](COPYING_FAQ) for details about how to apply our license.
-Copyright (C) 2019, Algorand Inc
+Copyright (C) 2019-2020, Algorand Inc.
[developer site url]: https://developer.algorand.org/
diff --git a/THANKS.md b/THANKS.md
index 53ce7defe9..10819df2f8 100644
--- a/THANKS.md
+++ b/THANKS.md
@@ -14,3 +14,4 @@ In no particular order:
### Bug Reports
- Nanyan
+- xixisese
diff --git a/agreement/abstractions.go b/agreement/abstractions.go
index e1e64f59de..97b1c0f2f7 100644
--- a/agreement/abstractions.go
+++ b/agreement/abstractions.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/actions.go b/agreement/actions.go
index 6ff79b3258..77742affcb 100644
--- a/agreement/actions.go
+++ b/agreement/actions.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -20,7 +20,6 @@ import (
"context"
"fmt"
- "github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/logging/logspec"
"github.com/algorand/go-algorand/logging/telemetryspec"
"github.com/algorand/go-algorand/protocol"
@@ -312,7 +311,7 @@ func (a pseudonodeAction) do(ctx context.Context, s *Service) {
case errPseudonodeNoProposals:
// no participation keys, do nothing.
default:
- logging.Base().Errorf("pseudonode.MakeProposals call failed %v", err)
+ s.log.Errorf("pseudonode.MakeProposals call failed %v", err)
}
case repropose:
logEvent := logspec.AgreementEvent{
@@ -336,7 +335,7 @@ func (a pseudonodeAction) do(ctx context.Context, s *Service) {
// do nothing
default:
// otherwise,
- logging.Base().Errorf("pseudonode.MakeVotes call failed for reproposal(%v) %v", a.T, err)
+ s.log.Errorf("pseudonode.MakeVotes call failed for reproposal(%v) %v", a.T, err)
}
case attest:
logEvent := logspec.AgreementEvent{
@@ -360,7 +359,7 @@ func (a pseudonodeAction) do(ctx context.Context, s *Service) {
s.demux.prioritize(voteEvents)
default:
// otherwise,
- logging.Base().Errorf("pseudonode.MakeVotes call failed(%v) %v", a.T, err)
+ s.log.Errorf("pseudonode.MakeVotes call failed(%v) %v", a.T, err)
fallthrough // just so that we would close the channel.
case errPseudonodeNoVotes:
// do nothing; we're closing the channel just to avoid leaving open channels, but it's not
diff --git a/agreement/actor.go b/agreement/actor.go
index 20f066c9da..c771604e1d 100644
--- a/agreement/actor.go
+++ b/agreement/actor.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -18,8 +18,6 @@ package agreement
import (
"fmt"
-
- "github.com/algorand/go-algorand/logging"
)
// An actor is a state machine which accepts events and returns sequences of actions.
@@ -89,12 +87,12 @@ func (l checkedActor) handle(r routerHandle, in event) []action {
for _, pre := range cerrpre {
if pre != nil {
- logging.Base().Warnf("precondition call violation: %v", pre)
+ r.t.log.Warnf("precondition call violation: %v", pre)
}
}
for _, post := range cerrpost {
if post != nil {
- logging.Base().Warnf("postcondition call violation: %v", post)
+ r.t.log.Warnf("postcondition call violation: %v", post)
}
}
// for _, pre := range terrpre {
diff --git a/agreement/agreeInstall.go b/agreement/agreeInstall.go
index da9a2969db..8fc32a9b8f 100644
--- a/agreement/agreeInstall.go
+++ b/agreement/agreeInstall.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/agreementtest/keyManager.go b/agreement/agreementtest/keyManager.go
index 28f750fef9..b905b3c0f8 100644
--- a/agreement/agreementtest/keyManager.go
+++ b/agreement/agreementtest/keyManager.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/agreementtest/simulate.go b/agreement/agreementtest/simulate.go
index cf37c63ff9..c08ece3679 100644
--- a/agreement/agreementtest/simulate.go
+++ b/agreement/agreementtest/simulate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -189,7 +189,7 @@ func Simulate(dbname string, n basics.Round, roundDeadline time.Duration, ledger
Logger: log,
Accessor: accessor,
Clock: stopwatch,
- Network: gossip.WrapNetwork(new(blackhole)),
+ Network: gossip.WrapNetwork(new(blackhole), log),
Ledger: ledger,
BlockFactory: proposalFactory,
BlockValidator: proposalValidator,
diff --git a/agreement/agreementtest/simulate_test.go b/agreement/agreementtest/simulate_test.go
index e21c9a3c93..0d9a83a5a2 100644
--- a/agreement/agreementtest/simulate_test.go
+++ b/agreement/agreementtest/simulate_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/asyncVoteVerifier.go b/agreement/asyncVoteVerifier.go
index 438915f0d0..85d890d8f6 100644
--- a/agreement/asyncVoteVerifier.go
+++ b/agreement/asyncVoteVerifier.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/autopsy.go b/agreement/autopsy.go
index 549a916729..f7675d0adc 100644
--- a/agreement/autopsy.go
+++ b/agreement/autopsy.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/bundle.go b/agreement/bundle.go
index f862834ead..fa4c430089 100644
--- a/agreement/bundle.go
+++ b/agreement/bundle.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/bundle_test.go b/agreement/bundle_test.go
index 5c38c5aa19..9b557d5b2c 100644
--- a/agreement/bundle_test.go
+++ b/agreement/bundle_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/cadaver.go b/agreement/cadaver.go
index fd74051c08..a8965322af 100644
--- a/agreement/cadaver.go
+++ b/agreement/cadaver.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/certificate.go b/agreement/certificate.go
index 7b26e2382e..c196e4c6b1 100644
--- a/agreement/certificate.go
+++ b/agreement/certificate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/certificate_test.go b/agreement/certificate_test.go
index f27f40c432..a2947200c9 100644
--- a/agreement/certificate_test.go
+++ b/agreement/certificate_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/common_test.go b/agreement/common_test.go
index 3b9696e208..39c7db72a8 100644
--- a/agreement/common_test.go
+++ b/agreement/common_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/coservice.go b/agreement/coservice.go
index 3b4cf20a99..fe378a570f 100644
--- a/agreement/coservice.go
+++ b/agreement/coservice.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -44,8 +44,8 @@ type coserviceMonitor struct {
}
type coserviceListener interface {
- inc(sum uint)
- dec(sum uint)
+ inc(sum uint, state map[coserviceType]uint)
+ dec(sum uint, state map[coserviceType]uint)
}
func (m *coserviceMonitor) inc(t coserviceType) {
@@ -62,7 +62,7 @@ func (m *coserviceMonitor) inc(t coserviceType) {
m.c[t]++
if m.coserviceListener != nil {
- m.coserviceListener.inc(m.sum())
+ m.coserviceListener.inc(m.sum(), m.c)
}
}
@@ -83,7 +83,7 @@ func (m *coserviceMonitor) dec(t coserviceType) {
m.c[t]--
if m.coserviceListener != nil {
- m.coserviceListener.dec(m.sum())
+ m.coserviceListener.dec(m.sum(), m.c)
}
}
diff --git a/agreement/cryptoRequestContext.go b/agreement/cryptoRequestContext.go
index 3f86bca01d..3a5594564b 100644
--- a/agreement/cryptoRequestContext.go
+++ b/agreement/cryptoRequestContext.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/cryptoRequestContext_test.go b/agreement/cryptoRequestContext_test.go
index bded4c62a6..aa107c1826 100644
--- a/agreement/cryptoRequestContext_test.go
+++ b/agreement/cryptoRequestContext_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/cryptoVerifier.go b/agreement/cryptoVerifier.go
index 23c443e889..5a695a7cc7 100644
--- a/agreement/cryptoVerifier.go
+++ b/agreement/cryptoVerifier.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/cryptoVerifier_test.go b/agreement/cryptoVerifier_test.go
index 9e71159e61..b6b0f88a4d 100644
--- a/agreement/cryptoVerifier_test.go
+++ b/agreement/cryptoVerifier_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/demux.go b/agreement/demux.go
index 5167487c03..12877aa954 100644
--- a/agreement/demux.go
+++ b/agreement/demux.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/demux_test.go b/agreement/demux_test.go
index f225082272..c585d2e048 100644
--- a/agreement/demux_test.go
+++ b/agreement/demux_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/doc.go b/agreement/doc.go
index de0da56a1a..690e249314 100644
--- a/agreement/doc.go
+++ b/agreement/doc.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/encoding_test.go b/agreement/encoding_test.go
index 479dc6d1e5..d6a74c36c3 100644
--- a/agreement/encoding_test.go
+++ b/agreement/encoding_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/errors.go b/agreement/errors.go
index 87150bfa14..3739d4b1bd 100644
--- a/agreement/errors.go
+++ b/agreement/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/events.go b/agreement/events.go
index 1448c106e6..a34d856f4e 100644
--- a/agreement/events.go
+++ b/agreement/events.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/bandwidthFilter_test.go b/agreement/fuzzer/bandwidthFilter_test.go
index 5883f18b79..0b37a665b5 100644
--- a/agreement/fuzzer/bandwidthFilter_test.go
+++ b/agreement/fuzzer/bandwidthFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/catchupFilter_test.go b/agreement/fuzzer/catchupFilter_test.go
index 6103a7cf61..05936758aa 100644
--- a/agreement/fuzzer/catchupFilter_test.go
+++ b/agreement/fuzzer/catchupFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/clockedFilter_test.go b/agreement/fuzzer/clockedFilter_test.go
index 6df94f5f18..b608ae1366 100644
--- a/agreement/fuzzer/clockedFilter_test.go
+++ b/agreement/fuzzer/clockedFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/dropMessageFilter_test.go b/agreement/fuzzer/dropMessageFilter_test.go
index 7716bde2e9..dfb07c1877 100644
--- a/agreement/fuzzer/dropMessageFilter_test.go
+++ b/agreement/fuzzer/dropMessageFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/duplicateMessageFilter_test.go b/agreement/fuzzer/duplicateMessageFilter_test.go
index 172237b030..80a3c6ac25 100644
--- a/agreement/fuzzer/duplicateMessageFilter_test.go
+++ b/agreement/fuzzer/duplicateMessageFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/filter_test.go b/agreement/fuzzer/filter_test.go
index 33d912fba6..4a3d9ca094 100644
--- a/agreement/fuzzer/filter_test.go
+++ b/agreement/fuzzer/filter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/fuzzer.go b/agreement/fuzzer/fuzzer.go
index d1a4c3aec3..ec30f5b573 100644
--- a/agreement/fuzzer/fuzzer.go
+++ b/agreement/fuzzer/fuzzer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/fuzzer_test.go b/agreement/fuzzer/fuzzer_test.go
index 5015fea0f4..fee40b9c48 100644
--- a/agreement/fuzzer/fuzzer_test.go
+++ b/agreement/fuzzer/fuzzer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -127,10 +127,11 @@ func (n *Fuzzer) initAgreementNode(nodeID int, filters ...NetworkFilterFactory)
return false
}
+ logger := n.log.WithFields(logging.Fields{"Source": "service-" + strconv.Itoa(nodeID)})
n.agreementParams[nodeID] = agreement.Parameters{
- Logger: n.log.WithFields(logging.Fields{"Source": "service-" + strconv.Itoa(nodeID)}),
+ Logger: logger,
Ledger: n.ledgers[nodeID],
- Network: gossip.WrapNetwork(n.facades[nodeID]),
+ Network: gossip.WrapNetwork(n.facades[nodeID], logger),
KeyManager: simpleKeyManager(n.accounts[nodeID : nodeID+1]),
BlockValidator: n.blockValidator,
BlockFactory: testBlockFactory{Owner: nodeID},
@@ -593,7 +594,7 @@ func (n *Fuzzer) CrashNode(nodeID int) {
n.facades[nodeID].ClearHandlers()
n.ledgers[nodeID].ClearNotifications()
- n.agreementParams[nodeID].Network = gossip.WrapNetwork(n.facades[nodeID])
+ n.agreementParams[nodeID].Network = gossip.WrapNetwork(n.facades[nodeID], n.log)
n.agreements[nodeID] = agreement.MakeService(n.agreementParams[nodeID])
cadaverFilename := fmt.Sprintf("%v-%v", n.networkName, nodeID)
diff --git a/agreement/fuzzer/keyManager_test.go b/agreement/fuzzer/keyManager_test.go
index d078d1d16b..70ba4de243 100644
--- a/agreement/fuzzer/keyManager_test.go
+++ b/agreement/fuzzer/keyManager_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/ledger_test.go b/agreement/fuzzer/ledger_test.go
index 6ce4f42f7c..20c0c564dd 100644
--- a/agreement/fuzzer/ledger_test.go
+++ b/agreement/fuzzer/ledger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/messageDecoderFilter_test.go b/agreement/fuzzer/messageDecoderFilter_test.go
index 2e633df78b..316eba66e4 100644
--- a/agreement/fuzzer/messageDecoderFilter_test.go
+++ b/agreement/fuzzer/messageDecoderFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/messageDelayFilter_test.go b/agreement/fuzzer/messageDelayFilter_test.go
index 7b569cf413..771d811107 100644
--- a/agreement/fuzzer/messageDelayFilter_test.go
+++ b/agreement/fuzzer/messageDelayFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/messageDuplicationFilter_test.go b/agreement/fuzzer/messageDuplicationFilter_test.go
index a16c91e470..b71caaf0ed 100644
--- a/agreement/fuzzer/messageDuplicationFilter_test.go
+++ b/agreement/fuzzer/messageDuplicationFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/messagePriorityQueue_test.go b/agreement/fuzzer/messagePriorityQueue_test.go
index 1e5a6e0d74..e775946f37 100644
--- a/agreement/fuzzer/messagePriorityQueue_test.go
+++ b/agreement/fuzzer/messagePriorityQueue_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/messageReflectionFilter_test.go b/agreement/fuzzer/messageReflectionFilter_test.go
index a50d23d5fd..b2a4a88684 100644
--- a/agreement/fuzzer/messageReflectionFilter_test.go
+++ b/agreement/fuzzer/messageReflectionFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/messageRegossipFilter_test.go b/agreement/fuzzer/messageRegossipFilter_test.go
index d3026c5886..f68208b546 100644
--- a/agreement/fuzzer/messageRegossipFilter_test.go
+++ b/agreement/fuzzer/messageRegossipFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/messageReorderingFilter_test.go b/agreement/fuzzer/messageReorderingFilter_test.go
index 389827a689..6f2657c62c 100644
--- a/agreement/fuzzer/messageReorderingFilter_test.go
+++ b/agreement/fuzzer/messageReorderingFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/networkFacade_test.go b/agreement/fuzzer/networkFacade_test.go
index 06262a1d3b..43629df97c 100644
--- a/agreement/fuzzer/networkFacade_test.go
+++ b/agreement/fuzzer/networkFacade_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/nodeCrashFilter_test.go b/agreement/fuzzer/nodeCrashFilter_test.go
index f068262848..5bc96de590 100644
--- a/agreement/fuzzer/nodeCrashFilter_test.go
+++ b/agreement/fuzzer/nodeCrashFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/nullFilter_test.go b/agreement/fuzzer/nullFilter_test.go
index 7298afa8cd..5de708b77f 100644
--- a/agreement/fuzzer/nullFilter_test.go
+++ b/agreement/fuzzer/nullFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/router_test.go b/agreement/fuzzer/router_test.go
index d33b6b2261..0071813e6f 100644
--- a/agreement/fuzzer/router_test.go
+++ b/agreement/fuzzer/router_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/schedulerFilter_test.go b/agreement/fuzzer/schedulerFilter_test.go
index adfbafa0d7..edcb724e84 100644
--- a/agreement/fuzzer/schedulerFilter_test.go
+++ b/agreement/fuzzer/schedulerFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/tests_test.go b/agreement/fuzzer/tests_test.go
index cefa880625..a2599e03f5 100644
--- a/agreement/fuzzer/tests_test.go
+++ b/agreement/fuzzer/tests_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/topologyFilter_test.go b/agreement/fuzzer/topologyFilter_test.go
index c053e468fe..b02a1166cb 100644
--- a/agreement/fuzzer/topologyFilter_test.go
+++ b/agreement/fuzzer/topologyFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/trafficStatisticsFilter_test.go b/agreement/fuzzer/trafficStatisticsFilter_test.go
index 6b395c4ca0..c9b2fe9854 100644
--- a/agreement/fuzzer/trafficStatisticsFilter_test.go
+++ b/agreement/fuzzer/trafficStatisticsFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/validator_test.go b/agreement/fuzzer/validator_test.go
index dd4a9f66a1..74d1acaeef 100644
--- a/agreement/fuzzer/validator_test.go
+++ b/agreement/fuzzer/validator_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/voteFilter_test.go b/agreement/fuzzer/voteFilter_test.go
index ca9dc6d2c7..16188113ef 100644
--- a/agreement/fuzzer/voteFilter_test.go
+++ b/agreement/fuzzer/voteFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/gossip/network.go b/agreement/gossip/network.go
index b94287c54a..b69fc4454e 100644
--- a/agreement/gossip/network.go
+++ b/agreement/gossip/network.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -49,10 +49,11 @@ type networkImpl struct {
bundleCh chan agreement.Message
net network.GossipNode
+ log logging.Logger
}
// WrapNetwork adapts a network.GossipNode into an agreement.Network.
-func WrapNetwork(net network.GossipNode) agreement.Network {
+func WrapNetwork(net network.GossipNode, log logging.Logger) agreement.Network {
i := new(networkImpl)
i.voteCh = make(chan agreement.Message, voteBufferSize)
@@ -60,6 +61,7 @@ func WrapNetwork(net network.GossipNode) agreement.Network {
i.bundleCh = make(chan agreement.Message, bundleBufferSize)
i.net = net
+ i.log = log
handlers := []network.TaggedMessageHandler{
{Tag: protocol.AgreementVoteTag, MessageHandler: network.HandlerFunc(i.processVoteMessage)},
@@ -116,7 +118,7 @@ func (i *networkImpl) Messages(t protocol.Tag) <-chan agreement.Message {
case protocol.VoteBundleTag:
return i.bundleCh
default:
- logging.Base().Panicf("bad tag! %v", t)
+ i.log.Panicf("bad tag! %v", t)
return nil
}
}
@@ -124,7 +126,7 @@ func (i *networkImpl) Messages(t protocol.Tag) <-chan agreement.Message {
func (i *networkImpl) Broadcast(t protocol.Tag, data []byte) (err error) {
err = i.net.Broadcast(context.Background(), t, data, false, nil)
if err != nil {
- logging.Base().Infof("agreement: could not broadcast message with tag %v: %v", t, err)
+ i.log.Infof("agreement: could not broadcast message with tag %v: %v", t, err)
}
return
}
@@ -134,12 +136,12 @@ func (i *networkImpl) Relay(h agreement.MessageHandle, t protocol.Tag, data []by
if metadata == nil { // synthentic loopback
err = i.net.Broadcast(context.Background(), t, data, false, nil)
if err != nil {
- logging.Base().Infof("agreement: could not (pseudo)relay message with tag %v: %v", t, err)
+ i.log.Infof("agreement: could not (pseudo)relay message with tag %v: %v", t, err)
}
} else {
err = i.net.Relay(context.Background(), t, data, false, metadata.raw.Sender)
if err != nil {
- logging.Base().Infof("agreement: could not relay message from %v with tag %v: %v", metadata.raw.Sender, t, err)
+ i.log.Infof("agreement: could not relay message from %v with tag %v: %v", metadata.raw.Sender, t, err)
}
}
return
diff --git a/agreement/gossip/networkFull_test.go b/agreement/gossip/networkFull_test.go
index 960896a46d..b888ee1e50 100644
--- a/agreement/gossip/networkFull_test.go
+++ b/agreement/gossip/networkFull_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -84,7 +84,7 @@ func spinNetwork(t *testing.T, nodesCount int) ([]*networkImpl, []*messageCounte
networkImpls := []*networkImpl{}
msgCounters := []*messageCounter{}
for _, gossipNode := range gossipNodes {
- networkImpl := WrapNetwork(gossipNode).(*networkImpl)
+ networkImpl := WrapNetwork(gossipNode, log).(*networkImpl)
networkImpls = append(networkImpls, networkImpl)
msgCounter := startMessageCounter(networkImpl)
msgCounters = append(msgCounters, msgCounter)
diff --git a/agreement/gossip/network_test.go b/agreement/gossip/network_test.go
index c13dcfdbdb..40105fe0b4 100644
--- a/agreement/gossip/network_test.go
+++ b/agreement/gossip/network_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -28,6 +28,7 @@ import (
"github.com/algorand/go-deadlock"
+ "github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/network"
"github.com/algorand/go-algorand/protocol"
)
@@ -323,7 +324,7 @@ func makewhiteholeNetwork(domain *whiteholeDomain) *whiteholeNetwork {
func spinNetworkImpl(domain *whiteholeDomain) (whiteholeNet *whiteholeNetwork, counter *messageCounter) {
whiteholeNet = makewhiteholeNetwork(domain)
- netImpl := WrapNetwork(whiteholeNet).(*networkImpl)
+ netImpl := WrapNetwork(whiteholeNet, logging.Base()).(*networkImpl)
counter = startMessageCounter(netImpl)
whiteholeNet.Start()
return
diff --git a/agreement/listener.go b/agreement/listener.go
index d356ba456e..c35ac09c61 100644
--- a/agreement/listener.go
+++ b/agreement/listener.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/message.go b/agreement/message.go
index d537c2a2e3..834f39d551 100644
--- a/agreement/message.go
+++ b/agreement/message.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/message_test.go b/agreement/message_test.go
index f64791bab1..9fe889c138 100644
--- a/agreement/message_test.go
+++ b/agreement/message_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/params.go b/agreement/params.go
index c4925bdc02..f677748c1a 100644
--- a/agreement/params.go
+++ b/agreement/params.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/persistence.go b/agreement/persistence.go
index 68045485e1..ce0ee23b0c 100644
--- a/agreement/persistence.go
+++ b/agreement/persistence.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/persistence_test.go b/agreement/persistence_test.go
index 24195695a7..ecbeac21da 100644
--- a/agreement/persistence_test.go
+++ b/agreement/persistence_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/player.go b/agreement/player.go
index 2403d60979..61c1639621 100644
--- a/agreement/player.go
+++ b/agreement/player.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/playerContract.go b/agreement/playerContract.go
index a5cf70da06..9d9df8bba6 100644
--- a/agreement/playerContract.go
+++ b/agreement/playerContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/player_test.go b/agreement/player_test.go
index c2c5828fd6..f2f505406b 100644
--- a/agreement/player_test.go
+++ b/agreement/player_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposal.go b/agreement/proposal.go
index c4c7d1c866..38df0f8f6d 100644
--- a/agreement/proposal.go
+++ b/agreement/proposal.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalManager.go b/agreement/proposalManager.go
index 9500379f25..21013c438f 100644
--- a/agreement/proposalManager.go
+++ b/agreement/proposalManager.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalManagerContract.go b/agreement/proposalManagerContract.go
index d46f2b7e00..d76c728877 100644
--- a/agreement/proposalManagerContract.go
+++ b/agreement/proposalManagerContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalManager_test.go b/agreement/proposalManager_test.go
index 44151b4ad3..eb38161578 100644
--- a/agreement/proposalManager_test.go
+++ b/agreement/proposalManager_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalStore.go b/agreement/proposalStore.go
index 4a8d09ad9c..dff13095be 100644
--- a/agreement/proposalStore.go
+++ b/agreement/proposalStore.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalStoreContract.go b/agreement/proposalStoreContract.go
index f45fa3b14c..ee44335a20 100644
--- a/agreement/proposalStoreContract.go
+++ b/agreement/proposalStoreContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalStore_test.go b/agreement/proposalStore_test.go
index 5a03ebaf44..cf1fabae4d 100644
--- a/agreement/proposalStore_test.go
+++ b/agreement/proposalStore_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -801,3 +801,109 @@ func TestProposalStoreRegressionBlockRedeliveryBug_b29ea57(t *testing.T) {
}
}
+
+func TestProposalStoreRegressionWrongPipelinePeriodBug_39387501(t *testing.T) {
+ var msgV1, msgV2, msgP1, msgP2 message
+ var rv rawVote
+ var propVal proposalValue
+ var propPay proposal
+ curRound := round(10)
+ proposer := basics.Address(randomBlockHash())
+
+ propPay = proposal{
+ unauthenticatedProposal: unauthenticatedProposal{
+ OriginalPeriod: 1,
+ OriginalProposer: proposer,
+ },
+ }
+ propVal = proposalValue{
+ OriginalPeriod: 1,
+ OriginalProposer: proposer,
+ BlockDigest: propPay.Digest(),
+ EncodingDigest: crypto.HashObj(propPay),
+ }
+ rv = rawVote{
+ Sender: proposer,
+ Round: curRound,
+ Period: 1,
+ Proposal: propVal,
+ }
+ msgV1 = message{
+ Tag: protocol.AgreementVoteTag,
+ Vote: vote{R: rv},
+ UnauthenticatedVote: unauthenticatedVote{R: rv},
+ }
+ msgP1 = message{
+ Tag: protocol.ProposalPayloadTag,
+ Proposal: propPay,
+ UnauthenticatedProposal: propPay.u(),
+ }
+
+ propPay = proposal{
+ unauthenticatedProposal: unauthenticatedProposal{
+ OriginalPeriod: 2,
+ OriginalProposer: proposer,
+ },
+ }
+ propVal = proposalValue{
+ OriginalPeriod: 2,
+ OriginalProposer: proposer,
+ BlockDigest: propPay.Digest(),
+ EncodingDigest: crypto.HashObj(propPay),
+ }
+ rv = rawVote{
+ Sender: proposer,
+ Round: curRound,
+ Period: 2,
+ Proposal: propVal,
+ }
+ msgV2 = message{
+ Tag: protocol.AgreementVoteTag,
+ Vote: vote{R: rv},
+ UnauthenticatedVote: unauthenticatedVote{R: rv},
+ }
+ msgP2 = message{
+ Tag: protocol.ProposalPayloadTag,
+ Proposal: propPay,
+ UnauthenticatedProposal: propPay.u(),
+ }
+
+ period1Trigger := newPeriodEvent{Period: 1, Proposal: bottom}
+ propVote1Receipt := messageEvent{T: voteVerified, Input: msgV1}
+ propPayload1Receipt := messageEvent{T: payloadPresent, Input: msgP1}
+ period2Trigger := newPeriodEvent{Period: 2, Proposal: bottom}
+ propVote2Receipt := messageEvent{T: voteVerified, Input: msgV2}
+ propPayload2Receipt := messageEvent{T: payloadPresent, Input: msgP2}
+
+ player := player{Round: curRound}
+
+ var router router
+ rr := routerFixture
+ router = &rr
+
+ var res event
+
+ res = router.dispatch(&proposalStoreTracer, player, period1Trigger, playerMachine, proposalMachineRound, curRound, 1, 0)
+ require.Equal(t, res.t(), none)
+
+ res = router.dispatch(&proposalStoreTracer, player, propVote1Receipt, playerMachine, proposalMachineRound, curRound, 1, 0)
+ require.Equal(t, res.t(), proposalAccepted)
+
+ res = router.dispatch(&proposalStoreTracer, player, period2Trigger, playerMachine, proposalMachineRound, curRound, 2, 0)
+ require.Equal(t, res.t(), none)
+
+ res = router.dispatch(&proposalStoreTracer, player, propVote2Receipt, playerMachine, proposalMachineRound, curRound, 2, 0)
+ require.Equal(t, res.t(), proposalAccepted)
+
+ res = router.dispatch(&proposalStoreTracer, player, propPayload2Receipt, playerMachine, proposalMachineRound, curRound, 2, 0)
+ require.Equal(t, res.t(), payloadPipelined)
+ require.Equal(t, res.(payloadProcessedEvent).Period, period(2))
+
+ res = router.dispatch(&proposalStoreTracer, player, propPayload1Receipt, playerMachine, proposalMachineRound, curRound, 1, 0)
+ if res.(payloadProcessedEvent).Period == 2 {
+ t.Fatalf("bug b29ea57: a proposal corresponding to an old period is erroneously seen as as corresponding to a new period")
+ } else {
+ require.Equal(t, res.t(), payloadPipelined)
+ require.Equal(t, res.(payloadProcessedEvent).Period, period(1))
+ }
+}
diff --git a/agreement/proposalTable.go b/agreement/proposalTable.go
index d0b57556e9..90ed90c65c 100644
--- a/agreement/proposalTable.go
+++ b/agreement/proposalTable.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalTracker.go b/agreement/proposalTracker.go
index 1c2a915a8e..1df9d106d3 100644
--- a/agreement/proposalTracker.go
+++ b/agreement/proposalTracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalTrackerContract.go b/agreement/proposalTrackerContract.go
index 08db14abbd..cff7ed03e9 100644
--- a/agreement/proposalTrackerContract.go
+++ b/agreement/proposalTrackerContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalTracker_test.go b/agreement/proposalTracker_test.go
index 97b1423b82..b0f8348644 100644
--- a/agreement/proposalTracker_test.go
+++ b/agreement/proposalTracker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposal_test.go b/agreement/proposal_test.go
index f09f6df98a..8cb358bd8e 100644
--- a/agreement/proposal_test.go
+++ b/agreement/proposal_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/pseudonode.go b/agreement/pseudonode.go
index a2405bfa85..735e884cb5 100644
--- a/agreement/pseudonode.go
+++ b/agreement/pseudonode.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/pseudonode_test.go b/agreement/pseudonode_test.go
index c78fe8bc46..71645abac2 100644
--- a/agreement/pseudonode_test.go
+++ b/agreement/pseudonode_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/router.go b/agreement/router.go
index f2da85e2e8..ea26462ed3 100644
--- a/agreement/router.go
+++ b/agreement/router.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/selector.go b/agreement/selector.go
index 94dd299914..f081db1e2b 100644
--- a/agreement/selector.go
+++ b/agreement/selector.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/service.go b/agreement/service.go
index ef7e00e293..db937ab94c 100644
--- a/agreement/service.go
+++ b/agreement/service.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/service_test.go b/agreement/service_test.go
index 2311c70431..0de42e5005 100644
--- a/agreement/service_test.go
+++ b/agreement/service_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -18,6 +18,7 @@ package agreement
import (
"bytes"
+ "context"
"crypto/sha256"
"fmt"
"math/rand"
@@ -35,6 +36,7 @@ import (
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/account"
"github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/util/db"
@@ -501,6 +503,8 @@ type activityMonitor struct {
activity chan struct{}
quiet chan struct{}
+
+ cb func(nodeID, map[coserviceType]uint)
}
func makeActivityMonitor() (m *activityMonitor) {
@@ -533,7 +537,6 @@ func (m *activityMonitor) dump() {
m.Lock()
defer m.Unlock()
- fmt.Println("activityMonitor: dump")
for n, s := range m.sums {
fmt.Printf("%v: %v\n", n, s)
}
@@ -558,12 +561,19 @@ func (m *activityMonitor) waitForQuiet() {
}
}
+func (m *activityMonitor) setCallback(cb func(nodeID, map[coserviceType]uint)) {
+ m.Lock()
+ defer m.Unlock()
+ m.cb = cb
+}
+
type amCoserviceListener struct {
id nodeID
+
*activityMonitor
}
-func (l amCoserviceListener) inc(sum uint) {
+func (l amCoserviceListener) inc(sum uint, v map[coserviceType]uint) {
l.Lock()
defer l.Unlock()
@@ -573,9 +583,13 @@ func (l amCoserviceListener) inc(sum uint) {
l.activity <- struct{}{}
l.busy = true
}
+
+ if l.cb != nil {
+ l.cb(l.id, v)
+ }
}
-func (l amCoserviceListener) dec(sum uint) {
+func (l amCoserviceListener) dec(sum uint, v map[coserviceType]uint) {
l.Lock()
defer l.Unlock()
@@ -585,6 +599,10 @@ func (l amCoserviceListener) dec(sum uint) {
l.quiet <- struct{}{}
l.busy = false
}
+
+ if l.cb != nil {
+ l.cb(l.id, v)
+ }
}
// copied from fuzzer/ledger_test.go. We can merge once a refactor seems necessary.
@@ -689,6 +707,11 @@ func (testingRand) Uint64() uint64 {
}
func setupAgreement(t *testing.T, numNodes int, traceLevel traceLevel, ledgerFactory func(map[basics.Address]basics.BalanceRecord) Ledger) (*testingNetwork, Ledger, func(), []*Service, []timers.Clock, []Ledger, *activityMonitor) {
+ var validator testBlockValidator
+ return setupAgreementWithValidator(t, numNodes, traceLevel, validator, ledgerFactory)
+}
+
+func setupAgreementWithValidator(t *testing.T, numNodes int, traceLevel traceLevel, validator BlockValidator, ledgerFactory func(map[basics.Address]basics.BalanceRecord) Ledger) (*testingNetwork, Ledger, func(), []*Service, []timers.Clock, []Ledger, *activityMonitor) {
bufCap := 1000 // max number of buffered messages
// system state setup: keygen, stake initialization
@@ -707,7 +730,6 @@ func setupAgreement(t *testing.T, numNodes int, traceLevel traceLevel, ledgerFac
ledgers := make([]Ledger, numNodes)
dbAccessors := make([]db.Accessor, numNodes)
services := make([]*Service, numNodes)
- var validator testBlockValidator
baseNetwork := makeTestingNetwork(numNodes, bufCap, validator)
am := makeActivityMonitor()
@@ -796,7 +818,7 @@ func (m *coserviceMonitor) clearClock() {
m.c[clockCoserviceType] = 0
if m.coserviceListener != nil {
- m.coserviceListener.dec(m.sum())
+ m.coserviceListener.dec(m.sum(), m.c)
}
}
@@ -1941,3 +1963,180 @@ func TestAgreementLargePeriods(t *testing.T) {
}
}
}
+
+type testSuspendableBlockValidator struct {
+ mu deadlock.Mutex
+ x chan struct{}
+}
+
+func makeTestSuspendableBlockValidator() (v *testSuspendableBlockValidator) {
+ v = new(testSuspendableBlockValidator)
+ v.x = make(chan struct{})
+ close(v.x)
+ return
+}
+
+func (v *testSuspendableBlockValidator) Validate(ctx context.Context, e bookkeeping.Block) (ValidatedBlock, error) {
+ v.mu.Lock()
+ ch := v.x
+ v.mu.Unlock()
+
+ <-ch
+ return testValidatedBlock{Inside: e}, nil
+}
+
+// returns a channel which when closed terminates validation
+func (v *testSuspendableBlockValidator) suspend() chan struct{} {
+ v.mu.Lock()
+ defer v.mu.Unlock()
+ v.x = make(chan struct{})
+ return v.x
+}
+
+func TestAgreementRegression_WrongPeriodPayloadVerificationCancellation_8ba23942(t *testing.T) {
+ numNodes := 5
+ validator := makeTestSuspendableBlockValidator()
+ baseNetwork, baseLedger, cleanupFn, services, clocks, ledgers, activityMonitor := setupAgreementWithValidator(t, numNodes, disabled, validator, makeTestLedger)
+ startRound := baseLedger.NextRound()
+ defer cleanupFn()
+ for i := 0; i < numNodes; i++ {
+ services[i].Start()
+ }
+
+ activityMonitor.waitForActivity()
+ activityMonitor.waitForQuiet()
+ zeroes := expectNewPeriod(clocks, 0)
+
+ // run two rounds
+ for j := 0; j < 2; j++ {
+ zeroes = runRound(clocks, activityMonitor, zeroes)
+ }
+
+ // run round and then start pocketing payloads, suspending validation
+ pocket0 := make(chan multicastParams, 100)
+ ch := validator.suspend()
+ closeFn := baseNetwork.pocketAllCompound(pocket0) // (takes effect next round)
+ {
+ triggerGlobalTimeout(filterTimeout, clocks, activityMonitor)
+ zeroes = expectNewPeriod(clocks, zeroes)
+ }
+
+ // force network into period 1 by failing period 0, entering with bottom and no soft threshold (to prevent proposal value pinning)
+ baseNetwork.dropAllSoftVotes()
+ triggerGlobalTimeout(filterTimeout, clocks, activityMonitor)
+ zeroes = expectNoNewPeriod(clocks, zeroes)
+
+ // resume delivery of payloads in following period
+ baseNetwork.repairAll()
+ closeFn()
+
+ // trigger the deadlineTimeout to enter the new period
+ // release proposed blocks in a controlled manner to prevent oversubscription of verification
+ pocket1 := make(chan multicastParams, 100)
+ closeFn = baseNetwork.pocketAllCompound(pocket1)
+ triggerGlobalTimeout(deadlineTimeout, clocks, activityMonitor)
+ baseNetwork.repairAll()
+ close(pocket1)
+ {
+ // setup synchronization channel
+ var csmu deadlock.Mutex
+ closed := false
+ vch := make(chan struct{})
+ cryptoStates := make(map[nodeID]uint)
+ activityMonitor.setCallback(func(id nodeID, v map[coserviceType]uint) {
+ csmu.Lock()
+ defer csmu.Unlock()
+ cryptoStates[id] = v[cryptoVerifierCoserviceType]
+
+ var s uint
+ for _, c := range cryptoStates {
+ s += c
+ }
+ if s == uint(numNodes-1) && !closed {
+ closed = true
+ close(vch)
+ }
+ })
+
+ baseNetwork.prepareAllMulticast()
+ for p := range pocket1 {
+ baseNetwork.multicast(p.tag, p.data, p.source, p.exclude)
+ }
+ baseNetwork.finishAllMulticast()
+
+ // wait for numNodes-1 pending crypto verification requests
+ <-vch
+ }
+
+ // attack the network with the stale payloads
+ {
+ // setup synchronization channel
+ var csmu deadlock.Mutex
+ closed := false
+ vch := make(chan struct{})
+ cryptoStates := make(map[nodeID]uint)
+ activityMonitor.setCallback(func(id nodeID, v map[coserviceType]uint) {
+ csmu.Lock()
+ defer csmu.Unlock()
+ cryptoStates[id] = v[cryptoVerifierCoserviceType]
+
+ var s uint
+ for _, c := range cryptoStates {
+ s += c
+ }
+ if s == uint(numNodes-1)*2 && !closed {
+ closed = true
+ close(vch)
+ }
+ })
+
+ baseNetwork.prepareAllMulticast()
+ for p := range pocket0 {
+ baseNetwork.multicast(p.tag, p.data, p.source, p.exclude)
+ }
+ baseNetwork.finishAllMulticast()
+
+ // wait for (numNodes-1)*2 pending crypto verification requests
+ <-vch
+ }
+
+ // resume block verification, replay potentially cancelled blocks to ensure good caching
+ // then wait for network to converge (round should terminate at this point)
+ activityMonitor.setCallback(nil)
+ close(ch)
+
+ baseNetwork.prepareAllMulticast()
+ for p := range pocket1 {
+ baseNetwork.multicast(p.tag, p.data, p.source, p.exclude)
+ }
+ baseNetwork.finishAllMulticast()
+
+ zeroes = expectNewPeriod(clocks, zeroes)
+ activityMonitor.waitForQuiet()
+
+ // run two more rounds
+ for j := 0; j < 2; j++ {
+ zeroes = runRound(clocks, activityMonitor, zeroes)
+ }
+ for i := 0; i < numNodes; i++ {
+ services[i].Shutdown()
+ }
+
+ const expectNumRounds = 5
+ for i := 0; i < numNodes; i++ {
+ if ledgers[i].NextRound() != startRound+round(expectNumRounds) {
+ panic("did not progress 5 rounds")
+ }
+ }
+
+ for j := 0; j < expectNumRounds; j++ {
+ ledger := ledgers[0].(*testLedger)
+ reference := ledger.entries[startRound+round(j)].Digest()
+ for i := 0; i < numNodes; i++ {
+ ledger := ledgers[i].(*testLedger)
+ if ledger.entries[startRound+round(j)].Digest() != reference {
+ panic("wrong block confirmed")
+ }
+ }
+ }
+}
diff --git a/agreement/state_machine_test.go b/agreement/state_machine_test.go
index dac15047a7..1bfd81b745 100644
--- a/agreement/state_machine_test.go
+++ b/agreement/state_machine_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/trace.go b/agreement/trace.go
index 92a1cd7d51..cec9301f61 100644
--- a/agreement/trace.go
+++ b/agreement/trace.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/traceTime.go b/agreement/traceTime.go
index ee6c52846c..8698ae13c8 100644
--- a/agreement/traceTime.go
+++ b/agreement/traceTime.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/types.go b/agreement/types.go
index 778643d56b..8c1a6385af 100644
--- a/agreement/types.go
+++ b/agreement/types.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/vote.go b/agreement/vote.go
index 8136c8cfdc..277f736845 100644
--- a/agreement/vote.go
+++ b/agreement/vote.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAggregator.go b/agreement/voteAggregator.go
index 30c51f7e06..1e4d309fb4 100644
--- a/agreement/voteAggregator.go
+++ b/agreement/voteAggregator.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAggregatorContract.go b/agreement/voteAggregatorContract.go
index 83b2c4103c..97f2dfc3fd 100644
--- a/agreement/voteAggregatorContract.go
+++ b/agreement/voteAggregatorContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAggregator_test.go b/agreement/voteAggregator_test.go
index 841769afe7..8282fbf5f2 100644
--- a/agreement/voteAggregator_test.go
+++ b/agreement/voteAggregator_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAuxiliary.go b/agreement/voteAuxiliary.go
index 9d38771caa..2f03ad332d 100644
--- a/agreement/voteAuxiliary.go
+++ b/agreement/voteAuxiliary.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAuxiliaryContract.go b/agreement/voteAuxiliaryContract.go
index 78f9fb532f..cd9240b5d2 100644
--- a/agreement/voteAuxiliaryContract.go
+++ b/agreement/voteAuxiliaryContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAuxiliary_test.go b/agreement/voteAuxiliary_test.go
index 2d99b03c2f..aa44df49c0 100644
--- a/agreement/voteAuxiliary_test.go
+++ b/agreement/voteAuxiliary_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteTracker.go b/agreement/voteTracker.go
index fed5491cd0..5aba4c9509 100644
--- a/agreement/voteTracker.go
+++ b/agreement/voteTracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteTrackerContract.go b/agreement/voteTrackerContract.go
index b3e4b48485..9555be8058 100644
--- a/agreement/voteTrackerContract.go
+++ b/agreement/voteTrackerContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteTracker_test.go b/agreement/voteTracker_test.go
index 795820fedc..2def94b5e5 100644
--- a/agreement/voteTracker_test.go
+++ b/agreement/voteTracker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/vote_test.go b/agreement/vote_test.go
index b943f0469c..e49f3d16a4 100644
--- a/agreement/vote_test.go
+++ b/agreement/vote_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/auction/client/auctionBankRestClient.go b/auction/client/auctionBankRestClient.go
index 7edfd483bc..d18de82d3c 100644
--- a/auction/client/auctionBankRestClient.go
+++ b/auction/client/auctionBankRestClient.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/auction/client/auctionConsoleRestClient.go b/auction/client/auctionConsoleRestClient.go
index e810fb208f..d014c11345 100644
--- a/auction/client/auctionConsoleRestClient.go
+++ b/auction/client/auctionConsoleRestClient.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/auction/logic.go b/auction/logic.go
index 2bad84d104..033356bbb8 100644
--- a/auction/logic.go
+++ b/auction/logic.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/auction/logic_test.go b/auction/logic_test.go
index bb93745cf2..4171822902 100644
--- a/auction/logic_test.go
+++ b/auction/logic_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/auction/messages.go b/auction/messages.go
index 529cee886f..9c6a4419d7 100644
--- a/auction/messages.go
+++ b/auction/messages.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/auction/serializedLogic.go b/auction/serializedLogic.go
index 806153175b..0c08d5c9f3 100644
--- a/auction/serializedLogic.go
+++ b/auction/serializedLogic.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/auction/sigcheck.go b/auction/sigcheck.go
index 2c39dd5b91..7cb5e4506f 100644
--- a/auction/sigcheck.go
+++ b/auction/sigcheck.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/auction/tracker.go b/auction/tracker.go
index a895ad3546..a69dbfd576 100644
--- a/auction/tracker.go
+++ b/auction/tracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/auction/tracker_test.go b/auction/tracker_test.go
index a4b1428418..fd20fa0d46 100644
--- a/auction/tracker_test.go
+++ b/auction/tracker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/buildnumber.dat b/buildnumber.dat
index 00750edc07..b8626c4cff 100644
--- a/buildnumber.dat
+++ b/buildnumber.dat
@@ -1 +1 @@
-3
+4
diff --git a/catchup/pref_test.go b/catchup/pref_test.go
index 2faba82e13..8214a81646 100644
--- a/catchup/pref_test.go
+++ b/catchup/pref_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -54,11 +54,11 @@ func BenchmarkServiceFetchBlocks(b *testing.B) {
require.NoError(b, err)
// Make Service
- syncer := MakeService(logging.Base(), defaultConfig, net, local, nil, new(mockedAuthenticator))
+ syncer := MakeService(logging.Base(), defaultConfig, net, local, nil, new(mockedAuthenticator), nil)
syncer.fetcherFactory = makeMockFactory(&MockedFetcher{ledger: remote, timeout: false, tries: make(map[basics.Round]int), latency: 100 * time.Millisecond, predictable: true})
b.StartTimer()
- syncer.sync()
+ syncer.sync(nil)
b.StopTimer()
local.Close()
require.Equal(b, remote.LastRound(), local.LastRound())
diff --git a/catchup/service.go b/catchup/service.go
index 9bd3d3e600..d906f6b3b1 100644
--- a/catchup/service.go
+++ b/catchup/service.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -18,6 +18,7 @@ package catchup
import (
"context"
+ "fmt"
"sync"
"sync/atomic"
"time"
@@ -36,21 +37,25 @@ import (
)
const catchupPeersForSync = 10
+const blockQueryPeerLimit = 10
+
// this should be at least the number of relays
const catchupRetryLimit = 500
+// PendingUnmatchedCertificate is a single certificate that is being waited upon to have its corresponding block fetched.
+type PendingUnmatchedCertificate struct {
+ Cert agreement.Certificate
+ VoteVerifier *agreement.AsyncVoteVerifier
+}
+
// Ledger represents the interface of a block database which the
// catchup server should interact with.
type Ledger interface {
- NextRound() basics.Round
- LastRound() basics.Round
- Wait(basics.Round) chan struct{}
+ agreement.LedgerReader
AddBlock(bookkeeping.Block, agreement.Certificate) error
- ConsensusParams(basics.Round) (config.ConsensusParams, error)
-
- // only needed to support tests
+ EnsureBlock(block *bookkeeping.Block, c agreement.Certificate)
+ LastRound() basics.Round
Block(basics.Round) (bookkeeping.Block, error)
- BlockCert(basics.Round) (bookkeeping.Block, agreement.Certificate, error)
}
// Service represents the catchup service. Once started and until it is stopped, it ensures that the ledger is up to date with network.
@@ -70,9 +75,13 @@ type Service struct {
// The channel gets closed when the initial sync is complete. This allows for other services to avoid
// the overhead of starting prematurely (before this node is caught-up and can validate messages for example).
- InitialSyncDone chan struct{}
- initialSyncNotified uint32
- protocolErrorLogged bool
+ InitialSyncDone chan struct{}
+ initialSyncNotified uint32
+ protocolErrorLogged bool
+ lastSupportedRound basics.Round
+ unmatchedPendingCertificates <-chan PendingUnmatchedCertificate
+
+ latestRoundFetcherFactory rpcs.FetcherFactory
}
// A BlockAuthenticator authenticates blocks given a certificate.
@@ -89,7 +98,7 @@ type BlockAuthenticator interface {
// MakeService creates a catchup service instance from its constituent components
// If wsf is nil, then fetch over gossip is disabled.
-func MakeService(log logging.Logger, config config.Local, net network.GossipNode, ledger Ledger, wsf *rpcs.WsFetcherService, auth BlockAuthenticator) (s *Service) {
+func MakeService(log logging.Logger, config config.Local, net network.GossipNode, ledger Ledger, wsf *rpcs.WsFetcherService, auth BlockAuthenticator, unmatchedPendingCertificates <-chan PendingUnmatchedCertificate) (s *Service) {
s = &Service{}
s.ctx, s.cancel = context.WithCancel(context.Background())
s.cfg = config
@@ -97,6 +106,9 @@ func MakeService(log logging.Logger, config config.Local, net network.GossipNode
s.ledger = ledger
s.net = net
s.auth = auth
+ s.unmatchedPendingCertificates = unmatchedPendingCertificates
+
+ s.latestRoundFetcherFactory = rpcs.MakeNetworkFetcherFactory(net, blockQueryPeerLimit, wsf)
s.log = log.With("Context", "sync")
s.InitialSyncDone = make(chan struct{})
@@ -172,7 +184,7 @@ func (s *Service) fetchAndWrite(fetcher rpcs.Fetcher, r basics.Round, prevFetchC
// Stop retrying after a while.
if i > catchupRetryLimit {
- s.log.Errorf("fetchAndWrite(%v): failed to fetch block many times", )
+ s.log.Errorf("fetchAndWrite: block retrieval exceeded retry limit")
return false
}
@@ -339,6 +351,27 @@ func (s *Service) pipelinedFetch(seedLookback uint64) {
from := s.ledger.NextRound()
nextRound := from
for ; nextRound < from+basics.Round(parallelRequests); nextRound++ {
+ // If the next round is not supported
+ if s.nextRoundIsNotSupported(nextRound) {
+ // We may get here when (1) The service starts
+ // and gets to an unsupported round. Since in
+ // this loop we do not wait for the requests
+ // to be written to the ledger, there is no
+ // guarantee that the unsupported round will be
+ // stopped in this case.
+
+ // (2) The unsupported round is detected in the
+ // "the rest" loop, but did not cancel because
+ // the last supported round was not yet written
+ // to the ledger.
+
+ // It is sufficient to check only in the first
+ // iteration, however checking in all in favor
+ // of code simplicity.
+ s.handleUnsupportedRound(nextRound)
+ break
+ }
+
currentRoundComplete := make(chan bool, 2)
// len(taskCh) + (# pending writes to completed) increases by 1
taskCh <- s.pipelineCallback(fetcher, nextRound, currentRoundComplete, recentReqs[len(recentReqs)-1], recentReqs[len(recentReqs)-int(seedLookback)])
@@ -357,6 +390,11 @@ func (s *Service) pipelinedFetch(seedLookback uint64) {
completedRounds[round] = true
// fetch rounds we can validate
for completedRounds[nextRound-basics.Round(parallelRequests)] {
+ // If the next round is not supported
+ if s.nextRoundIsNotSupported(nextRound) {
+ s.handleUnsupportedRound(nextRound)
+ return
+ }
delete(completedRounds, nextRound)
currentRoundComplete := make(chan bool, 2)
// len(taskCh) + (# pending writes to completed) increases by 1
@@ -381,7 +419,7 @@ func (s *Service) periodicSync() {
case <-s.ctx.Done():
return
}
- s.sync()
+ s.sync(nil)
stuckInARow := 0
sleepDuration := s.deadlineTimeout
for {
@@ -402,7 +440,10 @@ func (s *Service) periodicSync() {
continue
}
s.log.Info("It's been too long since our ledger advanced; resyncing")
- s.sync()
+ s.sync(nil)
+ case cert := <-s.unmatchedPendingCertificates:
+ // the agreement service has a valid certificate for a block, but not the block itself.
+ s.sync(&cert)
}
if currBlock == s.ledger.LastRound() {
@@ -419,8 +460,9 @@ func (s *Service) periodicSync() {
}
// Syncs the client with the network. sync asks the network for last known block and tries to sync the system
-// up the to the highest number it gets
-func (s *Service) sync() {
+// up the to the highest number it gets. When a certificate is provided, the sync function attempts to keep trying
+// to fetch the matching block or abort when the catchup service exits.
+func (s *Service) sync(cert *PendingUnmatchedCertificate) {
// Only run sync once at a time
// Store start time of sync - in NS so we can compute time.Duration (which is based on NS)
start := time.Now()
@@ -437,14 +479,19 @@ func (s *Service) sync() {
StartRound: uint64(pr),
})
- seedLookback := uint64(2)
- proto, err := s.ledger.ConsensusParams(pr)
- if err != nil {
- s.log.Errorf("catchup: could not get consensus parameters for round %v: $%v", pr, err)
+ if cert == nil {
+ seedLookback := uint64(2)
+ proto, err := s.ledger.ConsensusParams(pr)
+ if err != nil {
+ s.log.Errorf("catchup: could not get consensus parameters for round %v: $%v", pr, err)
+ } else {
+ seedLookback = proto.SeedLookback
+ }
+ s.pipelinedFetch(seedLookback)
} else {
- seedLookback = proto.SeedLookback
+ // we want to fetch a single round. no need to be concerned about lookback.
+ s.fetchRound(cert.Cert, cert.VoteVerifier)
}
- s.pipelinedFetch(seedLookback)
initSync := false
@@ -464,3 +511,109 @@ func (s *Service) sync() {
s.log.Infof("Catchup Service: finished catching up, now at round %v (previously %v). Total time catching up %v.", s.ledger.LastRound(), pr, elapsedTime)
}
+
+// TODO this doesn't actually use the digest from cert!
+func (s *Service) fetchRound(cert agreement.Certificate, verifier *agreement.AsyncVoteVerifier) {
+ blockHash := bookkeeping.BlockHash(cert.Proposal.BlockDigest) // semantic digest (i.e., hash of the block header), not byte-for-byte digest
+ fetcher := s.latestRoundFetcherFactory.NewOverGossip(protocol.UniEnsBlockReqTag)
+ defer func() {
+ fetcher.Close()
+ }()
+ for s.ledger.LastRound() < cert.Round {
+ if fetcher.OutOfPeers(cert.Round) {
+ fetcher.Close()
+ // refresh peers and try again
+ logging.Base().Warn("fetchRound found no outgoing peers")
+ s.net.RequestConnectOutgoing(true, s.ctx.Done())
+ fetcher = s.latestRoundFetcherFactory.NewOverGossip(protocol.UniEnsBlockReqTag)
+ }
+ // Ask the fetcher to get the block somehow
+ block, fetchedCert, rpcc, err := s.innerFetch(fetcher, cert.Round)
+
+ if err != nil {
+ select {
+ case <-s.ctx.Done():
+ logging.Base().Debugf("fetchRound was asked to quit before we could acquire the block")
+ return
+ default:
+ }
+ logging.Base().Warnf("fetchRound could not acquire block, fetcher errored out: %v", err)
+ continue
+ }
+ rpcc.Close()
+
+ if block.Hash() == blockHash && block.ContentsMatchHeader() {
+ s.ledger.EnsureBlock(block, cert)
+ return
+ }
+ // Otherwise, fetcher gave us the wrong block
+ logging.Base().Warnf("fetcher gave us bad/wrong block (for round %d): fetched hash %v; want hash %v", cert.Round, block.Hash(), blockHash)
+
+ // As a failsafe, if the cert we fetched is valid but for the wrong block, panic as loudly as possible
+ if cert.Round == fetchedCert.Round &&
+ cert.Proposal.BlockDigest != fetchedCert.Proposal.BlockDigest &&
+ fetchedCert.Authenticate(*block, s.ledger, verifier) == nil {
+ s := "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+ s += "!!!!!!!!!! FORK DETECTED !!!!!!!!!!!\n"
+ s += "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+ s += "fetchRound called with a cert authenticating block with hash %v.\n"
+ s += "We fetched a valid cert authenticating a different block, %v. This indicates a fork.\n\n"
+ s += "Cert from our agreement service:\n%#v\n\n"
+ s += "Cert from the fetcher:\n%#v\n\n"
+ s += "Block from the fetcher:\n%#v\n\n"
+ s += "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+ s += "!!!!!!!!!! FORK DETECTED !!!!!!!!!!!\n"
+ s += "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+ s = fmt.Sprintf(s, cert.Proposal.BlockDigest, fetchedCert.Proposal.BlockDigest, cert, fetchedCert, block)
+ fmt.Println(s)
+ logging.Base().Error(s)
+ }
+ }
+}
+
+// nextRoundIsNotSupported returns true if the next round upgrades to a protocol version
+// which is not supported.
+// In case of an error, it returns false
+func (s *Service) nextRoundIsNotSupported(nextRound basics.Round) bool {
+ lastLedgerRound := s.ledger.LastRound()
+ supportedUpgrades := config.Consensus
+
+ block, error := s.ledger.Block(lastLedgerRound)
+ if error != nil {
+ s.log.Errorf("nextRoundIsNotSupported: could not retrieve last block (%d) from the ledger.", lastLedgerRound)
+ return false
+ }
+ bh := block.BlockHeader
+ _, isSupportedUpgrade := supportedUpgrades[bh.NextProtocol]
+
+ if bh.NextProtocolSwitchOn > 0 && !isSupportedUpgrade {
+ // Save the last supported round number
+ // It is not necessary to check bh.NextProtocolSwitchOn < s.lastSupportedRound
+ // since there cannot be two protocol updates scheduled.
+ s.lastSupportedRound = bh.NextProtocolSwitchOn - 1
+
+ if nextRound >= bh.NextProtocolSwitchOn {
+ return true
+ }
+ }
+ return false
+}
+
+// handleUnSupportedRound receives a verified unsupported round: nextUnsupportedRound
+// Checks if the last supported round was added to the ledger, and stops the service.
+func (s *Service) handleUnsupportedRound(nextUnsupportedRound basics.Round) {
+
+ s.log.Infof("Catchup Service: round %d is not approved. Service will stop once the last supported round is added to the ledger.",
+ nextUnsupportedRound)
+
+ // If the next round is an unsupported round, need to stop the
+ // catchup service. Should stop after the last supported round
+ // is added to the ledger.
+ lr := s.ledger.LastRound()
+ // Ledger writes are in order. >= guarantees last supported round is added to the ledger.
+ if lr >= s.lastSupportedRound {
+ s.log.Infof("Catchup Service: finished catching up to the last supported round %d. The subsequent rounds are not supported. Service is stopping.",
+ lr)
+ s.cancel()
+ }
+}
diff --git a/catchup/service_test.go b/catchup/service_test.go
index ee7c264f63..d12d313550 100644
--- a/catchup/service_test.go
+++ b/catchup/service_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -30,8 +30,10 @@ import (
"github.com/algorand/go-algorand/agreement"
"github.com/algorand/go-algorand/components/mocks"
"github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/committee"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/rpcs"
@@ -115,14 +117,15 @@ func (m *MockedFetcher) FetchBlock(ctx context.Context, round basics.Round) (*bo
// Add random delay to get it out of sync
time.Sleep(time.Duration(rand.Int()%50) * time.Millisecond)
}
-
- block, cert, err := m.ledger.BlockCert(round)
+ block, err := m.ledger.Block(round)
if round > m.ledger.LastRound() {
return nil, nil, nil, errors.New("no block")
} else if err != nil {
panic(err)
}
+ var cert agreement.Certificate
+ cert.Proposal.BlockDigest = block.Digest()
return &block, &cert, &m.client, nil
}
@@ -182,10 +185,10 @@ func TestServiceFetchBlocksSameRange(t *testing.T) {
net := &mocks.MockNetwork{}
// Make Service
- syncer := MakeService(logging.Base(), defaultConfig, net, local, nil, &mockedAuthenticator{errorRound: -1})
+ syncer := MakeService(logging.Base(), defaultConfig, net, local, nil, &mockedAuthenticator{errorRound: -1}, nil)
syncer.fetcherFactory = makeMockFactory(&MockedFetcher{ledger: remote, timeout: false, tries: make(map[basics.Round]int)})
- syncer.sync()
+ syncer.sync(nil)
require.Equal(t, remote.LastRound(), local.LastRound())
}
@@ -197,7 +200,7 @@ func TestPeriodicSync(t *testing.T) {
initialLocalRound := local.LastRound()
// Make Service
- s := MakeService(logging.Base(), defaultConfig, &mocks.MockNetwork{}, local, nil, auth)
+ s := MakeService(logging.Base(), defaultConfig, &mocks.MockNetwork{}, local, nil, auth, nil)
s.deadlineTimeout = 2 * time.Second
factory := MockedFetcherFactory{fetcher: &MockedFetcher{ledger: remote, timeout: false, tries: make(map[basics.Round]int)}}
@@ -232,7 +235,7 @@ func TestServiceFetchBlocksOneBlock(t *testing.T) {
net := &mocks.MockNetwork{}
// Make Service
- s := MakeService(logging.Base(), defaultConfig, net, local, nil, &mockedAuthenticator{errorRound: -1})
+ s := MakeService(logging.Base(), defaultConfig, net, local, nil, &mockedAuthenticator{errorRound: -1}, nil)
factory := MockedFetcherFactory{fetcher: &MockedFetcher{ledger: remote, timeout: false, tries: make(map[basics.Round]int)}}
s.fetcherFactory = &factory
@@ -240,7 +243,7 @@ func TestServiceFetchBlocksOneBlock(t *testing.T) {
require.False(t, factory.fetcher.client.closed)
// Fetch blocks
- s.sync()
+ s.sync(nil)
// Asserts that the last block is the one we expect
require.Equal(t, lastRoundAtStart+basics.Round(numBlocks), local.LastRound())
@@ -270,7 +273,7 @@ func TestAbruptWrites(t *testing.T) {
lastRound := local.LastRound()
// Make Service
- s := MakeService(logging.Base(), defaultConfig, &mocks.MockNetwork{}, local, nil, &mockedAuthenticator{errorRound: -1})
+ s := MakeService(logging.Base(), defaultConfig, &mocks.MockNetwork{}, local, nil, &mockedAuthenticator{errorRound: -1}, nil)
factory := MockedFetcherFactory{fetcher: &MockedFetcher{ledger: remote, timeout: false, tries: make(map[basics.Round]int)}}
s.fetcherFactory = &factory
@@ -281,14 +284,16 @@ func TestAbruptWrites(t *testing.T) {
defer wg.Done()
for i := basics.Round(lastRound + 1); i <= basics.Round(numberOfBlocks); i++ {
time.Sleep(time.Duration(rand.Uint32()%5) * time.Millisecond)
- blk, cert, err := remote.BlockCert(i)
+ blk, err := remote.Block(i)
require.NoError(t, err)
+ var cert agreement.Certificate
+ cert.Proposal.BlockDigest = blk.Digest()
err = local.AddBlock(blk, cert)
require.NoError(t, err)
}
}()
- s.sync()
+ s.sync(nil)
require.Equal(t, remote.LastRound(), local.LastRound())
}
@@ -302,11 +307,11 @@ func TestServiceFetchBlocksMultiBlocks(t *testing.T) {
lastRoundAtStart := local.LastRound()
// Make Service
- syncer := MakeService(logging.Base(), defaultConfig, &mocks.MockNetwork{}, local, nil, &mockedAuthenticator{errorRound: -1})
+ syncer := MakeService(logging.Base(), defaultConfig, &mocks.MockNetwork{}, local, nil, &mockedAuthenticator{errorRound: -1}, nil)
syncer.fetcherFactory = &MockedFetcherFactory{fetcher: &MockedFetcher{ledger: remote, timeout: false, tries: make(map[basics.Round]int)}}
// Fetch blocks
- syncer.sync()
+ syncer.sync(nil)
// Asserts that the last block is the one we expect
require.Equal(t, lastRoundAtStart+numberOfBlocks, local.LastRound())
@@ -331,14 +336,132 @@ func TestServiceFetchBlocksMalformed(t *testing.T) {
lastRoundAtStart := local.LastRound()
// Make Service
- s := MakeService(logging.Base(), defaultConfig, &mocks.MockNetwork{}, local, nil, &mockedAuthenticator{errorRound: int(lastRoundAtStart + 1)})
+ s := MakeService(logging.Base(), defaultConfig, &mocks.MockNetwork{}, local, nil, &mockedAuthenticator{errorRound: int(lastRoundAtStart + 1)}, nil)
s.fetcherFactory = &MockedFetcherFactory{fetcher: &MockedFetcher{ledger: remote, timeout: false, tries: make(map[basics.Round]int)}}
- s.sync()
+ s.sync(nil)
require.Equal(t, lastRoundAtStart, local.LastRound())
require.True(t, s.fetcherFactory.(*MockedFetcherFactory).fetcher.client.closed)
}
+func TestOnSwitchToUnSupportedProtocol(t *testing.T) {
+ // Test the interruption in the initial loop
+ // This cannot happen in practice, but is used to test the code.
+ {
+ lastRoundRemote := 5
+ lastRoundLocal := 0
+ roundWithSwitchOn := 0
+ local, remote := helperTestOnSwitchToUnSupportedProtocol(t, lastRoundRemote, lastRoundLocal, roundWithSwitchOn, 0)
+
+ // Last supported round is 0, but is guaranteed
+ // to stop after 2 rounds.
+
+ // SeedLookback is 2, which allows two parallel fetches.
+ // i.e. rounds 1 and 2 may be simultaneously fetched.
+ require.Less(t, int(local.LastRound()), 3)
+ require.Equal(t, lastRoundRemote, int(remote.LastRound()))
+ }
+
+ // Test the interruption in "the rest" loop
+ {
+ lastRoundRemote := 10
+ lastRoundLocal := 7
+ roundWithSwitchOn := 5
+ local, remote := helperTestOnSwitchToUnSupportedProtocol(t, lastRoundRemote, lastRoundLocal, roundWithSwitchOn, 0)
+ for r := 1; r <= lastRoundLocal; r++ {
+ blk, err := local.Block(basics.Round(r))
+ require.NoError(t, err)
+ require.Equal(t, r, int(blk.Round()))
+ }
+ require.Equal(t, lastRoundLocal, int(local.LastRound()))
+ require.Equal(t, lastRoundRemote, int(remote.LastRound()))
+ }
+
+ // Test the interruption with short notice (less than
+ // SeedLookback or the number of parallel fetches which in the
+ // test is the same: 2)
+
+ // This can not happen in practice, because there will be
+ // enough rounds for the protocol upgrade notice.
+ {
+ lastRoundRemote := 14
+ lastRoundLocal := 7
+ roundWithSwitchOn := 7
+ local, remote := helperTestOnSwitchToUnSupportedProtocol(t, lastRoundRemote, lastRoundLocal, roundWithSwitchOn, 0)
+ for r := 1; r <= lastRoundLocal; r = r + 1 {
+ blk, err := local.Block(basics.Round(r))
+ require.NoError(t, err)
+ require.Equal(t, r, int(blk.Round()))
+ }
+ // Since round with switch on (7) can be fetched
+ // Simultaneously with round 8, round 8 might also be
+ // fetched.
+ require.Less(t, int(local.LastRound()), lastRoundLocal+2)
+ require.Equal(t, lastRoundRemote, int(remote.LastRound()))
+ }
+
+ // Test the interruption with short notice (less than
+ // SeedLookback or the number of parallel fetches which in the
+ // test is the same: 2)
+
+ // This case is a variation of the previous case. This may
+ // happen when the catchup service restart at the round when
+ // an upgrade happens.
+ {
+ lastRoundRemote := 14
+ lastRoundLocal := 7
+ roundWithSwitchOn := 7
+ roundsAlreadyInLocal := 8 // round 0 -> 7
+
+ local, remote := helperTestOnSwitchToUnSupportedProtocol(
+ t,
+ lastRoundRemote,
+ lastRoundLocal,
+ roundWithSwitchOn,
+ roundsAlreadyInLocal)
+
+ for r := 1; r <= lastRoundLocal; r = r + 1 {
+ blk, err := local.Block(basics.Round(r))
+ require.NoError(t, err)
+ require.Equal(t, r, int(blk.Round()))
+ }
+ // Since round with switch on (7) is already in the
+ // ledger, round 8 will not be fetched.
+ require.Equal(t, int(local.LastRound()), lastRoundLocal)
+ require.Equal(t, lastRoundRemote, int(remote.LastRound()))
+ }
+}
+
+func helperTestOnSwitchToUnSupportedProtocol(
+ t *testing.T,
+ lastRoundRemote,
+ lastRoundLocal,
+ roundWithSwitchOn,
+ roundsToCopy int) (local, remote Ledger) {
+
+ // Make Ledger
+ mRemote, mLocal := testingenvWithUpgrade(t, lastRoundRemote, roundWithSwitchOn, lastRoundLocal+1)
+
+ // Copy rounds to local
+ for r := 1; r < roundsToCopy; r++ {
+ mLocal.blocks = append(mLocal.blocks, mRemote.blocks[r])
+ }
+
+ local = mLocal
+ remote = Ledger(mRemote)
+
+ // Make Service
+ s := MakeService(logging.Base(), defaultConfig, &mocks.MockNetwork{}, local, nil, &mockedAuthenticator{errorRound: -1}, nil)
+ s.deadlineTimeout = 2 * time.Second
+
+ s.fetcherFactory = &MockedFetcherFactory{fetcher: &MockedFetcher{ledger: remote, timeout: false, tries: make(map[basics.Round]int)}}
+ s.Start()
+ defer s.Stop()
+
+ <-s.done
+ return local, remote
+}
+
const defaultRewardUnit = 1e6
type mockedLedger struct {
@@ -411,15 +534,6 @@ func (m *mockedLedger) Wait(r basics.Round) chan struct{} {
return m.chans[r]
}
-func (m *mockedLedger) BlockCert(r basics.Round) (bookkeeping.Block, agreement.Certificate, error) {
- m.mu.Lock()
- defer m.mu.Unlock()
- if r > m.lastRound() {
- return bookkeeping.Block{}, agreement.Certificate{}, errors.New("mockedLedger.BlockCert: round too high")
- }
- return m.blocks[r], agreement.Certificate{}, nil
-}
-
func (m *mockedLedger) Block(r basics.Round) (bookkeeping.Block, error) {
m.mu.Lock()
defer m.mu.Unlock()
@@ -429,6 +543,26 @@ func (m *mockedLedger) Block(r basics.Round) (bookkeeping.Block, error) {
return m.blocks[r], nil
}
+func (m *mockedLedger) BalanceRecord(basics.Round, basics.Address) (basics.BalanceRecord, error) {
+ return basics.BalanceRecord{}, errors.New("not needed for mockedLedger")
+}
+func (m *mockedLedger) Circulation(basics.Round) (basics.MicroAlgos, error) {
+ return basics.MicroAlgos{}, errors.New("not needed for mockedLedger")
+}
+func (m *mockedLedger) ConsensusVersion(basics.Round) (protocol.ConsensusVersion, error) {
+ return protocol.ConsensusCurrentVersion, nil
+}
+func (m *mockedLedger) EnsureBlock(block *bookkeeping.Block, c agreement.Certificate) {
+ m.AddBlock(*block, c)
+}
+func (m *mockedLedger) Seed(basics.Round) (committee.Seed, error) {
+ return committee.Seed{}, errors.New("not needed for mockedLedger")
+}
+
+func (m *mockedLedger) LookupDigest(basics.Round) (crypto.Digest, error) {
+ return crypto.Digest{}, errors.New("not needed for mockedLedger")
+}
+
func testingenv(t testing.TB, numBlocks int) (ledger, emptyLedger Ledger) {
mLedger := new(mockedLedger)
mEmptyLedger := new(mockedLedger)
@@ -445,3 +579,66 @@ func testingenv(t testing.TB, numBlocks int) (ledger, emptyLedger Ledger) {
return mLedger, mEmptyLedger
}
+
+func testingenvWithUpgrade(
+ t testing.TB,
+ numBlocks,
+ roundWithSwitchOn,
+ upgradeRound int) (ledger, emptyLedger *mockedLedger) {
+
+ mLedger := new(mockedLedger)
+ mEmptyLedger := new(mockedLedger)
+
+ var blk bookkeeping.Block
+ blk.CurrentProtocol = protocol.ConsensusCurrentVersion
+ mLedger.blocks = append(mLedger.blocks, blk)
+ mEmptyLedger.blocks = append(mEmptyLedger.blocks, blk)
+
+ for i := 1; i <= numBlocks; i++ {
+ blk = bookkeeping.MakeBlock(blk.BlockHeader)
+ if roundWithSwitchOn <= i {
+ modifierBlk := blk
+ blkh := &modifierBlk.BlockHeader
+ blkh.NextProtocolSwitchOn = basics.Round(upgradeRound)
+ blkh.NextProtocol = protocol.ConsensusVersion("some-unsupported-protocol")
+
+ mLedger.blocks = append(mLedger.blocks, modifierBlk)
+ continue
+ }
+
+ mLedger.blocks = append(mLedger.blocks, blk)
+ }
+
+ return mLedger, mEmptyLedger
+}
+
+type MockVoteVerifier struct{}
+
+func (avv *MockVoteVerifier) Quit() {
+}
+func (avv *MockVoteVerifier) Parallelism() int {
+ return 1
+}
+
+func TestCatchupUnmatchedCertificate(t *testing.T) {
+ // Make Ledger
+ remote, local := testingenv(t, 10)
+
+ lastRoundAtStart := local.LastRound()
+
+ // Make Service
+ s := MakeService(logging.Base(), defaultConfig, &mocks.MockNetwork{}, local, nil, &mockedAuthenticator{errorRound: int(lastRoundAtStart + 1)}, nil)
+ s.latestRoundFetcherFactory = &MockedFetcherFactory{fetcher: &MockedFetcher{ledger: remote, timeout: false, tries: make(map[basics.Round]int)}}
+ for roundNumber := 2; roundNumber < 10; roundNumber += 3 {
+ pc := &PendingUnmatchedCertificate{
+ Cert: agreement.Certificate{
+ Round: basics.Round(roundNumber),
+ },
+ VoteVerifier: agreement.MakeAsyncVoteVerifier(nil),
+ }
+ block, _ := remote.Block(basics.Round(roundNumber))
+ pc.Cert.Proposal.BlockDigest = block.Digest()
+ s.sync(pc)
+ require.True(t, s.latestRoundFetcherFactory.(*MockedFetcherFactory).fetcher.client.closed)
+ }
+}
diff --git a/cmd/algocfg/datadir.go b/cmd/algocfg/datadir.go
index b71947d057..8091223143 100644
--- a/cmd/algocfg/datadir.go
+++ b/cmd/algocfg/datadir.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/getCommand.go b/cmd/algocfg/getCommand.go
index de7b5a1ed1..cc14c585ab 100644
--- a/cmd/algocfg/getCommand.go
+++ b/cmd/algocfg/getCommand.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/main.go b/cmd/algocfg/main.go
index c2dae93fea..ce0398799d 100644
--- a/cmd/algocfg/main.go
+++ b/cmd/algocfg/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/messages.go b/cmd/algocfg/messages.go
index ed8b7e6a78..91596d1deb 100644
--- a/cmd/algocfg/messages.go
+++ b/cmd/algocfg/messages.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/report.go b/cmd/algocfg/report.go
index 02953817a9..d5bab7ea0c 100644
--- a/cmd/algocfg/report.go
+++ b/cmd/algocfg/report.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/resetCommand.go b/cmd/algocfg/resetCommand.go
index a55ff52a23..8118667ce6 100644
--- a/cmd/algocfg/resetCommand.go
+++ b/cmd/algocfg/resetCommand.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/setCommand.go b/cmd/algocfg/setCommand.go
index 2a45d75bb8..051ef178e5 100644
--- a/cmd/algocfg/setCommand.go
+++ b/cmd/algocfg/setCommand.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -119,6 +119,15 @@ func setFieldValue(field reflect.Value, value string) error {
// NOTE: We do not enforce bitsize
field.SetFloat(val)
+ case reflect.Bool:
+ switch value {
+ case "t", "true", "True", "TRUE", "1":
+ field.SetBool(true)
+ case "f", "false", "False", "FALSE", "0":
+ field.SetBool(false)
+ default:
+ return fmt.Errorf("could not parse value %#v as bool", value)
+ }
default:
return fmt.Errorf("unsupported parameter type '%s' - unable to set value", k)
}
diff --git a/cmd/algod/main.go b/cmd/algod/main.go
index 575f2bf0cc..189581847f 100644
--- a/cmd/algod/main.go
+++ b/cmd/algod/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -153,9 +153,16 @@ func main() {
}
defer fileLock.Unlock()
+ cfg, err := config.LoadConfigFromDisk(absolutePath)
+ if err != nil && !os.IsNotExist(err) {
+ // log is not setup yet, this will log to stderr
+ log.Fatalf("Cannot load config: %v", err)
+ }
+
// Enable telemetry hook in daemon to send logs to cloud
// If ALGOTEST env variable is set, telemetry is disabled - allows disabling telemetry for tests
isTest := os.Getenv("ALGOTEST") != ""
+ remoteTelemetryEnabled := false
if !isTest {
telemetryConfig, err := logging.EnsureTelemetryConfig(&dataDir, genesis.ID())
if err != nil {
@@ -166,10 +173,13 @@ func main() {
os.Exit(1)
}
+ telemetryConfig.SendToLog = telemetryConfig.SendToLog || cfg.TelemetryToLog
+
// Apply telemetry override.
telemetryConfig.Enable = logging.TelemetryOverride(*telemetryOverride)
+ remoteTelemetryEnabled = telemetryConfig.Enable
- if telemetryConfig.Enable {
+ if telemetryConfig.Enable || telemetryConfig.SendToLog {
// If session GUID specified, use it.
if *sessionGUID != "" {
if len(*sessionGUID) == 36 {
@@ -188,12 +198,6 @@ func main() {
Genesis: genesis,
}
- cfg, err := config.LoadConfigFromDisk(s.RootPath)
- if err != nil && !os.IsNotExist(err) {
- // log is not setup yet, this will log to stderr
- log.Fatalf("Cannot load config: %v", err)
- }
-
// Generate a REST API token if one was not provided
apiToken, wroteNewToken, err := tokens.ValidateOrGenerateAPIToken(s.RootPath, tokens.AlgodTokenFilename)
@@ -269,7 +273,7 @@ func main() {
cfgCopy.DNSBootstrapID = telemetryDNSBootstrapID
// If the telemetry URI is not set, periodically check SRV records for new telemetry URI
- if log.GetTelemetryURI() == "" {
+ if remoteTelemetryEnabled && log.GetTelemetryURI() == "" {
network.StartTelemetryURIUpdateService(time.Minute, cfg, s.Genesis.Network, log, done)
}
diff --git a/cmd/algofix/deadlock.go b/cmd/algofix/deadlock.go
index dfa7e58119..780cb5c5cf 100644
--- a/cmd/algofix/deadlock.go
+++ b/cmd/algofix/deadlock.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/blockWatcher.go b/cmd/algoh/blockWatcher.go
index c7eaee2398..cda98b2209 100644
--- a/cmd/algoh/blockWatcher.go
+++ b/cmd/algoh/blockWatcher.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/blockWatcher_test.go b/cmd/algoh/blockWatcher_test.go
index b9110d3ba8..7222d1bd48 100644
--- a/cmd/algoh/blockWatcher_test.go
+++ b/cmd/algoh/blockWatcher_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/blockstats.go b/cmd/algoh/blockstats.go
index c6874470a9..48b19fc3fe 100644
--- a/cmd/algoh/blockstats.go
+++ b/cmd/algoh/blockstats.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/blockstats_test.go b/cmd/algoh/blockstats_test.go
index 348ff7c570..30dd922713 100644
--- a/cmd/algoh/blockstats_test.go
+++ b/cmd/algoh/blockstats_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/client.go b/cmd/algoh/client.go
index 8d9c799b50..70ec162619 100644
--- a/cmd/algoh/client.go
+++ b/cmd/algoh/client.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/deadman.go b/cmd/algoh/deadman.go
index aa7d7cdb80..33320f7306 100644
--- a/cmd/algoh/deadman.go
+++ b/cmd/algoh/deadman.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/eventsender.go b/cmd/algoh/eventsender.go
index aa269b18ee..e9836883f8 100644
--- a/cmd/algoh/eventsender.go
+++ b/cmd/algoh/eventsender.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/main.go b/cmd/algoh/main.go
index 35e605ce44..bc533cc970 100644
--- a/cmd/algoh/main.go
+++ b/cmd/algoh/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/mockClient.go b/cmd/algoh/mockClient.go
index 8b8e18bb81..b9d71567b3 100644
--- a/cmd/algoh/mockClient.go
+++ b/cmd/algoh/mockClient.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/common.go b/cmd/algokey/common.go
index ea117fb0fb..2bccef2f68 100644
--- a/cmd/algokey/common.go
+++ b/cmd/algokey/common.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/export.go b/cmd/algokey/export.go
index 141145bebb..9468cffd61 100644
--- a/cmd/algokey/export.go
+++ b/cmd/algokey/export.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/generate.go b/cmd/algokey/generate.go
index 58c5356b42..774797b9de 100644
--- a/cmd/algokey/generate.go
+++ b/cmd/algokey/generate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/import.go b/cmd/algokey/import.go
index 2eeebdd07f..c43cdc3f7e 100644
--- a/cmd/algokey/import.go
+++ b/cmd/algokey/import.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/main.go b/cmd/algokey/main.go
index 6f1c40b03d..88c3b0eb80 100644
--- a/cmd/algokey/main.go
+++ b/cmd/algokey/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -21,6 +21,7 @@ import (
"os"
"github.com/spf13/cobra"
+ "github.com/spf13/cobra/doc"
)
var rootCmd = &cobra.Command{
@@ -43,6 +44,17 @@ func init() {
}
func main() {
+ // Hidden command to generate docs in a given directory
+ // algokey generate-docs [path]
+ if len(os.Args) == 3 && os.Args[1] == "generate-docs" {
+ err := doc.GenMarkdownTree(rootCmd, os.Args[2])
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ os.Exit(0)
+ }
+
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
diff --git a/cmd/algokey/multisig.go b/cmd/algokey/multisig.go
index 1075eea537..c8bd31306d 100644
--- a/cmd/algokey/multisig.go
+++ b/cmd/algokey/multisig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/part.go b/cmd/algokey/part.go
index 6c3109ab7f..982585cc43 100644
--- a/cmd/algokey/part.go
+++ b/cmd/algokey/part.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/sign.go b/cmd/algokey/sign.go
index 3d8d423302..c124a24475 100644
--- a/cmd/algokey/sign.go
+++ b/cmd/algokey/sign.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algons/commands.go b/cmd/algons/commands.go
index 52a299cedb..4d200e8278 100644
--- a/cmd/algons/commands.go
+++ b/cmd/algons/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algons/dnsCmd.go b/cmd/algons/dnsCmd.go
index 91a5499bee..c41e012891 100644
--- a/cmd/algons/dnsCmd.go
+++ b/cmd/algons/dnsCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -203,7 +203,7 @@ func doAddDNS(from string, to string) (err error) {
} else {
recordType = "CNAME"
}
- cloudflareDNS.SetDNSRecord(context.Background(), recordType, from, to, cloudflare.AutomaticTTL, priority, proxied)
+ err = cloudflareDNS.SetDNSRecord(context.Background(), recordType, from, to, cloudflare.AutomaticTTL, priority, proxied)
return
}
diff --git a/cmd/algorelay/commands.go b/cmd/algorelay/commands.go
index 7298ceec71..c3cad78e65 100644
--- a/cmd/algorelay/commands.go
+++ b/cmd/algorelay/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algorelay/eb/eb.go b/cmd/algorelay/eb/eb.go
index ad5b397639..8cb8c3e56d 100644
--- a/cmd/algorelay/eb/eb.go
+++ b/cmd/algorelay/eb/eb.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algorelay/relayCmd.go b/cmd/algorelay/relayCmd.go
index cea88c2c86..bebc628b99 100644
--- a/cmd/algorelay/relayCmd.go
+++ b/cmd/algorelay/relayCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/auctionbank/main.go b/cmd/auctionbank/main.go
index 3a8d5bf05d..2677345599 100644
--- a/cmd/auctionbank/main.go
+++ b/cmd/auctionbank/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/auctionbank/txhandle.go b/cmd/auctionbank/txhandle.go
index 4f6b043268..2502a9a853 100644
--- a/cmd/auctionbank/txhandle.go
+++ b/cmd/auctionbank/txhandle.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/auctionconsole/main.go b/cmd/auctionconsole/main.go
index c362bfa5c9..805e82e76f 100644
--- a/cmd/auctionconsole/main.go
+++ b/cmd/auctionconsole/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/auctionmaster/main.go b/cmd/auctionmaster/main.go
index 12b722a19c..9072e1e023 100644
--- a/cmd/auctionmaster/main.go
+++ b/cmd/auctionmaster/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/auctionmaster/util.go b/cmd/auctionmaster/util.go
index 84dce6d530..dc62d05bbd 100644
--- a/cmd/auctionmaster/util.go
+++ b/cmd/auctionmaster/util.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/auctionminion/main.go b/cmd/auctionminion/main.go
index 2e9eda2f94..9d7b3e1c99 100644
--- a/cmd/auctionminion/main.go
+++ b/cmd/auctionminion/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/buildtools/commands.go b/cmd/buildtools/commands.go
index 925f0074a5..82b577d778 100644
--- a/cmd/buildtools/commands.go
+++ b/cmd/buildtools/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/buildtools/genesis.go b/cmd/buildtools/genesis.go
index 0d70d4841e..324f50d350 100644
--- a/cmd/buildtools/genesis.go
+++ b/cmd/buildtools/genesis.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchupsrv/download.go b/cmd/catchupsrv/download.go
index f6d056edb7..7863de2554 100644
--- a/cmd/catchupsrv/download.go
+++ b/cmd/catchupsrv/download.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchupsrv/download_test.go b/cmd/catchupsrv/download_test.go
index 9c2e550a21..cd004c3fc7 100644
--- a/cmd/catchupsrv/download_test.go
+++ b/cmd/catchupsrv/download_test.go
@@ -1,3 +1,19 @@
+// Copyright (C) 2019-2020 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see .
+
package main
import (
diff --git a/cmd/catchupsrv/main.go b/cmd/catchupsrv/main.go
index c230fc4904..e5f1129830 100644
--- a/cmd/catchupsrv/main.go
+++ b/cmd/catchupsrv/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/dbgen/main.go b/cmd/dbgen/main.go
index cdf54166e3..c1002affaa 100644
--- a/cmd/dbgen/main.go
+++ b/cmd/dbgen/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/diagcfg/main.go b/cmd/diagcfg/main.go
index 17b910e36e..029e399144 100644
--- a/cmd/diagcfg/main.go
+++ b/cmd/diagcfg/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/diagcfg/messages.go b/cmd/diagcfg/messages.go
index 71e59ae2e4..16e2d4b255 100644
--- a/cmd/diagcfg/messages.go
+++ b/cmd/diagcfg/messages.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/diagcfg/metric.go b/cmd/diagcfg/metric.go
index 9e6440169f..80d1b597f6 100644
--- a/cmd/diagcfg/metric.go
+++ b/cmd/diagcfg/metric.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/diagcfg/telemetry.go b/cmd/diagcfg/telemetry.go
index d07f9f7c2a..bc832a46f4 100644
--- a/cmd/diagcfg/telemetry.go
+++ b/cmd/diagcfg/telemetry.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/dispenser/server.go b/cmd/dispenser/server.go
index 033754aa0f..a4d2203e73 100644
--- a/cmd/dispenser/server.go
+++ b/cmd/dispenser/server.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/genesis/newgenesis.go b/cmd/genesis/newgenesis.go
index 8e0ce9eb35..bba3d8d3b7 100644
--- a/cmd/genesis/newgenesis.go
+++ b/cmd/genesis/newgenesis.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/account.go b/cmd/goal/account.go
index c9f37a024b..157ca64367 100644
--- a/cmd/goal/account.go
+++ b/cmd/goal/account.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -245,7 +245,7 @@ var accountMultisigCmd = &cobra.Command{
var renameCmd = &cobra.Command{
Use: "rename [old name] [new name]",
Short: "Change the human-friendly name of an account",
- Long: `Change the human-friendly name of an account`,
+ Long: `Change the human-friendly name of an account. This is a local-only name, it is not stored on the network.`,
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
accountList := makeAccountsList(ensureSingleDataDir())
@@ -325,6 +325,7 @@ var newCmd = &cobra.Command{
var deleteCmd = &cobra.Command{
Use: "delete",
Short: "Delete an account",
+ Long: `Delete the indicated account. The key management daemon will no longer know about this account, although the account will still exist on the network.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
dataDir := ensureSingleDataDir()
@@ -388,6 +389,7 @@ var newMultisigCmd = &cobra.Command{
var deleteMultisigCmd = &cobra.Command{
Use: "delete",
Short: "Delete a multisig account",
+ Long: `Delete a multisig account. Like ordinary account delete, the local node will no longer know about the account, but it may still exist on the network.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
dataDir := ensureSingleDataDir()
@@ -408,6 +410,7 @@ var deleteMultisigCmd = &cobra.Command{
var infoMultisigCmd = &cobra.Command{
Use: "info",
Short: "Print information about a multisig account",
+ Long: `Print information about a multisig account, such as its Algorand multisig version, or the number of keys needed to validate a transaction from the multisig account.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
dataDir := ensureSingleDataDir()
@@ -431,7 +434,7 @@ var infoMultisigCmd = &cobra.Command{
var listCmd = &cobra.Command{
Use: "list",
Short: "Show the list of Algorand accounts on this machine",
- Long: `Show the list of Algorand accounts on this machine. Also indicates whether the account is [offline] or [online], and if the account is the default account for goal.`,
+ Long: `Show the list of Algorand accounts on this machine. Indicates whether the account is [offline] or [online], and if the account is the default account for goal. Also displays balances and asset information.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
dataDir := ensureSingleDataDir()
@@ -513,8 +516,8 @@ var listCmd = &cobra.Command{
var balanceCmd = &cobra.Command{
Use: "balance",
- Short: "Retrieve the balance for the specified account, in microAlgos",
- Long: `Retrieve the balance for the specified account, in microAlgos`,
+ Short: "Retrieve the balances for the specified account",
+ Long: `Retrieve the balance record for the specified account, displaying both algos and assets. Algo balance is displayed in microAlgos.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
dataDir := ensureSingleDataDir()
@@ -531,7 +534,7 @@ var balanceCmd = &cobra.Command{
var rewardsCmd = &cobra.Command{
Use: "rewards",
Short: "Retrieve the rewards for the specified account",
- Long: `Retrieve the rewards for the specified account`,
+ Long: `Retrieve the rewards for the specified account, including pending rewards. Units displayed are microAlgos.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
dataDir := ensureSingleDataDir()
@@ -636,7 +639,7 @@ func changeAccountOnlineStatus(acct string, part *algodAcct.Participation, goOnl
var addParticipationKeyCmd = &cobra.Command{
Use: "addpartkey",
Short: "Generate a participation key for the specified account",
- Long: `Generate a participation key for the specified account`,
+ Long: `Generate a participation key for the specified account. This participation key can then be used for going online and participating in consensus.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
dataDir := ensureSingleDataDir()
@@ -690,7 +693,7 @@ No --delete-input flag specified, exiting without installing key.`)
var renewParticipationKeyCmd = &cobra.Command{
Use: "renewpartkey",
Short: "Renew an account's participation key",
- Long: `Generate a participation key for the specified account and register it`,
+ Long: `Generate a participation key for the specified account and issue the necessary transaction to register it.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
dataDir := ensureSingleDataDir()
@@ -755,7 +758,7 @@ func generateAndRegisterPartKey(address string, currentRound, lastValidRound uin
var renewAllParticipationKeyCmd = &cobra.Command{
Use: "renewallpartkeys",
Short: "Renew all existing participation keys",
- Long: `Generate new participation keys for all existing accounts with participation keys and register them`,
+ Long: `Generate new participation keys for all existing accounts with participation keys and issue the necessary transactions to register them.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
onDataDirs(func(dataDir string) {
@@ -835,6 +838,7 @@ func renewPartKeysInDir(dataDir string, lastValidRound uint64, fee uint64, lease
var listParticipationKeysCmd = &cobra.Command{
Use: "listpartkeys",
Short: "List participation keys",
+ Long: `List all participation keys tracked by algod, with additional information such as key validity period.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
dataDir := ensureSingleDataDir()
@@ -941,7 +945,7 @@ var importCmd = &cobra.Command{
var exportCmd = &cobra.Command{
Use: "export",
Short: "Export an account key for use with account import",
- Long: "Export an account mnemonic seed, for use with account import. This exports the seed for a single account and should not be confused with the wallet mnemonic.",
+ Long: "Export an account mnemonic seed, for use with account import. This exports the seed for a single account and should NOT be confused with the wallet mnemonic.",
Run: func(cmd *cobra.Command, args []string) {
dataDir := ensureSingleDataDir()
client := ensureKmdClient(dataDir)
@@ -1070,7 +1074,7 @@ type partkeyInfo struct {
var partkeyInfoCmd = &cobra.Command{
Use: "partkeyinfo",
Short: "Output details about all available part keys",
- Long: `Output details about all available part keys in the specified data directory(ies)`,
+ Long: `Output details about all available part keys in the specified data directory(ies), such as key validity period.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
diff --git a/cmd/goal/accountsList.go b/cmd/goal/accountsList.go
index aff004ca05..e82e0a5ff0 100644
--- a/cmd/goal/accountsList.go
+++ b/cmd/goal/accountsList.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/asset.go b/cmd/goal/asset.go
index a5b0ddc9ae..a31557fef6 100644
--- a/cmd/goal/asset.go
+++ b/cmd/goal/asset.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -211,6 +211,7 @@ func lookupAssetID(cmd *cobra.Command, creator string, client libgoal.Client) {
var createAssetCmd = &cobra.Command{
Use: "create",
Short: "Create an asset",
+ Long: "Post a transaction declaring and issuing a new layer-one asset on the network.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
checkTxValidityPeriodCmdFlags(cmd)
@@ -287,6 +288,7 @@ var createAssetCmd = &cobra.Command{
var destroyAssetCmd = &cobra.Command{
Use: "destroy",
Short: "Destroy an asset",
+ Long: `Issue a transaction deleting an asset from the network. This transaction must be issued by the asset owner, who must hold all outstanding asset tokens.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
checkTxValidityPeriodCmdFlags(cmd)
@@ -354,6 +356,7 @@ var destroyAssetCmd = &cobra.Command{
var configAssetCmd = &cobra.Command{
Use: "config",
Short: "Configure an asset",
+ Long: `Change an asset configuration. This transaction must be issued by the asset manager. This allows any management address to be changed: manager, freezer, reserve, or clawback.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
checkTxValidityPeriodCmdFlags(cmd)
@@ -442,7 +445,7 @@ var configAssetCmd = &cobra.Command{
var sendAssetCmd = &cobra.Command{
Use: "send",
Short: "Transfer assets",
- Long: "Transfer asset holdings. Use a zero self-transfer to add an asset to an account in the first place.",
+ Long: "Transfer asset holdings. An account can begin accepting an asset by issuing a zero-amount asset transfer to itself.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
checkTxValidityPeriodCmdFlags(cmd)
@@ -523,6 +526,7 @@ var sendAssetCmd = &cobra.Command{
var freezeAssetCmd = &cobra.Command{
Use: "freeze",
Short: "Freeze assets",
+ Long: `Freeze or unfreeze assets for a target account. The transaction must be issued by the freeze address for the asset in question.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
checkTxValidityPeriodCmdFlags(cmd)
@@ -601,6 +605,7 @@ func assetDecimalsFmt(amount uint64, decimals uint32) string {
var infoAssetCmd = &cobra.Command{
Use: "info",
Short: "Look up current parameters for an asset",
+ Long: `Look up asset information stored on the network, such as asset creator, management addresses, or asset name.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
dataDir := ensureSingleDataDir()
diff --git a/cmd/goal/clerk.go b/cmd/goal/clerk.go
index 95cee4f8fa..9159aad897 100644
--- a/cmd/goal/clerk.go
+++ b/cmd/goal/clerk.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -139,7 +139,7 @@ func init() {
var clerkCmd = &cobra.Command{
Use: "clerk",
Short: "Provides the tools to control transactions ",
- Long: `Collection of commands to support the mangement of transaction information.`,
+ Long: `Collection of commands to support the management of transaction information.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
//If no arguments passed, we should fallback to help
@@ -536,6 +536,7 @@ var rawsendCmd = &cobra.Command{
var inspectCmd = &cobra.Command{
Use: "inspect",
Short: "print a transaction file",
+ Long: `Loads a transaction file, attempts to decode the transaction, and displays the decoded information.`,
Run: func(cmd *cobra.Command, args []string) {
for _, txFilename := range args {
data, err := readFile(txFilename)
@@ -815,7 +816,7 @@ func disassembleFile(fname, outname string) {
var compileCmd = &cobra.Command{
Use: "compile",
Short: "compile a contract program",
- Long: "compile a contract program, report its address",
+ Long: "Reads a TEAL contract program and compiles it to binary output and contract address.",
Run: func(cmd *cobra.Command, args []string) {
for _, fname := range args {
if disassesmble {
@@ -877,7 +878,7 @@ var compileCmd = &cobra.Command{
var dryrunCmd = &cobra.Command{
Use: "dryrun",
Short: "test a program offline",
- Long: "test a program offline under various conditions and verbosity",
+ Long: "Test a TEAL program offline under various conditions and verbosity.",
Run: func(cmd *cobra.Command, args []string) {
data, err := readFile(txFilename)
if err != nil {
diff --git a/cmd/goal/commands.go b/cmd/goal/commands.go
index 1e050f7ee6..eb06006318 100644
--- a/cmd/goal/commands.go
+++ b/cmd/goal/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -153,8 +153,7 @@ func main() {
var versionCmd = &cobra.Command{
Use: "version",
- Short: "The current version of the Algorand daemon (algod)",
- Long: `The current version of the Algorand daemon (algod)`,
+ Short: "The current version of the Algorand daemon (algod).",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
onDataDirs(func(dataDir string) {
@@ -178,8 +177,7 @@ var versionCmd = &cobra.Command{
var licenseCmd = &cobra.Command{
Use: "license",
- Short: "Display license information",
- Long: `Displays license information`,
+ Short: "Display license information.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(config.GetLicenseInfo())
@@ -189,7 +187,7 @@ var licenseCmd = &cobra.Command{
var reportCmd = &cobra.Command{
Use: "report",
Short: "",
- Long: "Produces report helpful for debugging",
+ Long: "Produces report helpful for debugging.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(config.FormatVersionAndLicense())
diff --git a/cmd/goal/commands_test.go b/cmd/goal/commands_test.go
index e863fc658f..45e4f0195c 100644
--- a/cmd/goal/commands_test.go
+++ b/cmd/goal/commands_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/common.go b/cmd/goal/common.go
index 7bcccd69cb..bd54d9d077 100644
--- a/cmd/goal/common.go
+++ b/cmd/goal/common.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/completion.go b/cmd/goal/completion.go
index eb670062ff..9a27c3c5e9 100644
--- a/cmd/goal/completion.go
+++ b/cmd/goal/completion.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -29,8 +29,7 @@ func init() {
var completionCmd = &cobra.Command{
Use: "completion",
- Short: "Shell completion helper",
- Long: "Shell completion helper",
+ Short: "Shell completion helper.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
// If no arguments passed, we should fallback to help
@@ -40,8 +39,7 @@ var completionCmd = &cobra.Command{
var bashCompletionCmd = &cobra.Command{
Use: "bash",
- Short: "Generate bash completion commands",
- Long: "Generate bash completion commands",
+ Short: "Generate bash completion commands.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
rootCmd.GenBashCompletion(os.Stdout)
@@ -50,8 +48,7 @@ var bashCompletionCmd = &cobra.Command{
var zshCompletionCmd = &cobra.Command{
Use: "zsh",
- Short: "Generate zsh completion commands",
- Long: "Generate zsh completion commands",
+ Short: "Generate zsh completion commands.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
rootCmd.GenZshCompletion(os.Stdout)
diff --git a/cmd/goal/inspect.go b/cmd/goal/inspect.go
index 26e93cde63..8b81568a4d 100644
--- a/cmd/goal/inspect.go
+++ b/cmd/goal/inspect.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/inspect_test.go b/cmd/goal/inspect_test.go
index 66f243ce08..e492789b75 100644
--- a/cmd/goal/inspect_test.go
+++ b/cmd/goal/inspect_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/kmd.go b/cmd/goal/kmd.go
index 2919456168..5e24813e38 100644
--- a/cmd/goal/kmd.go
+++ b/cmd/goal/kmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -34,7 +34,7 @@ func init() {
var kmdCmd = &cobra.Command{
Use: "kmd",
Short: "Interact with kmd, the key management daemon",
- Long: `Interact with kmd, the key management daemon`,
+ Long: `Interact with kmd, the key management daemon. The key management daemon is a separate process from algod that is solely responsible for key management.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
cmd.HelpFunc()(cmd, args)
@@ -61,8 +61,7 @@ func startKMDForDataDir(binDir, algodDataDir, kmdDataDir string) {
var startKMDCmd = &cobra.Command{
Use: "start",
- Short: "Start the kmd process or restart it with an updated timeout",
- Long: `Start the kmd process or restart it with an updated timeout`,
+ Short: "Start the kmd process, or restart it with an updated timeout.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
binDir, err := util.ExeDir()
@@ -79,8 +78,7 @@ var startKMDCmd = &cobra.Command{
var stopKMDCmd = &cobra.Command{
Use: "stop",
- Short: "Stop the kmd process if it's running",
- Long: `Stop the kmd process if it's running`,
+ Short: "Stop the kmd process if it is running.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
binDir, err := util.ExeDir()
diff --git a/cmd/goal/ledger.go b/cmd/goal/ledger.go
index e36b6b8490..4e7e49ea61 100644
--- a/cmd/goal/ledger.go
+++ b/cmd/goal/ledger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -17,19 +17,35 @@
package main
import (
+ "bytes"
"fmt"
+ "strconv"
"github.com/spf13/cobra"
+
+ "github.com/algorand/go-algorand/protocol/transcode"
+)
+
+var (
+ blockFilename string
+ rawBlock bool
+ base32Encoding bool
+ strictJSON bool
)
func init() {
ledgerCmd.AddCommand(supplyCmd)
+ ledgerCmd.AddCommand(blockCmd)
+
+ blockCmd.Flags().StringVarP(&blockFilename, "out", "o", stdoutFilenameValue, "The filename to dump the block to (if not set, use stdout)")
+ blockCmd.Flags().BoolVarP(&rawBlock, "raw", "r", false, "Format block as msgpack")
+ blockCmd.Flags().BoolVar(&base32Encoding, "b32", false, "Encode binary blobs using base32 instead of base64")
+ blockCmd.Flags().BoolVar(&strictJSON, "strict", false, "Strict JSON decode: turn all keys into strings")
}
var ledgerCmd = &cobra.Command{
Use: "ledger",
- Short: "Access ledger-related details",
- Long: "Access ledger-related details",
+ Short: "Access ledger-related details.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
// If no arguments passed, we should fallback to help
@@ -40,7 +56,7 @@ var ledgerCmd = &cobra.Command{
var supplyCmd = &cobra.Command{
Use: "supply",
Short: "Show ledger token supply",
- Long: "Show ledger token supply. All units are in microAlgos.",
+ Long: `Show ledger token supply. All units are in microAlgos. The "Total Money" is all algos held by online+offline accounts (excludes non-participating accounts). The "Online Money" is the amount held solely by online accounts.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
dataDir := ensureSingleDataDir()
@@ -52,3 +68,45 @@ var supplyCmd = &cobra.Command{
fmt.Printf("Round: %v\nTotal Money: %v microAlgos\nOnline Money: %v microAlgos\n", response.Round, response.TotalMoney, response.OnlineMoney)
},
}
+
+var blockCmd = &cobra.Command{
+ Use: "block [round number]",
+ Short: "Dump a block to a file or stdout",
+ Long: "Dump a block to a file or stdout. Default behavior is to attempt to decode the raw bytes returned from algod to JSON.",
+ Args: cobra.ExactArgs(1),
+ Run: func(cmd *cobra.Command, args []string) {
+ round, err := strconv.ParseUint(args[0], 10, 64)
+ if err != nil {
+ reportErrorf(errParsingRoundNumber, err)
+ }
+
+ dataDir := ensureSingleDataDir()
+ client := ensureAlgodClient(dataDir)
+ response, err := client.RawBlock(round)
+ if err != nil {
+ reportErrorf(errorRequestFail, err)
+ }
+
+ // Unless the user asked for the raw block,
+ // print the block encoded as JSON
+ if !rawBlock {
+ in := bytes.NewBuffer(response)
+ out := bytes.NewBuffer(nil)
+ err = transcode.Transcode(true, base32Encoding, strictJSON, in, out)
+ if err != nil {
+ reportErrorf(errEncodingBlockAsJSON, err)
+ }
+ response = out.Bytes()
+ } else {
+ if base32Encoding || strictJSON {
+ reportErrorf(errBadBlockArgs)
+ }
+ }
+
+ // If blockFilename flag was not set, the default value '-' will write to stdout
+ err = writeFile(blockFilename, response, 0600)
+ if err != nil {
+ reportErrorf(fileWriteError, blockFilename, err)
+ }
+ },
+}
diff --git a/cmd/goal/logging.go b/cmd/goal/logging.go
index c9248a9df5..1f5b6ed9c2 100644
--- a/cmd/goal/logging.go
+++ b/cmd/goal/logging.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -47,7 +47,7 @@ func init() {
var loggingCmd = &cobra.Command{
Use: "logging",
Short: "Control and manage Algorand logging",
- Long: `Enable/disable and configure Algorand remote logging`,
+ Long: `Enable/disable and configure Algorand remote logging.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
fmt.Fprintf(os.Stderr, "Warning: `goal logging` deprecated, use `diagcfg telemetry status`\n")
@@ -90,8 +90,7 @@ var enableCmd = &cobra.Command{
var disableCmd = &cobra.Command{
Use: "disable",
- Short: "Disable Algorand remote logging",
- Long: `Disable Algorand remote logging`,
+ Short: "Disable Algorand remote logging.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
fmt.Fprintf(os.Stderr, "Warning: `goal logging disable` deprecated, use `diagcfg telemetry disable`\n")
diff --git a/cmd/goal/messages.go b/cmd/goal/messages.go
index 92e9ec16dc..5e96e58268 100644
--- a/cmd/goal/messages.go
+++ b/cmd/goal/messages.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -57,7 +57,8 @@ const (
infoNodeAlreadyStarted = "Algorand node was already started!"
infoTryingToStopNode = "Trying to stop the node..."
infoNodeSuccessfullyStopped = "The node was successfully stopped."
- infoNodeStatus = "Last committed block: %d\nTime since last block: %s\nSync Time: %s\nLast consensus protocol: %s\nNext consensus protocol: %s\nRound for next consensus protocol: %d\nNext consensus protocol supported: %v\nHas Synced Since Startup: %t"
+ infoNodeStatus = "Last committed block: %d\nTime since last block: %s\nSync Time: %s\nLast consensus protocol: %s\nNext consensus protocol: %s\nRound for next consensus protocol: %d\nNext consensus protocol supported: %v"
+ catchupStoppedOnUnsupported = "Last supported block (%d) is committed. The next block consensus protocol is not supported. Catchup service is stopped."
errorNodeCreationIPFailure = "Parsing passed IP %v failed: need a valid IPv4 or IPv6 address with a specified port number"
errorNodeNotDetected = "Algorand node does not appear to be running: %s"
errorNodeStatus = "Cannot contact Algorand node: %s."
@@ -149,4 +150,9 @@ const (
errWalletNotFound = "Wallet '%s' not found"
errDefaultWalletNotFound = "Wallet with ID '%s' not found. Was the default wallet deleted?"
errGettingToken = "Couldn't get token for wallet '%s' (ID: %s): %s"
+
+ // Ledger
+ errParsingRoundNumber = "Error parsing round number: %s"
+ errBadBlockArgs = "Cannot combine --b32=true or --strict=true with --raw"
+ errEncodingBlockAsJSON = "Error encoding block as json: %s"
)
diff --git a/cmd/goal/multisig.go b/cmd/goal/multisig.go
index e20ddb01b3..d58f733761 100644
--- a/cmd/goal/multisig.go
+++ b/cmd/goal/multisig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -63,7 +63,7 @@ func init() {
var multisigCmd = &cobra.Command{
Use: "multisig",
Short: "Provides tools working with multisig transactions ",
- Long: `Create, examine, and add signatures to multisig transactions`,
+ Long: `Create, examine, and add signatures to multisig transactions.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
//If no arguments passed, we should fallback to help
@@ -74,7 +74,7 @@ var multisigCmd = &cobra.Command{
var addSigCmd = &cobra.Command{
Use: "sign -t TXFILE -a ADDR",
Short: "Add a signature to a multisig transaction",
- Long: `Start a multisig, or add a signature to an existing multisig, for a given transaction`,
+ Long: `Start a multisig, or add a signature to an existing multisig, for a given transaction.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
data, err := readFile(txFilename)
@@ -139,7 +139,7 @@ var addSigCmd = &cobra.Command{
var signProgramCmd = &cobra.Command{
Use: "signprogram -t TXFILE -a ADDR",
Short: "Add a signature to a multisig LogicSig",
- Long: `Start a multisig LogicSig, or add a signature to an existing multisig, for a given program`,
+ Long: `Start a multisig LogicSig, or add a signature to an existing multisig, for a given program.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
dataDir := ensureSingleDataDir()
@@ -225,7 +225,7 @@ var signProgramCmd = &cobra.Command{
var mergeSigCmd = &cobra.Command{
Use: "merge -o MERGEDTXFILE TXFILE1 TXFILE2 ...",
Short: "Merge multisig signatures on transactions",
- Long: `Combine multiple partially-signed multisig transactions, and write out transactions with a single merged multisig signature`,
+ Long: `Combine multiple partially-signed multisig transactions, and write out transactions with a single merged multisig signature.`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
reportErrorf(txNoFilesError)
diff --git a/cmd/goal/network.go b/cmd/goal/network.go
index bfa76aa0f7..75b2153525 100644
--- a/cmd/goal/network.go
+++ b/cmd/goal/network.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -93,7 +93,7 @@ var networkCreateCmd = &cobra.Command{
panic(err)
}
- network, err := netdeploy.CreateNetworkFromTemplate(networkName, networkRootDir, networkTemplateFile, binDir, !noImportKeys)
+ network, err := netdeploy.CreateNetworkFromTemplate(networkName, networkRootDir, networkTemplateFile, binDir, !noImportKeys, nil)
if err != nil {
if noClean {
reportInfof(" ** failed ** - Preserving network rootdir '%s'", networkRootDir)
@@ -126,7 +126,7 @@ func getNetworkAndBinDir() (netdeploy.Network, string) {
var networkStartCmd = &cobra.Command{
Use: "start",
Short: "Start a deployed private network",
- Long: `Start a deployed private network`,
+ Long: `Start a deployed private network by starting each individual node.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
network, binDir := getNetworkAndBinDir()
@@ -148,8 +148,7 @@ var networkStartCmd = &cobra.Command{
var networkRestartCmd = &cobra.Command{
Use: "restart",
- Short: "Restart a deployed private network",
- Long: `Restart a deployed private network`,
+ Short: "Restart a deployed private network.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
network, binDir := getNetworkAndBinDir()
@@ -164,8 +163,7 @@ var networkRestartCmd = &cobra.Command{
var networkStopCmd = &cobra.Command{
Use: "stop",
- Short: "Stop a deployed private network",
- Long: `Stop a deployed private network`,
+ Short: "Stop a deployed private network.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
network, binDir := getNetworkAndBinDir()
@@ -176,8 +174,7 @@ var networkStopCmd = &cobra.Command{
var networkStatusCmd = &cobra.Command{
Use: "status",
- Short: "Prints status for all nodes in a deployed private network",
- Long: `Prints status for all nodes in a deployed private network`,
+ Short: "Prints status for all nodes in a deployed private network.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
network, binDir := getNetworkAndBinDir()
diff --git a/cmd/goal/node.go b/cmd/goal/node.go
index 7003de11c6..eeaf7844b2 100644
--- a/cmd/goal/node.go
+++ b/cmd/goal/node.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -99,8 +99,7 @@ var nodeCmd = &cobra.Command{
var startCmd = &cobra.Command{
Use: "start",
- Short: "Init the specified algorand node",
- Long: `Init the specified algorand node`,
+ Short: "Init the specified Algorand node.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
binDir, err := util.ExeDir()
@@ -146,8 +145,7 @@ func getRunHostedConfigFlag(dataDir string) bool {
var stopCmd = &cobra.Command{
Use: "stop",
- Short: "stop the specified Algorand node",
- Long: `Stop the specified Algorand node`,
+ Short: "stop the specified Algorand node.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
binDir, err := util.ExeDir()
@@ -171,8 +169,7 @@ var stopCmd = &cobra.Command{
var restartCmd = &cobra.Command{
Use: "restart",
- Short: "stop, and then start, the specified Algorand node",
- Long: `Stop, and then start, the specified Algorand node`,
+ Short: "Stop, and then start, the specified Algorand node.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
binDir, err := util.ExeDir()
@@ -228,8 +225,7 @@ var restartCmd = &cobra.Command{
var generateTokenCmd = &cobra.Command{
Use: "generatetoken",
- Short: "Generate and install a new API token",
- Long: "Generate and install a new API token",
+ Short: "Generate and install a new API token.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
onDataDirs(func(dataDir string) {
@@ -262,7 +258,7 @@ var generateTokenCmd = &cobra.Command{
var statusCmd = &cobra.Command{
Use: "status",
Short: "Get the current node status",
- Long: `Show the current status of the running Algorand node`,
+ Long: `Show the current status of the running Algorand node.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
onDataDirs(getStatus)
@@ -290,12 +286,27 @@ func getStatus(dataDir string) {
func makeStatusString(stat v1.NodeStatus) string {
lastRoundTime := fmt.Sprintf("%.1fs", time.Duration(stat.TimeSinceLastRound).Seconds())
catchupTime := fmt.Sprintf("%.1fs", time.Duration(stat.CatchupTime).Seconds())
- return fmt.Sprintf(infoNodeStatus, stat.LastRound, lastRoundTime, catchupTime, stat.LastVersion, stat.NextVersion, stat.NextVersionRound, stat.NextVersionSupported, stat.HasSyncedSinceStartup)
+ statusString := fmt.Sprintf(
+ infoNodeStatus,
+ stat.LastRound,
+ lastRoundTime,
+ catchupTime,
+ stat.LastVersion,
+ stat.NextVersion,
+ stat.NextVersionRound,
+ stat.NextVersionSupported)
+
+ if stat.StoppedAtUnsupportedRound {
+ statusString = statusString + "\n" + fmt.Sprintf(catchupStoppedOnUnsupported, stat.LastRound)
+ }
+
+ return statusString
}
var lastroundCmd = &cobra.Command{
Use: "lastround",
Short: "Print the last round number",
+ Long: `Prints the most recent round confirmed by the Algorand node.`,
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
onDataDirs(func(dataDir string) {
@@ -367,7 +378,7 @@ var pendingTxnsCmd = &cobra.Command{
var waitCmd = &cobra.Command{
Use: "wait",
Short: "Waits for the node to make progress",
- Long: "Waits for the node to make progress, which includes catching up",
+ Long: "Waits for the node to make progress, which includes catching up.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
client := ensureAlgodClient(ensureSingleDataDir())
@@ -411,8 +422,7 @@ func isValidIP(userInput string) bool {
var createCmd = &cobra.Command{
Use: "create",
- Short: "create a node at the desired data directory for the desired network",
- Long: "create a node at the desired data directory for the desired network",
+ Short: "Create a node at the desired data directory for the desired network.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
diff --git a/cmd/goal/wallet.go b/cmd/goal/wallet.go
index ad70eff50e..756213d98c 100644
--- a/cmd/goal/wallet.go
+++ b/cmd/goal/wallet.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -48,8 +48,7 @@ func init() {
var walletCmd = &cobra.Command{
Use: "wallet",
- Short: "Manage wallets: encrypted collections of Algorand account keys",
- Long: `Manage wallets: encrypted collections of Algorand account keys`,
+ Short: "Manage wallets: encrypted collections of Algorand account keys.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, args []string) {
// Update the default wallet
@@ -80,8 +79,7 @@ var walletCmd = &cobra.Command{
var newWalletCmd = &cobra.Command{
Use: "new [wallet name]",
- Short: "Create a new wallet",
- Long: `Create a new wallet`,
+ Short: "Create a new wallet.",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
var err error
@@ -187,8 +185,7 @@ var newWalletCmd = &cobra.Command{
var listWalletsCmd = &cobra.Command{
Use: "list",
- Short: "List wallets managed by kmd",
- Long: `List wallets managed by kmd`,
+ Short: "List wallets managed by kmd.",
Args: validateNoPosArgsFn,
Run: func(cmd *cobra.Command, _ []string) {
onDataDirs(func(dataDir string) {
diff --git a/cmd/incorporate/incorporate.go b/cmd/incorporate/incorporate.go
index 5af86a1fbf..7fd3dc2027 100644
--- a/cmd/incorporate/incorporate.go
+++ b/cmd/incorporate/incorporate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/kmd/codes/codes.go b/cmd/kmd/codes/codes.go
index 44753bd264..ba8d86992c 100644
--- a/cmd/kmd/codes/codes.go
+++ b/cmd/kmd/codes/codes.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/kmd/main.go b/cmd/kmd/main.go
index f2b09f0d91..60f49cc77a 100644
--- a/cmd/kmd/main.go
+++ b/cmd/kmd/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/kmd/mlock_darwin.go b/cmd/kmd/mlock_darwin.go
index 3ef2f35b17..8338f6ae06 100644
--- a/cmd/kmd/mlock_darwin.go
+++ b/cmd/kmd/mlock_darwin.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/kmd/mlock_linux.go b/cmd/kmd/mlock_linux.go
index 11514798aa..aea67f1024 100644
--- a/cmd/kmd/mlock_linux.go
+++ b/cmd/kmd/mlock_linux.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/msgpacktool/main.go b/cmd/msgpacktool/main.go
index c836293ba2..72fa0ab34d 100644
--- a/cmd/msgpacktool/main.go
+++ b/cmd/msgpacktool/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -45,6 +45,8 @@ import (
"flag"
"fmt"
"os"
+
+ "github.com/algorand/go-algorand/protocol/transcode"
)
var mpToJSON = flag.Bool("d", false, "Decode msgpack to JSON")
@@ -64,7 +66,7 @@ func main() {
os.Exit(1)
}
- err := transcode(*mpToJSON, os.Stdin, os.Stdout)
+ err := transcode.Transcode(*mpToJSON, *base32Encoding, *strictJSON, os.Stdin, os.Stdout)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
diff --git a/cmd/netdummy/main.go b/cmd/netdummy/main.go
index d44b48fc67..e12cbc1118 100644
--- a/cmd/netdummy/main.go
+++ b/cmd/netdummy/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/netgoal/commands.go b/cmd/netgoal/commands.go
index c4fd45736b..87524e803f 100644
--- a/cmd/netgoal/commands.go
+++ b/cmd/netgoal/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/netgoal/generate.go b/cmd/netgoal/generate.go
index 558d3768c4..6042a9329e 100644
--- a/cmd/netgoal/generate.go
+++ b/cmd/netgoal/generate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/netgoal/messages.go b/cmd/netgoal/messages.go
index 6135358a13..647776ab4c 100644
--- a/cmd/netgoal/messages.go
+++ b/cmd/netgoal/messages.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/netgoal/network.go b/cmd/netgoal/network.go
index bd66839d02..a4fd89624d 100644
--- a/cmd/netgoal/network.go
+++ b/cmd/netgoal/network.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/netgoal/recipe.go b/cmd/netgoal/recipe.go
index 0d957f277e..c4b00958e8 100644
--- a/cmd/netgoal/recipe.go
+++ b/cmd/netgoal/recipe.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/nodecfg/apply.go b/cmd/nodecfg/apply.go
index 11f18fe0fc..c794fdff68 100644
--- a/cmd/nodecfg/apply.go
+++ b/cmd/nodecfg/apply.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/nodecfg/commands.go b/cmd/nodecfg/commands.go
index c02cd8eb87..0e7b4b2645 100644
--- a/cmd/nodecfg/commands.go
+++ b/cmd/nodecfg/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/nodecfg/download.go b/cmd/nodecfg/download.go
index 7138a1d01c..32a21931d7 100644
--- a/cmd/nodecfg/download.go
+++ b/cmd/nodecfg/download.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/nodecfg/get.go b/cmd/nodecfg/get.go
index 64f5ac544d..ad4204efaa 100644
--- a/cmd/nodecfg/get.go
+++ b/cmd/nodecfg/get.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/opdoc/opdoc.go b/cmd/opdoc/opdoc.go
index 665154761e..d2ebcd9277 100644
--- a/cmd/opdoc/opdoc.go
+++ b/cmd/opdoc/opdoc.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/pingpong/commands.go b/cmd/pingpong/commands.go
index e5e5cbb8a3..e77f696e64 100644
--- a/cmd/pingpong/commands.go
+++ b/cmd/pingpong/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/pingpong/runCmd.go b/cmd/pingpong/runCmd.go
index 7a36144351..3b07574741 100644
--- a/cmd/pingpong/runCmd.go
+++ b/cmd/pingpong/runCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/pingpong/teal_programs.go b/cmd/pingpong/teal_programs.go
index 815b5bc481..855fe53e3f 100644
--- a/cmd/pingpong/teal_programs.go
+++ b/cmd/pingpong/teal_programs.go
@@ -1,3 +1,19 @@
+// Copyright (C) 2019-2020 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see .
+
package main
var tealLight = "int 1"
diff --git a/cmd/updater/commands.go b/cmd/updater/commands.go
index cbb90ea830..39b686df41 100644
--- a/cmd/updater/commands.go
+++ b/cmd/updater/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/updater/sendCmd.go b/cmd/updater/sendCmd.go
index 322e79b481..1d91667411 100644
--- a/cmd/updater/sendCmd.go
+++ b/cmd/updater/sendCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/updater/toolsCmd.go b/cmd/updater/toolsCmd.go
index 7c961f3bec..251aed37d2 100644
--- a/cmd/updater/toolsCmd.go
+++ b/cmd/updater/toolsCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/updater/util.go b/cmd/updater/util.go
index 8ce21c50d2..12cd98a481 100644
--- a/cmd/updater/util.go
+++ b/cmd/updater/util.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/updater/versionCmd.go b/cmd/updater/versionCmd.go
index 7f17a5562a..f19462237e 100644
--- a/cmd/updater/versionCmd.go
+++ b/cmd/updater/versionCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/updater/version_test.go b/cmd/updater/version_test.go
index fa47bd3916..b702e24bdb 100644
--- a/cmd/updater/version_test.go
+++ b/cmd/updater/version_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/components/mocks/mockNetwork.go b/components/mocks/mockNetwork.go
index dcc7bd1ceb..92ee3af726 100644
--- a/components/mocks/mockNetwork.go
+++ b/components/mocks/mockNetwork.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/components/mocks/mockNodeContext.go b/components/mocks/mockNodeContext.go
index c1be0c04ad..214623fa66 100644
--- a/components/mocks/mockNodeContext.go
+++ b/components/mocks/mockNodeContext.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/components/nodeContext.go b/components/nodeContext.go
index c92d8f0e91..9eb583eb21 100644
--- a/components/nodeContext.go
+++ b/components/nodeContext.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/buildvars.go b/config/buildvars.go
index 793a40ecc8..611b8b8860 100644
--- a/config/buildvars.go
+++ b/config/buildvars.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/config.go b/config/config.go
index b17bd36742..aee0349e9a 100644
--- a/config/config.go
+++ b/config/config.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -71,12 +71,23 @@ type ConsensusParams struct {
// to be high enough to ensure that there are sufficient participants
// after the upgrade.
//
- // There is a delay of UpgradeWaitRounds between approval of
- // an upgrade and its deployment, to give clients time to notify users.
- UpgradeVoteRounds uint64
- UpgradeThreshold uint64
- UpgradeWaitRounds uint64
- MaxVersionStringLen int
+ // A consensus protocol upgrade may specify the delay between its
+ // acceptance and its execution. This gives clients time to notify
+ // users. This delay is specified by the upgrade proposer and must
+ // be between MinUpgradeWaitRounds and MaxUpgradeWaitRounds (inclusive)
+ // in the old protocol's parameters. Note that these parameters refer
+ // to the representation of the delay in a block rather than the actual
+ // delay: if the specified delay is zero, it is equivalent to
+ // DefaultUpgradeWaitRounds.
+ //
+ // The maximum length of a consensus version string is
+ // MaxVersionStringLen.
+ UpgradeVoteRounds uint64
+ UpgradeThreshold uint64
+ DefaultUpgradeWaitRounds uint64
+ MinUpgradeWaitRounds uint64
+ MaxUpgradeWaitRounds uint64
+ MaxVersionStringLen int
// MaxTxnBytesPerBlock determines the maximum number of bytes
// that transactions can take up in a block. Specifically,
@@ -95,8 +106,10 @@ type ConsensusParams struct {
MaxTxnLife uint64
// ApprovedUpgrades describes the upgrade proposals that this protocol
- // implementation will vote for.
- ApprovedUpgrades map[protocol.ConsensusVersion]bool
+ // implementation will vote for, along with their delay value
+ // (in rounds). A delay value of zero is the same as a delay of
+ // DefaultUpgradeWaitRounds.
+ ApprovedUpgrades map[protocol.ConsensusVersion]uint64
// SupportGenesisHash indicates support for the GenesisHash
// fields in transactions (and requires them in blocks).
@@ -257,10 +270,10 @@ func initConsensusProtocols() {
// Base consensus protocol version, v7.
v7 := ConsensusParams{
- UpgradeVoteRounds: 10000,
- UpgradeThreshold: 9000,
- UpgradeWaitRounds: 10000,
- MaxVersionStringLen: 64,
+ UpgradeVoteRounds: 10000,
+ UpgradeThreshold: 9000,
+ DefaultUpgradeWaitRounds: 10000,
+ MaxVersionStringLen: 64,
MinBalance: 10000,
MinTxnFee: 1000,
@@ -274,7 +287,7 @@ func initConsensusProtocols() {
RewardUnit: 1e6,
RewardsRateRefreshInterval: 5e5,
- ApprovedUpgrades: map[protocol.ConsensusVersion]bool{},
+ ApprovedUpgrades: map[protocol.ConsensusVersion]uint64{},
NumProposers: 30,
SoftCommitteeSize: 2500,
@@ -300,7 +313,7 @@ func initConsensusProtocols() {
MaxTxGroupSize: 1,
}
- v7.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v7.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV7] = v7
// v8 uses parameters and a seed derivation policy (the "twin seeds") from Georgios' new analysis
@@ -321,20 +334,20 @@ func initConsensusProtocols() {
v8.DownCommitteeSize = 5000
v8.DownCommitteeThreshold = 3838
- v8.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v8.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV8] = v8
// v7 can be upgraded to v8.
- v7.ApprovedUpgrades[protocol.ConsensusV8] = true
+ v7.ApprovedUpgrades[protocol.ConsensusV8] = 0
// v9 increases the minimum balance to 100,000 microAlgos.
v9 := v8
v9.MinBalance = 100000
- v9.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v9.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV9] = v9
// v8 can be upgraded to v9.
- v8.ApprovedUpgrades[protocol.ConsensusV9] = true
+ v8.ApprovedUpgrades[protocol.ConsensusV9] = 0
// v10 introduces fast partition recovery (and also raises NumProposers).
v10 := v9
@@ -346,82 +359,82 @@ func initConsensusProtocols() {
v10.RedoCommitteeThreshold = 1768
v10.DownCommitteeSize = 6000
v10.DownCommitteeThreshold = 4560
- v10.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v10.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV10] = v10
// v9 can be upgraded to v10.
- v9.ApprovedUpgrades[protocol.ConsensusV10] = true
+ v9.ApprovedUpgrades[protocol.ConsensusV10] = 0
// v11 introduces SignedTxnInBlock.
v11 := v10
v11.SupportSignedTxnInBlock = true
v11.PaysetCommitFlat = true
- v11.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v11.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV11] = v11
// v10 can be upgraded to v11.
- v10.ApprovedUpgrades[protocol.ConsensusV11] = true
+ v10.ApprovedUpgrades[protocol.ConsensusV11] = 0
// v12 increases the maximum length of a version string.
v12 := v11
v12.MaxVersionStringLen = 128
- v12.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v12.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV12] = v12
// v11 can be upgraded to v12.
- v11.ApprovedUpgrades[protocol.ConsensusV12] = true
+ v11.ApprovedUpgrades[protocol.ConsensusV12] = 0
// v13 makes the consensus version a meaningful string.
v13 := v12
- v13.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v13.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV13] = v13
// v12 can be upgraded to v13.
- v12.ApprovedUpgrades[protocol.ConsensusV13] = true
+ v12.ApprovedUpgrades[protocol.ConsensusV13] = 0
// v14 introduces tracking of closing amounts in ApplyData, and enables
// GenesisHash in transactions.
v14 := v13
v14.ApplyData = true
v14.SupportGenesisHash = true
- v14.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v14.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV14] = v14
// v13 can be upgraded to v14.
- v13.ApprovedUpgrades[protocol.ConsensusV14] = true
+ v13.ApprovedUpgrades[protocol.ConsensusV14] = 0
// v15 introduces tracking of reward distributions in ApplyData.
v15 := v14
v15.RewardsInApplyData = true
v15.ForceNonParticipatingFeeSink = true
- v15.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v15.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV15] = v15
// v14 can be upgraded to v15.
- v14.ApprovedUpgrades[protocol.ConsensusV15] = true
+ v14.ApprovedUpgrades[protocol.ConsensusV15] = 0
// v16 fixes domain separation in credentials.
v16 := v15
v16.CredentialDomainSeparationEnabled = true
v16.RequireGenesisHash = true
- v16.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v16.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV16] = v16
// v15 can be upgraded to v16.
- v15.ApprovedUpgrades[protocol.ConsensusV16] = true
+ v15.ApprovedUpgrades[protocol.ConsensusV16] = 0
// ConsensusV17 points to 'final' spec commit
v17 := v16
- v17.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v17.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV17] = v17
// v16 can be upgraded to v17.
- v16.ApprovedUpgrades[protocol.ConsensusV17] = true
+ v16.ApprovedUpgrades[protocol.ConsensusV17] = 0
// ConsensusV18 points to reward calculation spec commit
v18 := v17
v18.PendingResidueRewards = true
- v18.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v18.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
v18.TxnCounter = true
v18.Asset = true
v18.LogicSigVersion = 1
@@ -439,83 +452,85 @@ func initConsensusProtocols() {
// ConsensusV19 is the official spec commit ( teal, assets, group tx )
v19 := v18
- v19.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v19.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusV19] = v19
// v18 can be upgraded to v19.
- v18.ApprovedUpgrades[protocol.ConsensusV19] = true
+ v18.ApprovedUpgrades[protocol.ConsensusV19] = 0
// v17 can be upgraded to v19.
- v17.ApprovedUpgrades[protocol.ConsensusV19] = true
+ v17.ApprovedUpgrades[protocol.ConsensusV19] = 0
// v20 points to adding the precision to the assets.
v20 := v19
- v20.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ v20.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
v20.MaxAssetDecimals = 19
// we want to adjust the upgrade time to be roughly one week.
// one week, in term of rounds would be:
// 140651 = (7 * 24 * 60 * 60 / 4.3)
// for the sake of future manual calculations, we'll round that down
// a bit :
- v20.UpgradeWaitRounds = 140000
+ v20.DefaultUpgradeWaitRounds = 140000
Consensus[protocol.ConsensusV20] = v20
// v19 can be upgraded to v20.
- v19.ApprovedUpgrades[protocol.ConsensusV20] = true
+ v19.ApprovedUpgrades[protocol.ConsensusV20] = 0
// ConsensusFuture is used to test features that are implemented
// but not yet released in a production protocol version.
vFuture := v20
- vFuture.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ vFuture.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
+ vFuture.MinUpgradeWaitRounds = 10000
+ vFuture.MaxUpgradeWaitRounds = 150000
Consensus[protocol.ConsensusFuture] = vFuture
}
func initConsensusTestProtocols() {
// Various test protocol versions
Consensus[protocol.ConsensusTest0] = ConsensusParams{
- UpgradeVoteRounds: 2,
- UpgradeThreshold: 1,
- UpgradeWaitRounds: 2,
- MaxVersionStringLen: 64,
+ UpgradeVoteRounds: 2,
+ UpgradeThreshold: 1,
+ DefaultUpgradeWaitRounds: 2,
+ MaxVersionStringLen: 64,
MaxTxnBytesPerBlock: 1000000,
DefaultKeyDilution: 10000,
- ApprovedUpgrades: map[protocol.ConsensusVersion]bool{
- protocol.ConsensusTest1: true,
+ ApprovedUpgrades: map[protocol.ConsensusVersion]uint64{
+ protocol.ConsensusTest1: 0,
},
}
Consensus[protocol.ConsensusTest1] = ConsensusParams{
- UpgradeVoteRounds: 10,
- UpgradeThreshold: 8,
- UpgradeWaitRounds: 10,
- MaxVersionStringLen: 64,
+ UpgradeVoteRounds: 10,
+ UpgradeThreshold: 8,
+ DefaultUpgradeWaitRounds: 10,
+ MaxVersionStringLen: 64,
MaxTxnBytesPerBlock: 1000000,
DefaultKeyDilution: 10000,
- ApprovedUpgrades: map[protocol.ConsensusVersion]bool{},
+ ApprovedUpgrades: map[protocol.ConsensusVersion]uint64{},
}
testBigBlocks := Consensus[protocol.ConsensusCurrentVersion]
testBigBlocks.MaxTxnBytesPerBlock = 100000000
- testBigBlocks.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ testBigBlocks.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusTestBigBlocks] = testBigBlocks
rapidRecalcParams := Consensus[protocol.ConsensusCurrentVersion]
- rapidRecalcParams.RewardsRateRefreshInterval = 25
+ rapidRecalcParams.RewardsRateRefreshInterval = 10
//because rapidRecalcParams is based on ConsensusCurrentVersion,
//it *shouldn't* have any ApprovedUpgrades
//but explicitly mark "no approved upgrades" just in case
- rapidRecalcParams.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ rapidRecalcParams.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
Consensus[protocol.ConsensusTestRapidRewardRecalculation] = rapidRecalcParams
// Setting the testShorterLookback parameters derived from ConsensusCurrentVersion
// Will result in MaxBalLookback = 32
// Used to run tests faster where past MaxBalLookback values are checked
testShorterLookback := Consensus[protocol.ConsensusCurrentVersion]
- testShorterLookback.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ testShorterLookback.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
// MaxBalLookback = 2 x SeedRefreshInterval x SeedLookback
// ref. https://github.com/algorandfoundation/specs/blob/master/dev/abft.md
@@ -523,6 +538,39 @@ func initConsensusTestProtocols() {
testShorterLookback.SeedRefreshInterval = 8
testShorterLookback.MaxBalLookback = 2 * testShorterLookback.SeedLookback * testShorterLookback.SeedRefreshInterval // 32
Consensus[protocol.ConsensusTestShorterLookback] = testShorterLookback
+
+ // The following two protocols: testUnupgradedProtocol and testUnupgradedToProtocol
+ // are used to test the case when some nodes in the network do not make progress.
+
+ // testUnupgradedToProtocol is derived from ConsensusCurrentVersion and upgraded
+ // from testUnupgradedProtocol.
+ testUnupgradedToProtocol := Consensus[protocol.ConsensusCurrentVersion]
+ testUnupgradedToProtocol.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
+ Consensus[protocol.ConsensusTestUnupgradedToProtocol] = testUnupgradedToProtocol
+
+ // testUnupgradedProtocol is used to control the upgrade of a node. This is used
+ // to construct and run a network where some node is upgraded, and some other
+ // node is not upgraded.
+ // testUnupgradedProtocol is derived from ConsensusCurrentVersion and upgrades to
+ // testUnupgradedToProtocol.
+ testUnupgradedProtocol := Consensus[protocol.ConsensusCurrentVersion]
+ testUnupgradedProtocol.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
+
+ testUnupgradedProtocol.UpgradeVoteRounds = 3
+ testUnupgradedProtocol.UpgradeThreshold = 2
+ testUnupgradedProtocol.DefaultUpgradeWaitRounds = 3
+ b, err := strconv.ParseBool(os.Getenv("ALGORAND_TEST_UNUPGRADEDPROTOCOL_DELETE_UPGRADE"))
+ // Do not upgrade to the next version if
+ // ALGORAND_TEST_UNUPGRADEDPROTOCOL_DELETE_UPGRADE is set to true (e.g. 1, TRUE)
+ if err == nil && b {
+ // Configure as if testUnupgradedToProtocol is not supported by the binary
+ delete(Consensus, protocol.ConsensusTestUnupgradedToProtocol)
+ } else {
+ // Direct upgrade path from ConsensusTestUnupgradedProtocol to ConsensusTestUnupgradedToProtocol
+ // This is needed for the voting nodes vote to upgrade to the next protocol
+ testUnupgradedProtocol.ApprovedUpgrades[protocol.ConsensusTestUnupgradedToProtocol] = 0
+ }
+ Consensus[protocol.ConsensusTestUnupgradedProtocol] = testUnupgradedProtocol
}
func initConsensusTestFastUpgrade() {
@@ -532,12 +580,12 @@ func initConsensusTestFastUpgrade() {
fastParams := params
fastParams.UpgradeVoteRounds = 5
fastParams.UpgradeThreshold = 3
- fastParams.UpgradeWaitRounds = 5
+ fastParams.DefaultUpgradeWaitRounds = 5
fastParams.MaxVersionStringLen += len(protocol.ConsensusTestFastUpgrade(""))
- fastParams.ApprovedUpgrades = make(map[protocol.ConsensusVersion]bool)
+ fastParams.ApprovedUpgrades = make(map[protocol.ConsensusVersion]uint64)
- for ver, flag := range params.ApprovedUpgrades {
- fastParams.ApprovedUpgrades[protocol.ConsensusTestFastUpgrade(ver)] = flag
+ for ver := range params.ApprovedUpgrades {
+ fastParams.ApprovedUpgrades[protocol.ConsensusTestFastUpgrade(ver)] = 0
}
fastUpgradeProtocols[protocol.ConsensusTestFastUpgrade(proto)] = fastParams
@@ -751,6 +799,13 @@ type Local struct {
// PeerConnectionsUpdateInterval defines the interval at which the peer connections information is being sent to the
// telemetry ( when enabled ). Defined in seconds.
PeerConnectionsUpdateInterval int
+
+ // EnableProfiler enables the go pprof endpoints, should be false if
+ // the algod api will be exposed to untrusted individuals
+ EnableProfiler bool
+
+ // TelemetryToLog records messages to node.log that are normally sent to remote event monitoring
+ TelemetryToLog bool
}
// Filenames of config files within the configdir (e.g. ~/.algorand)
diff --git a/config/config_test.go b/config/config_test.go
index f6525d7628..273b88eed0 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/consensus_test.go b/config/consensus_test.go
index 2e6330e104..7c34947d06 100644
--- a/config/consensus_test.go
+++ b/config/consensus_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/keyfile.go b/config/keyfile.go
index 205d0401d2..1824fabab1 100644
--- a/config/keyfile.go
+++ b/config/keyfile.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/local_defaults.go b/config/local_defaults.go
index 863730c665..6e8dedb117 100644
--- a/config/local_defaults.go
+++ b/config/local_defaults.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -82,6 +82,7 @@ var defaultLocalV5 = Local{
RunHosted: false,
SuggestedFeeBlockHistory: 3,
SuggestedFeeSlidingWindowSize: 50,
+ TelemetryToLog: true,
TxPoolExponentialIncreaseFactor: 2,
TxPoolSize: 15000,
TxSyncIntervalSeconds: 60,
diff --git a/config/version.go b/config/version.go
index e6aed22a50..2f5b08cfec 100644
--- a/config/version.go
+++ b/config/version.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go
index 0e6519c153..5c85a50c00 100644
--- a/crypto/crypto_test.go
+++ b/crypto/crypto_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/cryptoerror.go b/crypto/cryptoerror.go
index 7ca3afac59..ac07590191 100644
--- a/crypto/cryptoerror.go
+++ b/crypto/cryptoerror.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/curve25519.go b/crypto/curve25519.go
index b0bcd85f0f..362d5a8356 100644
--- a/crypto/curve25519.go
+++ b/crypto/curve25519.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/curve25519_test.go b/crypto/curve25519_test.go
index 3a4cc7cd8a..6df5a8bd19 100644
--- a/crypto/curve25519_test.go
+++ b/crypto/curve25519_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/encoding_test.go b/crypto/encoding_test.go
index e20c2d5fdd..e5b5dd134a 100644
--- a/crypto/encoding_test.go
+++ b/crypto/encoding_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merkle/root.go b/crypto/merkle/root.go
index 563f4a399b..11540b3102 100644
--- a/crypto/merkle/root.go
+++ b/crypto/merkle/root.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/multisig.go b/crypto/multisig.go
index bca8479fe1..4c6ccf18a3 100644
--- a/crypto/multisig.go
+++ b/crypto/multisig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/multisig_test.go b/crypto/multisig_test.go
index 3dab74ce3f..3ff3b6afcf 100644
--- a/crypto/multisig_test.go
+++ b/crypto/multisig_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/onetimesig.go b/crypto/onetimesig.go
index d0454756b2..a04dfd0d75 100644
--- a/crypto/onetimesig.go
+++ b/crypto/onetimesig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/onetimesig_test.go b/crypto/onetimesig_test.go
index 9de3b2b44e..59b7ef4017 100644
--- a/crypto/onetimesig_test.go
+++ b/crypto/onetimesig_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/passphrase/errors.go b/crypto/passphrase/errors.go
index d5518211a2..52f25c38a3 100644
--- a/crypto/passphrase/errors.go
+++ b/crypto/passphrase/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/passphrase/passphrase.go b/crypto/passphrase/passphrase.go
index b997dc7ce8..0bff402a26 100644
--- a/crypto/passphrase/passphrase.go
+++ b/crypto/passphrase/passphrase.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/passphrase/passphrase_test.go b/crypto/passphrase/passphrase_test.go
index e1dcc22ad4..7ee613eca2 100644
--- a/crypto/passphrase/passphrase_test.go
+++ b/crypto/passphrase/passphrase_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/passphrase/wordlist.go b/crypto/passphrase/wordlist.go
index 084393991a..58eca0c27d 100644
--- a/crypto/passphrase/wordlist.go
+++ b/crypto/passphrase/wordlist.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/rand.go b/crypto/rand.go
index 6f7dca89a0..4e44edd41f 100644
--- a/crypto/rand.go
+++ b/crypto/rand.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/rand_test.go b/crypto/rand_test.go
index 13a0c8c3db..776c58e932 100644
--- a/crypto/rand_test.go
+++ b/crypto/rand_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/util.go b/crypto/util.go
index 19ff9fa9cf..cd34a11162 100644
--- a/crypto/util.go
+++ b/crypto/util.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/util_test.go b/crypto/util_test.go
index abaf52d239..0dc4281e4a 100644
--- a/crypto/util_test.go
+++ b/crypto/util_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/vrf.go b/crypto/vrf.go
index b7eb8d8e5f..f1d8e13375 100644
--- a/crypto/vrf.go
+++ b/crypto/vrf.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/vrf_test.go b/crypto/vrf_test.go
index 729531ed9f..fdb1d1992f 100644
--- a/crypto/vrf_test.go
+++ b/crypto/vrf_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/client/encoding.go b/daemon/algod/api/client/encoding.go
index 7a2737c2c2..15c6e3613b 100644
--- a/daemon/algod/api/client/encoding.go
+++ b/daemon/algod/api/client/encoding.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/client/restClient.go b/daemon/algod/api/client/restClient.go
index 5894b797bf..d10579bb74 100644
--- a/daemon/algod/api/client/restClient.go
+++ b/daemon/algod/api/client/restClient.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -39,6 +39,7 @@ const (
authHeader = "X-Algo-API-Token"
healthCheckEndpoint = "/health"
apiVersionPathPrefix = "/v1"
+ maxRawResponseBytes = 50e6
)
// unversionedPaths ais a set of paths that should not be prefixed by the API version
@@ -87,7 +88,7 @@ func stripTransaction(tx string) string {
}
// submitForm is a helper used for submitting (ex.) GETs and POSTs to the server
-func (client RestClient) submitForm(response interface{}, path string, request interface{}, requestMethod string, encodeJSON bool) error {
+func (client RestClient) submitForm(response interface{}, path string, request interface{}, requestMethod string, encodeJSON bool, decodeJSON bool) error {
var err error
queryURL := client.serverURL
queryURL.Path = path
@@ -134,11 +135,12 @@ func (client RestClient) submitForm(response interface{}, path string, request i
httpClient := &http.Client{}
resp, err := httpClient.Do(req)
-
if err != nil {
return err
}
+ // Ensure response isn't too large
+ resp.Body = http.MaxBytesReader(nil, resp.Body, maxRawResponseBytes)
defer resp.Body.Close()
err = extractError(resp)
@@ -146,20 +148,42 @@ func (client RestClient) submitForm(response interface{}, path string, request i
return err
}
- dec := json.NewDecoder(resp.Body)
- return dec.Decode(&response)
+ if decodeJSON {
+ dec := json.NewDecoder(resp.Body)
+ return dec.Decode(&response)
+ }
+
+ // Response must implement RawResponse
+ raw, ok := response.(v1.RawResponse)
+ if !ok {
+ return fmt.Errorf("can only decode raw response into type implementing v1.RawResponse")
+ }
+
+ bodyBytes, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return err
+ }
+
+ raw.SetBytes(bodyBytes)
+ return nil
}
// get performs a GET request to the specific path against the server
func (client RestClient) get(response interface{}, path string, request interface{}) error {
- return client.submitForm(response, path, request, "GET", false /* encodeJSON */)
+ return client.submitForm(response, path, request, "GET", false /* encodeJSON */, true /* decodeJSON */)
+}
+
+// getRaw behaves identically to get but doesn't json decode the response, and
+// the response must implement the v1.RawResponse interface
+func (client RestClient) getRaw(response v1.RawResponse, path string, request interface{}) error {
+ return client.submitForm(response, path, request, "GET", false /* encodeJSON */, false /* decodeJSON */)
}
// post sends a POST request to the given path with the given request object.
// No query parameters will be sent if request is nil.
// response must be a pointer to an object as post writes the response there.
func (client RestClient) post(response interface{}, path string, request interface{}) error {
- return client.submitForm(response, path, request, "POST", true /* encodeJSON */)
+ return client.submitForm(response, path, request, "POST", true /* encodeJSON */, true /* decodeJSON */)
}
// Status retrieves the StatusResponse from the running node
@@ -219,6 +243,10 @@ type assetsParams struct {
Max uint64 `url:"max"`
}
+type rawblockParams struct {
+ Raw uint64 `url:"raw"`
+}
+
// TransactionsByAddr returns all transactions for a PK [addr] in the [first,
// last] rounds range.
func (client RestClient) TransactionsByAddr(addr string, first, last, max uint64) (response v1.TransactionList, err error) {
@@ -303,6 +331,12 @@ func (client RestClient) Block(round uint64) (response v1.Block, err error) {
return
}
+// RawBlock gets the encoded, raw msgpack block for the given round
+func (client RestClient) RawBlock(round uint64) (response v1.RawBlock, err error) {
+ err = client.getRaw(&response, fmt.Sprintf("/block/%d", round), rawblockParams{1})
+ return
+}
+
// GetGoRoutines gets a dump of the goroutines from pprof
// Not supported
func (client RestClient) GetGoRoutines(ctx context.Context) (goRoutines string, err error) {
diff --git a/daemon/algod/api/server/common/handlers.go b/daemon/algod/api/server/common/handlers.go
index fe21bfcb48..687bd9ef34 100644
--- a/daemon/algod/api/server/common/handlers.go
+++ b/daemon/algod/api/server/common/handlers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/common/metrics.go b/daemon/algod/api/server/common/metrics.go
index f216cd32f8..7a9986fbab 100644
--- a/daemon/algod/api/server/common/metrics.go
+++ b/daemon/algod/api/server/common/metrics.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/common/responses.go b/daemon/algod/api/server/common/responses.go
index 3b395241dc..192e983afd 100644
--- a/daemon/algod/api/server/common/responses.go
+++ b/daemon/algod/api/server/common/responses.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/common/routes.go b/daemon/algod/api/server/common/routes.go
index f8ebd82367..9e0229271a 100644
--- a/daemon/algod/api/server/common/routes.go
+++ b/daemon/algod/api/server/common/routes.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/lib/common.go b/daemon/algod/api/server/lib/common.go
index b137fea9ed..c22594c4bf 100644
--- a/daemon/algod/api/server/lib/common.go
+++ b/daemon/algod/api/server/lib/common.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -43,8 +43,9 @@ type Routes []Route
// ReqContext is passed to each of the handlers below via wrapCtx, allowing
// handlers to interact with the node
type ReqContext struct {
- Node *node.AlgorandFullNode
- Log logging.Logger
+ Node *node.AlgorandFullNode
+ Log logging.Logger
+ Shutdown <-chan struct{}
}
// ErrorResponse sets the specified status code (should != 200), and fills in the
diff --git a/daemon/algod/api/server/lib/middlewares/auth.go b/daemon/algod/api/server/lib/middlewares/auth.go
index 28b1770838..705a88cb94 100644
--- a/daemon/algod/api/server/lib/middlewares/auth.go
+++ b/daemon/algod/api/server/lib/middlewares/auth.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/lib/middlewares/cors.go b/daemon/algod/api/server/lib/middlewares/cors.go
index 83e815c68a..53902e53a1 100644
--- a/daemon/algod/api/server/lib/middlewares/cors.go
+++ b/daemon/algod/api/server/lib/middlewares/cors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/lib/middlewares/logger.go b/daemon/algod/api/server/lib/middlewares/logger.go
index 09797f1d06..631b9d71d3 100644
--- a/daemon/algod/api/server/lib/middlewares/logger.go
+++ b/daemon/algod/api/server/lib/middlewares/logger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/router.go b/daemon/algod/api/server/router.go
index 2c41fb4ea1..85e3ad2a39 100644
--- a/daemon/algod/api/server/router.go
+++ b/daemon/algod/api/server/router.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -76,6 +76,7 @@ import (
const (
apiV1Tag = "v1"
debugRouteName = "debug"
+ pprofEndpointPrefix = "/debug/pprof/"
urlAuthEndpointPrefix = "/urlAuth/{apiToken:[0-9a-f]+}"
)
@@ -106,7 +107,7 @@ func registerHandlers(router *mux.Router, prefix string, routes lib.Routes, ctx
}
// NewRouter builds and returns a new router from routes
-func NewRouter(logger logging.Logger, node *node.AlgorandFullNode, apiToken string) *mux.Router {
+func NewRouter(logger logging.Logger, node *node.AlgorandFullNode, shutdown <-chan struct{}, apiToken string) *mux.Router {
router := mux.NewRouter().StrictSlash(true)
// Middleware
@@ -115,14 +116,17 @@ func NewRouter(logger logging.Logger, node *node.AlgorandFullNode, apiToken stri
router.Use(middlewares.CORS)
// Request Context
- ctx := lib.ReqContext{Node: node, Log: logger}
+ ctx := lib.ReqContext{Node: node, Log: logger, Shutdown: shutdown}
- // Registers /debug/pprof handler under root path and under /urlAuth path
- // to support header or url-provided token.
- router.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux)
+ // Route pprof requests
+ if node.Config().EnableProfiler {
+ // Registers /debug/pprof handler under root path and under /urlAuth path
+ // to support header or url-provided token.
+ router.PathPrefix(pprofEndpointPrefix).Handler(http.DefaultServeMux)
- urlAuthRouter := router.PathPrefix(urlAuthEndpointPrefix)
- urlAuthRouter.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux).Name(debugRouteName)
+ urlAuthRouter := router.PathPrefix(urlAuthEndpointPrefix)
+ urlAuthRouter.PathPrefix(pprofEndpointPrefix).Handler(http.DefaultServeMux).Name(debugRouteName)
+ }
// Registering common routes
registerHandlers(router, "", common.Routes, ctx)
diff --git a/daemon/algod/api/server/v1/handlers/errors.go b/daemon/algod/api/server/v1/handlers/errors.go
index 98dede9ae7..3013d42a3d 100644
--- a/daemon/algod/api/server/v1/handlers/errors.go
+++ b/daemon/algod/api/server/v1/handlers/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -24,6 +24,7 @@ var (
errFailedRetrievingNodeStatus = "failed retrieving node status"
errFailedRetrievingAsset = "failed to retrieve asset information"
errFailedParsingRoundNumber = "failed to parse the round number"
+ errFailedParsingRawOption = "failed to parse the raw option"
errFailedParsingMaxAssetsToList = "failed to parse max assets, must be between %d and %d"
errFailedParsingAssetIdx = "failed to parse asset index"
errFailedToGetAssetCreator = "failed to retrieve asset creator from the ledger"
@@ -39,5 +40,7 @@ var (
errNoRoundsSpecified = "Indexer is not enabled, firstRound and lastRound must be specified"
errNoTxnSpecified = "no transaction ID was specified"
errTransactionNotFound = "couldn't find the required transaction in the required range"
+ errServiceShuttingDown = "operation aborted as server is shutting down"
errUnknownTransactionType = "found a transaction with an unknown type"
+ errRequestedRoundInUnsupportedRound = "requested round would reach only after the protocol upgrade which isn't supported"
)
diff --git a/daemon/algod/api/server/v1/handlers/handlers.go b/daemon/algod/api/server/v1/handlers/handlers.go
index af610c68fa..6c97b58bb9 100644
--- a/daemon/algod/api/server/v1/handlers/handlers.go
+++ b/daemon/algod/api/server/v1/handlers/handlers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -39,6 +39,7 @@ import (
"github.com/algorand/go-algorand/ledger"
"github.com/algorand/go-algorand/node"
"github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/rpcs"
)
func nodeStatus(node *node.AlgorandFullNode) (res v1.NodeStatus, err error) {
@@ -48,13 +49,14 @@ func nodeStatus(node *node.AlgorandFullNode) (res v1.NodeStatus, err error) {
}
return v1.NodeStatus{
- LastRound: uint64(stat.LastRound),
- LastVersion: string(stat.LastVersion),
- NextVersion: string(stat.NextVersion),
- NextVersionRound: uint64(stat.NextVersionRound),
- NextVersionSupported: stat.NextVersionSupported,
- TimeSinceLastRound: stat.TimeSinceLastRound().Nanoseconds(),
- CatchupTime: stat.CatchupTime.Nanoseconds(),
+ LastRound: uint64(stat.LastRound),
+ LastVersion: string(stat.LastVersion),
+ NextVersion: string(stat.NextVersion),
+ NextVersionRound: uint64(stat.NextVersionRound),
+ NextVersionSupported: stat.NextVersionSupported,
+ TimeSinceLastRound: stat.TimeSinceLastRound().Nanoseconds(),
+ CatchupTime: stat.CatchupTime.Nanoseconds(),
+ StoppedAtUnsupportedRound: stat.StoppedAtUnsupportedRound,
}, nil
}
@@ -417,9 +419,29 @@ func WaitForBlock(ctx lib.ReqContext, w http.ResponseWriter, r *http.Request) {
return
}
+ ledger := ctx.Node.Ledger()
+ latestBlkHdr, err := ledger.BlockHdr(ledger.Latest())
+ if err != nil {
+ lib.ErrorResponse(w, http.StatusInternalServerError, err, errFailedRetrievingNodeStatus, ctx.Log)
+ return
+ }
+ if latestBlkHdr.NextProtocol != "" {
+ if _, nextProtocolSupported := config.Consensus[latestBlkHdr.NextProtocol]; !nextProtocolSupported {
+ // see if the desired protocol switch is expect to happen before or after the above point.
+ if latestBlkHdr.NextProtocolSwitchOn <= basics.Round(queryRound+1) {
+ // we would never reach to this round, since this round would happen after the (unsupported) protocol upgrade.
+ lib.ErrorResponse(w, http.StatusBadRequest, err, errRequestedRoundInUnsupportedRound, ctx.Log)
+ return
+ }
+ }
+ }
+
select {
+ case <-ctx.Shutdown:
+ lib.ErrorResponse(w, http.StatusInternalServerError, err, errServiceShuttingDown, ctx.Log)
+ return
case <-time.After(1 * time.Minute):
- case <-ctx.Node.Ledger().Wait(basics.Round(queryRound + 1)):
+ case <-ledger.Wait(basics.Round(queryRound + 1)):
}
nodeStatus, err := nodeStatus(ctx.Node)
@@ -1180,6 +1202,12 @@ func GetBlock(ctx lib.ReqContext, w http.ResponseWriter, r *http.Request) {
// minimum: 0
// required: true
// description: The round from which to fetch block information.
+ // - name: raw
+ // in: query
+ // type: integer
+ // format: int64
+ // required: false
+ // description: Return raw msgpack block bytes
// Responses:
// 200:
// "$ref": '#/responses/BlockResponse'
@@ -1197,6 +1225,33 @@ func GetBlock(ctx lib.ReqContext, w http.ResponseWriter, r *http.Request) {
return
}
+ // raw msgpack option:
+ rawstr := r.FormValue("raw")
+ if rawstr != "" {
+ rawint, err := strconv.ParseUint(rawstr, 10, 64)
+ if err != nil {
+ lib.ErrorResponse(w, http.StatusBadRequest, err, errFailedParsingRawOption, ctx.Log)
+ return
+ }
+ if rawint != 0 {
+ blockbytes, err := rpcs.RawBlockBytes(ctx.Node.Ledger(), basics.Round(queryRound))
+ if err != nil {
+ lib.ErrorResponse(w, http.StatusInternalServerError, err, errFailedLookingUpLedger, ctx.Log)
+ return
+ }
+ w.Header().Set("Content-Type", rpcs.LedgerResponseContentType)
+ w.Header().Set("Content-Length", strconv.Itoa(len(blockbytes)))
+ w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
+ w.WriteHeader(http.StatusOK)
+ _, err = w.Write(blockbytes)
+ if err != nil {
+ ctx.Log.Warnf("algod failed to write an object to the response stream: %v", err)
+ }
+ return
+ }
+ }
+
+ // decoded json-reencoded default:
ledger := ctx.Node.Ledger()
b, c, err := ledger.BlockCert(basics.Round(queryRound))
if err != nil {
diff --git a/daemon/algod/api/server/v1/handlers/handlers_test.go b/daemon/algod/api/server/v1/handlers/handlers_test.go
index b6e1894a04..b904f97353 100644
--- a/daemon/algod/api/server/v1/handlers/handlers_test.go
+++ b/daemon/algod/api/server/v1/handlers/handlers_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v1/handlers/responses.go b/daemon/algod/api/server/v1/handlers/responses.go
index fab747f38c..c608ed209e 100644
--- a/daemon/algod/api/server/v1/handlers/responses.go
+++ b/daemon/algod/api/server/v1/handlers/responses.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -175,6 +175,18 @@ func (r TransactionParamsResponse) getBody() interface{} {
return r.Body
}
+// RawBlockResponse contains encoded, raw block information
+//
+// swagger:response RawBlockResponse
+type RawBlockResponse struct {
+ // in: body
+ Body *v1.RawBlock
+}
+
+func (r RawBlockResponse) getBody() interface{} {
+ return r.Body
+}
+
// BlockResponse contains block information
//
// swagger:response BlockResponse
diff --git a/daemon/algod/api/server/v1/routes/routes.go b/daemon/algod/api/server/v1/routes/routes.go
index 2fbe293efa..7722320122 100644
--- a/daemon/algod/api/server/v1/routes/routes.go
+++ b/daemon/algod/api/server/v1/routes/routes.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/spec/common/model.go b/daemon/algod/api/spec/common/model.go
index f6e77ef4bb..de033e381b 100644
--- a/daemon/algod/api/spec/common/model.go
+++ b/daemon/algod/api/spec/common/model.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/spec/v1/model.go b/daemon/algod/api/spec/v1/model.go
index 157c48e469..e8f611e99a 100644
--- a/daemon/algod/api/spec/v1/model.go
+++ b/daemon/algod/api/spec/v1/model.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -58,6 +58,11 @@ type NodeStatus struct {
// HasSyncedSinceStartup indicates whether a round has completed since startup
// Required: true
HasSyncedSinceStartup bool `json:"hasSyncedSinceStartup"`
+
+ // StoppedAtUnsupportedRound indicates that the node does not support the new rounds and has stopped making progress
+ //
+ // Required: true
+ StoppedAtUnsupportedRound bool `json:"stoppedAtUnsupportedRound"`
}
// TransactionID Description
@@ -608,6 +613,21 @@ type TransactionParams struct {
MinTxnFee uint64 `json:"minFee"`
}
+// RawResponse is fulfilled by responses that should not be decoded as msgpack
+type RawResponse interface {
+ SetBytes([]byte)
+}
+
+// RawBlock represents an encoded msgpack block
+// swagger:model RawBlock
+// swagger:strfmt byte
+type RawBlock []byte
+
+// SetBytes fulfills the RawResponse interface on RawBlock
+func (rb *RawBlock) SetBytes(b []byte) {
+ *rb = b
+}
+
// Block contains a block information
// swagger:model Block
type Block struct {
diff --git a/daemon/algod/deadlockLogger.go b/daemon/algod/deadlockLogger.go
index 8a8d3ddeb9..67f2c634db 100644
--- a/daemon/algod/deadlockLogger.go
+++ b/daemon/algod/deadlockLogger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/server.go b/daemon/algod/server.go
index 767e016b89..6437f6ce91 100644
--- a/daemon/algod/server.go
+++ b/daemon/algod/server.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -55,9 +55,7 @@ type Server struct {
node *node.AlgorandFullNode
metricCollector *metrics.MetricService
metricServiceStarted bool
-
- stopping deadlock.Mutex
- stopped bool
+ stopping chan struct{}
}
// Initialize creates a Node instance with applicable network services
@@ -178,9 +176,11 @@ func (s *Server) Start() {
os.Exit(1)
}
+ s.stopping = make(chan struct{})
+
// use the data dir as the static file dir (for our API server), there's
// no need to separate the two yet. This lets us serve the swagger.json file.
- apiHandler := apiServer.NewRouter(s.log, s.node, apiToken)
+ apiHandler := apiServer.NewRouter(s.log, s.node, s.stopping, apiToken)
addr := cfg.EndpointAddress
if addr == "" {
@@ -202,8 +202,6 @@ func (s *Server) Start() {
WriteTimeout: time.Duration(cfg.RestWriteTimeoutSeconds) * time.Second,
}
- defer s.Stop()
-
tcpListener := listener.(*net.TCPListener)
errChan := make(chan error, 1)
go func() {
@@ -227,30 +225,28 @@ func (s *Server) Start() {
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
signal.Ignore(syscall.SIGHUP)
- go func() {
- sig := <-c
+
+ fmt.Printf("Node running and accepting RPC requests over HTTP on port %v. Press Ctrl-C to exit\n", addr)
+ select {
+ case err := <-errChan:
+ if err != nil {
+ s.log.Warn(err)
+ } else {
+ s.log.Info("Node exited successfully")
+ }
+ s.Stop()
+ case sig := <-c:
fmt.Printf("Exiting on %v\n", sig)
s.Stop()
os.Exit(0)
- }()
-
- fmt.Printf("Node running and accepting RPC requests over HTTP on port %v. Press Ctrl-C to exit\n", addr)
- err = <-errChan
- if err != nil {
- s.log.Warn(err)
- } else {
- s.log.Info("Node exited successfully")
}
}
// Stop initiates a graceful shutdown of the node by shutting down the network server.
func (s *Server) Stop() {
- s.stopping.Lock()
- defer s.stopping.Unlock()
-
- if s.stopped {
- return
- }
+ // close the s.stopping, which would signal the rest api router that any pending commands
+ // should be aborted.
+ close(s.stopping)
// Attempt to log a shutdown event before we exit...
s.log.Event(telemetryspec.ApplicationState, telemetryspec.ShutdownEvent)
@@ -275,8 +271,6 @@ func (s *Server) Stop() {
os.Remove(s.pidFile)
os.Remove(s.netFile)
os.Remove(s.netListenFile)
-
- s.stopped = true
}
// OverridePhonebook is used to replace the phonebook associated with
diff --git a/daemon/algod/server_test.go b/daemon/algod/server_test.go
index 4848e833a5..d414d02be1 100644
--- a/daemon/algod/server_test.go
+++ b/daemon/algod/server_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/api/api.go b/daemon/kmd/api/api.go
index 142f5ed7e0..d38fb85adc 100644
--- a/daemon/kmd/api/api.go
+++ b/daemon/kmd/api/api.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/api/cors.go b/daemon/kmd/api/cors.go
index e401e580ef..06548eb75d 100644
--- a/daemon/kmd/api/cors.go
+++ b/daemon/kmd/api/cors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/api/v1/auth.go b/daemon/kmd/api/v1/auth.go
index 0963d0d779..33fbeaae97 100644
--- a/daemon/kmd/api/v1/auth.go
+++ b/daemon/kmd/api/v1/auth.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/api/v1/errors.go b/daemon/kmd/api/v1/errors.go
index c5566d6fc4..bb9c60ea6c 100644
--- a/daemon/kmd/api/v1/errors.go
+++ b/daemon/kmd/api/v1/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/api/v1/handlers.go b/daemon/kmd/api/v1/handlers.go
index 5d0049c574..a984da2c40 100644
--- a/daemon/kmd/api/v1/handlers.go
+++ b/daemon/kmd/api/v1/handlers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/client/client.go b/daemon/kmd/client/client.go
index 037ea7af0a..68d21c3bb9 100644
--- a/daemon/kmd/client/client.go
+++ b/daemon/kmd/client/client.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/client/requests.go b/daemon/kmd/client/requests.go
index 4e8ad50838..683f801b2c 100644
--- a/daemon/kmd/client/requests.go
+++ b/daemon/kmd/client/requests.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/client/wrappers.go b/daemon/kmd/client/wrappers.go
index 0393eaa0e1..581f66675e 100644
--- a/daemon/kmd/client/wrappers.go
+++ b/daemon/kmd/client/wrappers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/config/config.go b/daemon/kmd/config/config.go
index 5e2318fd05..9e10f59e77 100644
--- a/daemon/kmd/config/config.go
+++ b/daemon/kmd/config/config.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/config/errors.go b/daemon/kmd/config/errors.go
index 3635659855..e4a051c211 100644
--- a/daemon/kmd/config/errors.go
+++ b/daemon/kmd/config/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/kmd.go b/daemon/kmd/kmd.go
index 355145aaab..6ed2587db1 100644
--- a/daemon/kmd/kmd.go
+++ b/daemon/kmd/kmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/lib/kmdapi/common.go b/daemon/kmd/lib/kmdapi/common.go
index e2d3cef646..5263e9ba02 100644
--- a/daemon/kmd/lib/kmdapi/common.go
+++ b/daemon/kmd/lib/kmdapi/common.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/lib/kmdapi/requests.go b/daemon/kmd/lib/kmdapi/requests.go
index f79f0945ad..070b3429b9 100644
--- a/daemon/kmd/lib/kmdapi/requests.go
+++ b/daemon/kmd/lib/kmdapi/requests.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/lib/kmdapi/responses.go b/daemon/kmd/lib/kmdapi/responses.go
index ee91607072..a47b24af48 100644
--- a/daemon/kmd/lib/kmdapi/responses.go
+++ b/daemon/kmd/lib/kmdapi/responses.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/server/errors.go b/daemon/kmd/server/errors.go
index 5f28234216..ade13a0601 100644
--- a/daemon/kmd/server/errors.go
+++ b/daemon/kmd/server/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/server/server.go b/daemon/kmd/server/server.go
index e3298fea1e..92eb22c2c3 100644
--- a/daemon/kmd/server/server.go
+++ b/daemon/kmd/server/server.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/session/auth.go b/daemon/kmd/session/auth.go
index b823896f0b..857c27dea2 100644
--- a/daemon/kmd/session/auth.go
+++ b/daemon/kmd/session/auth.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/session/session.go b/daemon/kmd/session/session.go
index d4177d0e58..6afea8d2eb 100644
--- a/daemon/kmd/session/session.go
+++ b/daemon/kmd/session/session.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/driver.go b/daemon/kmd/wallet/driver/driver.go
index b6545e50ae..53b8bcb88c 100644
--- a/daemon/kmd/wallet/driver/driver.go
+++ b/daemon/kmd/wallet/driver/driver.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/ledger.go b/daemon/kmd/wallet/driver/ledger.go
index ee2b404a0a..0e4d777d99 100644
--- a/daemon/kmd/wallet/driver/ledger.go
+++ b/daemon/kmd/wallet/driver/ledger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/ledger_errors.go b/daemon/kmd/wallet/driver/ledger_errors.go
index 2f9f70e7b6..337f9242cc 100644
--- a/daemon/kmd/wallet/driver/ledger_errors.go
+++ b/daemon/kmd/wallet/driver/ledger_errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/ledger_hid.go b/daemon/kmd/wallet/driver/ledger_hid.go
index ca87f4b71b..0b5e58b823 100644
--- a/daemon/kmd/wallet/driver/ledger_hid.go
+++ b/daemon/kmd/wallet/driver/ledger_hid.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/sqlite.go b/daemon/kmd/wallet/driver/sqlite.go
index fabee925e4..c9942f6017 100644
--- a/daemon/kmd/wallet/driver/sqlite.go
+++ b/daemon/kmd/wallet/driver/sqlite.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/sqlite_crypto.go b/daemon/kmd/wallet/driver/sqlite_crypto.go
index 81a9525d76..efe469cc57 100644
--- a/daemon/kmd/wallet/driver/sqlite_crypto.go
+++ b/daemon/kmd/wallet/driver/sqlite_crypto.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/sqlite_errors.go b/daemon/kmd/wallet/driver/sqlite_errors.go
index 79eef013e1..003bfd3c02 100644
--- a/daemon/kmd/wallet/driver/sqlite_errors.go
+++ b/daemon/kmd/wallet/driver/sqlite_errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/util.go b/daemon/kmd/wallet/driver/util.go
index 8c4f77c141..f9439094d9 100644
--- a/daemon/kmd/wallet/driver/util.go
+++ b/daemon/kmd/wallet/driver/util.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/wallet.go b/daemon/kmd/wallet/wallet.go
index 946f477cef..ed8e49ea37 100644
--- a/daemon/kmd/wallet/wallet.go
+++ b/daemon/kmd/wallet/wallet.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/account.go b/data/account/account.go
index 8dfdad5e02..c97162ebd9 100644
--- a/data/account/account.go
+++ b/data/account/account.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/partInstall.go b/data/account/partInstall.go
index 523fde4065..4d59c82d3e 100644
--- a/data/account/partInstall.go
+++ b/data/account/partInstall.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/participation.go b/data/account/participation.go
index 3114164710..af5e403859 100644
--- a/data/account/participation.go
+++ b/data/account/participation.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/participation_test.go b/data/account/participation_test.go
index cb8e524221..5eb0767fec 100644
--- a/data/account/participation_test.go
+++ b/data/account/participation_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/rootInstall.go b/data/account/rootInstall.go
index a085d5c1b4..faed519f46 100644
--- a/data/account/rootInstall.go
+++ b/data/account/rootInstall.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/accountManager.go b/data/accountManager.go
index 0f8766f775..0b527d4699 100644
--- a/data/accountManager.go
+++ b/data/accountManager.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/address.go b/data/basics/address.go
index bd57e40507..c0341517b1 100644
--- a/data/basics/address.go
+++ b/data/basics/address.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -33,6 +33,8 @@ const (
checksumLength = 4
)
+var base32Encoder = base32.StdEncoding.WithPadding(base32.NoPadding)
+
// GetChecksum returns the checksum as []byte
// Checksum in Algorand are the last 4 bytes of the shortAddress Hash. H(Address)[28:]
func (addr Address) GetChecksum() []byte {
@@ -48,7 +50,8 @@ func (addr Address) GetUserAddress() string {
// UnmarshalChecksumAddress tries to unmarshal the checksummed address string.
func UnmarshalChecksumAddress(address string) (Address, error) {
- decoded, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(address)
+ decoded, err := base32Encoder.DecodeString(address)
+
if err != nil {
return Address{}, fmt.Errorf("failed to decode address %s to base 32", address)
}
@@ -77,9 +80,12 @@ func UnmarshalChecksumAddress(address string) (Address, error) {
// String returns a string representation of Address
func (addr Address) String() string {
- var addrWithChecksum []byte
- addrWithChecksum = append(addr[:], addr.GetChecksum()...)
- return base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(addrWithChecksum)
+ addrWithChecksum := make([]byte, crypto.DigestSize+checksumLength)
+ copy(addrWithChecksum[:crypto.DigestSize], addr[:])
+ // calling addr.GetChecksum() here takes 20ns more than just rolling it out, so we'll just repeat that code.
+ shortAddressHash := crypto.Hash(addr[:])
+ copy(addrWithChecksum[crypto.DigestSize:], shortAddressHash[len(shortAddressHash)-checksumLength:])
+ return base32Encoder.EncodeToString(addrWithChecksum)
}
// MarshalText returns the address string as an array of bytes
diff --git a/data/basics/address_test.go b/data/basics/address_test.go
index b178a67818..485e6c70d3 100644
--- a/data/basics/address_test.go
+++ b/data/basics/address_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -107,3 +107,29 @@ func TestAddressMarshalUnmarshal(t *testing.T) {
require.NoError(t, err)
require.Equal(t, testob, nob)
}
+
+func BenchmarkAddressFormatting(b *testing.B) {
+ addr := "J5YDZLPOHWB5O6MVRHNFGY4JXIQAYYM6NUJWPBSYBBIXH5ENQ4Z5LTJELU"
+ uaddr, err := UnmarshalChecksumAddress(addr)
+ require.NoError(b, err)
+
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ stringed := uaddr.String()
+ if len(stringed) == 0 {
+ break
+ }
+ }
+}
+
+func BenchmarkUnmarshalChecksumAddress(b *testing.B) {
+ addr := "J5YDZLPOHWB5O6MVRHNFGY4JXIQAYYM6NUJWPBSYBBIXH5ENQ4Z5LTJELU"
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := UnmarshalChecksumAddress(addr)
+ if err != nil {
+ break
+ }
+ }
+}
diff --git a/data/basics/overflow.go b/data/basics/overflow.go
index 55cc8139c9..2937b82d9d 100644
--- a/data/basics/overflow.go
+++ b/data/basics/overflow.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/units.go b/data/basics/units.go
index 4ee87b59f9..bc12bfefb3 100644
--- a/data/basics/units.go
+++ b/data/basics/units.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/units_test.go b/data/basics/units_test.go
index 9d245a1266..2fe8d1447f 100644
--- a/data/basics/units_test.go
+++ b/data/basics/units_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/userBalance.go b/data/basics/userBalance.go
index 0244dbda68..1796c72c62 100644
--- a/data/basics/userBalance.go
+++ b/data/basics/userBalance.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/userBalance_test.go b/data/basics/userBalance_test.go
index 969f199770..087fbfe399 100644
--- a/data/basics/userBalance_test.go
+++ b/data/basics/userBalance_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/bookkeeping/block.go b/data/bookkeeping/block.go
index a2ad96cb54..e6119262bc 100644
--- a/data/bookkeeping/block.go
+++ b/data/bookkeeping/block.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -97,9 +97,9 @@ type (
//
// If enough votes are collected, the proposal is approved, and will
// definitely take effect. The proposal lingers for some number of
- // rounds (UpgradeWaitRounds) to give clients a chance to notify users
- // about an approved upgrade, if the client doesn't support it, so the
- // user has a chance to download updated client software.
+ // rounds to give clients a chance to notify users about an approved
+ // upgrade, if the client doesn't support it, so the user has a chance
+ // to download updated client software.
//
// Block proposers influence this upgrade machinery through two fields
// in UpgradeVote: UpgradePropose, which proposes an upgrade to a new
@@ -157,6 +157,9 @@ type (
// UpgradePropose indicates a proposed upgrade
UpgradePropose protocol.ConsensusVersion `codec:"upgradeprop"`
+ // UpgradeDelay indicates the time between acceptance and execution
+ UpgradeDelay basics.Round `codec:"upgradedelay"`
+
// UpgradeApprove indicates a yes vote for the current proposal
UpgradeApprove bool `codec:"upgradeyes"`
}
@@ -280,7 +283,7 @@ func (s RewardsState) NextRewardsState(nextRound basics.Round, nextProto config.
return
}
-// computeUpgradeState determines the UpgradeState for a block at round thisR,
+// applyUpgradeVote determines the UpgradeState for a block at round r,
// given the previous block's UpgradeState "s" and this block's UpgradeVote.
//
// This function returns an error if the input is not valid in prevState: that
@@ -290,37 +293,52 @@ func (s UpgradeState) applyUpgradeVote(r basics.Round, vote UpgradeVote) (res Up
// Locate the config parameters for current protocol
params, ok := config.Consensus[s.CurrentProtocol]
if !ok {
- err = fmt.Errorf("computeUpgradeState: unsupported protocol %v", s.CurrentProtocol)
+ err = fmt.Errorf("applyUpgradeVote: unsupported protocol %v", s.CurrentProtocol)
return
}
// Apply proposal of upgrade to new protocol
if vote.UpgradePropose != "" {
if s.NextProtocol != "" {
- err = fmt.Errorf("computeUpgradeState: new proposal during existing proposal")
+ err = fmt.Errorf("applyUpgradeVote: new proposal during existing proposal")
return
}
if len(vote.UpgradePropose) > params.MaxVersionStringLen {
- err = fmt.Errorf("proposed protocol version %s too long", vote.UpgradePropose)
+ err = fmt.Errorf("applyUpgradeVote: proposed protocol version %s too long", vote.UpgradePropose)
+ return
+ }
+
+ upgradeDelay := uint64(vote.UpgradeDelay)
+ if upgradeDelay > params.MaxUpgradeWaitRounds || upgradeDelay < params.MinUpgradeWaitRounds {
+ err = fmt.Errorf("applyUpgradeVote: proposed upgrade wait rounds %d out of permissible range", upgradeDelay)
return
}
+ if upgradeDelay == 0 {
+ upgradeDelay = params.DefaultUpgradeWaitRounds
+ }
+
s.NextProtocol = vote.UpgradePropose
s.NextProtocolApprovals = 0
s.NextProtocolVoteBefore = r + basics.Round(params.UpgradeVoteRounds)
- s.NextProtocolSwitchOn = r + basics.Round(params.UpgradeVoteRounds) + basics.Round(params.UpgradeWaitRounds)
+ s.NextProtocolSwitchOn = r + basics.Round(params.UpgradeVoteRounds) + basics.Round(upgradeDelay)
+ } else {
+ if vote.UpgradeDelay != 0 {
+ err = fmt.Errorf("applyUpgradeVote: upgrade delay %d nonzero when not proposing", vote.UpgradeDelay)
+ return
+ }
}
// Apply approval of existing protocol upgrade
if vote.UpgradeApprove {
if s.NextProtocol == "" {
- err = fmt.Errorf("computeUpgradeState: approval without an active proposal")
+ err = fmt.Errorf("applyUpgradeVote: approval without an active proposal")
return
}
if r >= s.NextProtocolVoteBefore {
- err = fmt.Errorf("computeUpgradeState: approval after vote deadline")
+ err = fmt.Errorf("applyUpgradeVote: approval after vote deadline")
return
}
@@ -364,20 +382,18 @@ func ProcessUpgradeParams(prev BlockHeader) (uv UpgradeVote, us UpgradeState, er
// If there is no upgrade proposal, see if we can make one
if prev.NextProtocol == "" {
for k, v := range prevParams.ApprovedUpgrades {
- if v {
- upgradeVote.UpgradePropose = k
- upgradeVote.UpgradeApprove = true
- break
- }
+ upgradeVote.UpgradePropose = k
+ upgradeVote.UpgradeDelay = basics.Round(v)
+ upgradeVote.UpgradeApprove = true
+ break
}
}
- // If there is a proposal being voted on, see if we approve it
+ // If there is a proposal being voted on, see if we approve it and its delay
round := prev.Round + 1
if round < prev.NextProtocolVoteBefore {
- if prevParams.ApprovedUpgrades[prev.NextProtocol] {
- upgradeVote.UpgradeApprove = true
- }
+ _, ok := prevParams.ApprovedUpgrades[prev.NextProtocol]
+ upgradeVote.UpgradeApprove = ok
}
upgradeState, err := prev.UpgradeState.applyUpgradeVote(round, upgradeVote)
diff --git a/data/bookkeeping/block_test.go b/data/bookkeeping/block_test.go
index eb2c0664e9..3c48874876 100644
--- a/data/bookkeeping/block_test.go
+++ b/data/bookkeeping/block_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -35,17 +35,26 @@ var proto1 = protocol.ConsensusVersion("Test1")
var proto2 = protocol.ConsensusVersion("Test2")
var proto3 = protocol.ConsensusVersion("Test3")
var protoUnsupported = protocol.ConsensusVersion("TestUnsupported")
+var protoDelay = protocol.ConsensusVersion("TestDelay")
func init() {
params1 := config.Consensus[protocol.ConsensusCurrentVersion]
- params1.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{
- proto2: true,
+ params1.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{
+ proto2: 0,
}
config.Consensus[proto1] = params1
params2 := config.Consensus[protocol.ConsensusCurrentVersion]
- params2.ApprovedUpgrades = map[protocol.ConsensusVersion]bool{}
+ params2.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
config.Consensus[proto2] = params2
+
+ paramsDelay := config.Consensus[protocol.ConsensusCurrentVersion]
+ paramsDelay.MinUpgradeWaitRounds = 3
+ paramsDelay.MaxUpgradeWaitRounds = 7
+ paramsDelay.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{
+ proto1: 5,
+ }
+ config.Consensus[protoDelay] = paramsDelay
}
func TestUpgradeVote(t *testing.T) {
@@ -109,6 +118,30 @@ func TestUpgradeVote(t *testing.T) {
require.Equal(t, s1.NextProtocolSwitchOn, basics.Round(0))
}
+func TestUpgradeVariableDelay(t *testing.T) {
+ s := UpgradeState{
+ CurrentProtocol: protoDelay,
+ }
+
+ _, err := s.applyUpgradeVote(basics.Round(10), UpgradeVote{UpgradePropose: proto1, UpgradeDelay: 2})
+ require.Error(t, err, "accepted upgrade vote with delay less than MinUpgradeWaitRounds")
+
+ _, err = s.applyUpgradeVote(basics.Round(10), UpgradeVote{UpgradePropose: proto1, UpgradeDelay: 8})
+ require.Error(t, err, "accepted upgrade vote with delay more than MaxUpgradeWaitRounds")
+
+ _, err = s.applyUpgradeVote(basics.Round(10), UpgradeVote{UpgradePropose: proto1, UpgradeDelay: 5})
+ require.NoError(t, err, "did not accept upgrade vote with in-bounds delay")
+
+ _, err = s.applyUpgradeVote(basics.Round(10), UpgradeVote{UpgradePropose: proto1, UpgradeDelay: 3})
+ require.NoError(t, err, "did not accept upgrade vote with minimal delay")
+
+ _, err = s.applyUpgradeVote(basics.Round(10), UpgradeVote{UpgradePropose: proto1, UpgradeDelay: 7})
+ require.NoError(t, err, "did not accept upgrade vote with maximal delay")
+
+ _, err = s.applyUpgradeVote(basics.Round(10), UpgradeVote{UpgradePropose: proto1, UpgradeDelay: 0})
+ require.Error(t, err, "accepted upgrade vote with zero (below minimal) delay")
+}
+
func TestMakeBlockUpgrades(t *testing.T) {
var b Block
b.BlockHeader.GenesisID = t.Name()
@@ -133,6 +166,30 @@ func TestMakeBlockUpgrades(t *testing.T) {
require.NoError(t, err)
require.Equal(t, b3.UpgradePropose, protocol.ConsensusVersion(""))
require.Equal(t, b3.UpgradeApprove, false)
+
+ var bd Block
+ bd.BlockHeader.GenesisID = t.Name()
+ bd.CurrentProtocol = protoDelay
+ bd.BlockHeader.GenesisID = "test"
+ crypto.RandBytes(bd.BlockHeader.GenesisHash[:])
+
+ bd1 := MakeBlock(bd.BlockHeader)
+ err = bd1.PreCheck(bd.BlockHeader)
+ require.NoError(t, err)
+ require.Equal(t, bd1.UpgradePropose, proto1)
+ require.Equal(t, bd1.UpgradeApprove, true)
+ require.Equal(t, bd1.UpgradeDelay, basics.Round(5))
+ require.Equal(t, bd1.NextProtocol, proto1)
+ require.Equal(t, bd1.NextProtocolSwitchOn-bd1.NextProtocolVoteBefore, basics.Round(5))
+
+ bd2 := MakeBlock(bd1.BlockHeader)
+ err = bd2.PreCheck(bd1.BlockHeader)
+ require.NoError(t, err)
+ require.Equal(t, bd2.UpgradePropose, protocol.ConsensusVersion(""))
+ require.Equal(t, bd2.UpgradeApprove, true)
+ require.Equal(t, bd2.UpgradeDelay, basics.Round(0))
+ require.Equal(t, bd2.NextProtocol, proto1)
+ require.Equal(t, bd2.NextProtocolSwitchOn-bd2.NextProtocolVoteBefore, basics.Round(5))
}
func TestBlockUnsupported(t *testing.T) {
diff --git a/data/bookkeeping/encoding_test.go b/data/bookkeeping/encoding_test.go
index 50b72e97fa..9be938a976 100644
--- a/data/bookkeeping/encoding_test.go
+++ b/data/bookkeeping/encoding_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/bookkeeping/genesis.go b/data/bookkeeping/genesis.go
index 8937ff9288..c34c56bd74 100644
--- a/data/bookkeeping/genesis.go
+++ b/data/bookkeeping/genesis.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/bookkeeping/prettyprinting.go b/data/bookkeeping/prettyprinting.go
index 05d10ca718..418c5d959f 100644
--- a/data/bookkeeping/prettyprinting.go
+++ b/data/bookkeeping/prettyprinting.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/committee.go b/data/committee/committee.go
index 85ed9325cc..fa8687aaaa 100644
--- a/data/committee/committee.go
+++ b/data/committee/committee.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/common_test.go b/data/committee/common_test.go
index db7db5667b..542884a665 100644
--- a/data/committee/common_test.go
+++ b/data/committee/common_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/credential.go b/data/committee/credential.go
index f91fa11fd2..5d8168fe27 100644
--- a/data/committee/credential.go
+++ b/data/committee/credential.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/credential_test.go b/data/committee/credential_test.go
index b41b4ca2fa..df46a72ac2 100644
--- a/data/committee/credential_test.go
+++ b/data/committee/credential_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/encoding_test.go b/data/committee/encoding_test.go
index 512d8bce8d..4602eed792 100644
--- a/data/committee/encoding_test.go
+++ b/data/committee/encoding_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/sortition/sortition.go b/data/committee/sortition/sortition.go
index c3e281324c..e4fc15afe4 100644
--- a/data/committee/sortition/sortition.go
+++ b/data/committee/sortition/sortition.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/sortition/sortition_test.go b/data/committee/sortition/sortition_test.go
index b997f0d580..d94d1ce883 100644
--- a/data/committee/sortition/sortition_test.go
+++ b/data/committee/sortition/sortition_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/common_test.go b/data/common_test.go
index 91424a3c12..4a77242d02 100644
--- a/data/common_test.go
+++ b/data/common_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/datatest/fabricateLedger.go b/data/datatest/fabricateLedger.go
index c5a9dd5413..0d5b407822 100644
--- a/data/datatest/fabricateLedger.go
+++ b/data/datatest/fabricateLedger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/datatest/impls.go b/data/datatest/impls.go
index 2ecc33a71a..9c570a654a 100644
--- a/data/datatest/impls.go
+++ b/data/datatest/impls.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/encoding_test.go b/data/encoding_test.go
index f69a58416f..e67dd59c27 100644
--- a/data/encoding_test.go
+++ b/data/encoding_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/genesisBalances.go b/data/genesisBalances.go
index da33f50c6e..20e408938d 100644
--- a/data/genesisBalances.go
+++ b/data/genesisBalances.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/hashable/message.go b/data/hashable/message.go
index 7462391007..95e14c9b8a 100644
--- a/data/hashable/message.go
+++ b/data/hashable/message.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/ledger.go b/data/ledger.go
index 7bc59aa3ff..f1ca591912 100644
--- a/data/ledger.go
+++ b/data/ledger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/ledger_test.go b/data/ledger_test.go
index 92accbaa09..76a3c902d1 100644
--- a/data/ledger_test.go
+++ b/data/ledger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/pools/ewma.go b/data/pools/ewma.go
index 6331e7aecf..ba0f740da6 100644
--- a/data/pools/ewma.go
+++ b/data/pools/ewma.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/pools/ewma_test.go b/data/pools/ewma_test.go
index 4dfc38369f..2f8dbc33d6 100644
--- a/data/pools/ewma_test.go
+++ b/data/pools/ewma_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/pools/feeTracker.go b/data/pools/feeTracker.go
index 1a7e247de2..44c7853f56 100644
--- a/data/pools/feeTracker.go
+++ b/data/pools/feeTracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/pools/feeTracker_test.go b/data/pools/feeTracker_test.go
index d06f6647ac..3d0f34e449 100644
--- a/data/pools/feeTracker_test.go
+++ b/data/pools/feeTracker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/pools/statusCache.go b/data/pools/statusCache.go
index 5d545ca577..9a71d05f1f 100644
--- a/data/pools/statusCache.go
+++ b/data/pools/statusCache.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/pools/transactionPool.go b/data/pools/transactionPool.go
index 71d49611b8..fe108e448b 100644
--- a/data/pools/transactionPool.go
+++ b/data/pools/transactionPool.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/pools/transactionPool_test.go b/data/pools/transactionPool_test.go
index de53121567..757b14b0fe 100644
--- a/data/pools/transactionPool_test.go
+++ b/data/pools/transactionPool_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/aggregates.go b/data/transactions/aggregates.go
index e1911c59cc..006e8b559f 100644
--- a/data/transactions/aggregates.go
+++ b/data/transactions/aggregates.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/aggregates_test.go b/data/transactions/aggregates_test.go
index 2b0aa153e7..87b67e9b5e 100644
--- a/data/transactions/aggregates_test.go
+++ b/data/transactions/aggregates_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/asset.go b/data/transactions/asset.go
index 967eb8f57f..99b8870194 100644
--- a/data/transactions/asset.go
+++ b/data/transactions/asset.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/common_test.go b/data/transactions/common_test.go
index 868046995d..e993bf1123 100644
--- a/data/transactions/common_test.go
+++ b/data/transactions/common_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/error.go b/data/transactions/error.go
index 93bc4f6e3f..e584653911 100644
--- a/data/transactions/error.go
+++ b/data/transactions/error.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/keyreg.go b/data/transactions/keyreg.go
index dc613992e7..be6f531189 100644
--- a/data/transactions/keyreg.go
+++ b/data/transactions/keyreg.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/keyreg_test.go b/data/transactions/keyreg_test.go
index 2c4df758c7..7998c46ba7 100644
--- a/data/transactions/keyreg_test.go
+++ b/data/transactions/keyreg_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/assembler.go b/data/transactions/logic/assembler.go
index 29569e9542..c0262a080a 100644
--- a/data/transactions/logic/assembler.go
+++ b/data/transactions/logic/assembler.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go
index 7888cc3810..9daf98e579 100644
--- a/data/transactions/logic/assembler_test.go
+++ b/data/transactions/logic/assembler_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/doc.go b/data/transactions/logic/doc.go
index c4cdce30d2..7d51689dc4 100644
--- a/data/transactions/logic/doc.go
+++ b/data/transactions/logic/doc.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/doc_test.go b/data/transactions/logic/doc_test.go
index 29fb6ffb9d..72abd8fdf3 100644
--- a/data/transactions/logic/doc_test.go
+++ b/data/transactions/logic/doc_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go
index 90ed394aa0..0ef3ec15c1 100644
--- a/data/transactions/logic/eval.go
+++ b/data/transactions/logic/eval.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go
index 257131c7eb..fc228fe45e 100644
--- a/data/transactions/logic/eval_test.go
+++ b/data/transactions/logic/eval_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/program.go b/data/transactions/logic/program.go
index 408f4210db..fcb6c50b27 100644
--- a/data/transactions/logic/program.go
+++ b/data/transactions/logic/program.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logicsig.go b/data/transactions/logicsig.go
index a4b04d7169..b5c19078fb 100644
--- a/data/transactions/logicsig.go
+++ b/data/transactions/logicsig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/payment.go b/data/transactions/payment.go
index 3ea4dc36e2..c4d1d63d2d 100644
--- a/data/transactions/payment.go
+++ b/data/transactions/payment.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/payment_test.go b/data/transactions/payment_test.go
index b1f0f1cc68..6bd3fd6249 100644
--- a/data/transactions/payment_test.go
+++ b/data/transactions/payment_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/perf_test.go b/data/transactions/perf_test.go
index 37704f246f..1051f58a9e 100644
--- a/data/transactions/perf_test.go
+++ b/data/transactions/perf_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/signedtxn.go b/data/transactions/signedtxn.go
index 6fe0ddf3ce..c41ed37f81 100644
--- a/data/transactions/signedtxn.go
+++ b/data/transactions/signedtxn.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/signedtxn_test.go b/data/transactions/signedtxn_test.go
index 0594cb785d..dbc7923295 100644
--- a/data/transactions/signedtxn_test.go
+++ b/data/transactions/signedtxn_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/testhelpers.go b/data/transactions/testhelpers.go
index 35e10bc31e..230fbfbf39 100644
--- a/data/transactions/testhelpers.go
+++ b/data/transactions/testhelpers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/transaction.go b/data/transactions/transaction.go
index 591d68aa3f..14e1e3206a 100644
--- a/data/transactions/transaction.go
+++ b/data/transactions/transaction.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/transaction_test.go b/data/transactions/transaction_test.go
index c29e84632b..88445e959f 100644
--- a/data/transactions/transaction_test.go
+++ b/data/transactions/transaction_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/verify/txn.go b/data/transactions/verify/txn.go
index 28c6229e71..ef59f6ddf5 100644
--- a/data/transactions/verify/txn.go
+++ b/data/transactions/verify/txn.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/verify/txn_test.go b/data/transactions/verify/txn_test.go
index 3fced94d84..121e733288 100644
--- a/data/transactions/verify/txn_test.go
+++ b/data/transactions/verify/txn_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/txHandler.go b/data/txHandler.go
index 1a5daa35cc..b3fb24ae8f 100644
--- a/data/txHandler.go
+++ b/data/txHandler.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/txHandler_test.go b/data/txHandler_test.go
index 9ea0a30ba1..10c462a381 100644
--- a/data/txHandler_test.go
+++ b/data/txHandler_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/debug/carpenter/main.go b/debug/carpenter/main.go
index aa3c087f7b..a196057e5b 100644
--- a/debug/carpenter/main.go
+++ b/debug/carpenter/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/debug/coroner/main.go b/debug/coroner/main.go
index 91db4f25d8..4ff681a122 100644
--- a/debug/coroner/main.go
+++ b/debug/coroner/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/debug/doberman/logo.go b/debug/doberman/logo.go
index 77d2f1b78b..bdcfe762fc 100644
--- a/debug/doberman/logo.go
+++ b/debug/doberman/logo.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/debug/doberman/main.go b/debug/doberman/main.go
index 471789c2e0..a351469734 100644
--- a/debug/doberman/main.go
+++ b/debug/doberman/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/docker/build/Dockerfile b/docker/build/Dockerfile
index f502a81ec6..d3d0e20e9b 100644
--- a/docker/build/Dockerfile
+++ b/docker/build/Dockerfile
@@ -1,7 +1,7 @@
FROM ubuntu:16.04
ENV GOLANG_VERSION 1.12
-RUN apt update && apt install -y git libboost-all-dev wget sqlite3 autoconf build-essential
+RUN apt-get update && apt-get install -y git libboost-all-dev wget sqlite3 autoconf build-essential shellcheck
WORKDIR /root
RUN wget --quiet https://dl.google.com/go/go${GOLANG_VERSION}.linux-amd64.tar.gz && tar -xvf go${GOLANG_VERSION}.linux-amd64.tar.gz && mv go /usr/local
ENV GOROOT=/usr/local/go \
diff --git a/docker/build/Dockerfile-deploy b/docker/build/Dockerfile-deploy
index 560f7d0279..69fdbd3145 100644
--- a/docker/build/Dockerfile-deploy
+++ b/docker/build/Dockerfile-deploy
@@ -1,7 +1,7 @@
FROM ubuntu:18.04
ENV GOLANG_VERSION 1.12
-RUN apt update && apt install -y git libboost-all-dev wget sqlite3 autoconf jq bsdmainutils
+RUN apt-get update && apt-get install -y git libboost-all-dev wget sqlite3 autoconf jq bsdmainutils shellcheck
WORKDIR /root
RUN wget --quiet https://dl.google.com/go/go${GOLANG_VERSION}.linux-amd64.tar.gz && tar -xvf go${GOLANG_VERSION}.linux-amd64.tar.gz && mv go /usr/local
ENV GOROOT=/usr/local/go \
diff --git a/docker/releases/Dockerfile-stable b/docker/releases/Dockerfile-stable
deleted file mode 100644
index b62e5cb940..0000000000
--- a/docker/releases/Dockerfile-stable
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM ubuntu
-
-WORKDIR /root/install
-RUN apt update && apt install -y ca-certificates curl --no-install-recommends && \
- curl --silent -L https://github.com/algorand/go-algorand-doc/blob/master/downloads/installers/linux_amd64/install_master_linux-amd64.tar.gz?raw=true -o installer.tar.gz && \
- tar -xf installer.tar.gz && \
- ./update.sh -c stable -n -p ~/node -d ~/node/data -i && \
- cd .. && \
- rm -rf /var/lib/apt/lists/* && \
- rm -rf install
-WORKDIR /root/node
-
-ENTRYPOINT ["/bin/bash"]
diff --git a/docker/releases/Dockerfile-stable-testnet b/docker/releases/Dockerfile-stable-testnet
deleted file mode 100644
index d422632ac3..0000000000
--- a/docker/releases/Dockerfile-stable-testnet
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM ubuntu
-
-WORKDIR /root/install
-RUN apt update && apt install -y ca-certificates curl --no-install-recommends && \
- curl --silent -L https://github.com/algorand/go-algorand-doc/blob/master/downloads/installers/linux_amd64/install_master_linux-amd64.tar.gz?raw=true -o installer.tar.gz && \
- tar -xf installer.tar.gz && \
- ./update.sh -c stable -n -p ~/node -d ~/node/data -i -g testnet && \
- cd .. && \
- rm -rf /var/lib/apt/lists/* && \
- rm -rf install
-WORKDIR /root/node
-
-ENTRYPOINT ["/bin/bash"]
diff --git a/docker/releases/build_releases.sh b/docker/releases/build_releases.sh
new file mode 100755
index 0000000000..c944dc1dda
--- /dev/null
+++ b/docker/releases/build_releases.sh
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+
+# Need to log in to Docker desktop before docker push will succeed.
+# e.g. `docker login`
+# Login name is "algorand".
+
+# To build both images, one could run:
+#
+# $ ./build_releases.sh
+# $ ./build_releases.sh testnet
+#
+# or
+#
+# for name in {mainnet,testnet}
+# do
+# ./build_releases.sh $name
+# done
+
+GREEN_FG=$(tput setaf 2 2>/dev/null)
+RED_FG=$(tput setaf 1 2>/dev/null)
+END_FG_COLOR=$(tput sgr0 2>/dev/null)
+
+# Default to "mainnet".
+NAME=${1:-mainnet}
+NETWORK=
+
+if [[ ! "$NAME" =~ ^mainnet$|^testnet$ ]]
+then
+ echo "$RED_FG[$0]$END_FG_COLOR Network values must be either \`mainnet\` or \`testnet\`."
+ exit 1
+fi
+
+if [ "$NAME" == "testnet" ]
+then
+ NETWORK="-g $1"
+fi
+
+build_image () {
+ IFS='' read -r -d '' DOCKERFILE < 0 || partKeyCreated > 0) {
+ fmt.Printf("Created %d new rootkeys and %d new partkeys.\n", rootKeyCreated, partKeyCreated)
+ }
+
return
}
diff --git a/gen/pregen/mainnet/metadata.json b/gen/pregen/mainnet/metadata.json
index 21abed6718..88ca4ac456 100644
--- a/gen/pregen/mainnet/metadata.json
+++ b/gen/pregen/mainnet/metadata.json
@@ -1,6 +1,6 @@
{
"Network": "mainnet",
- "SchemaID": "v0.9",
+ "SchemaID": "v1.0",
"ConsensusProtocol": "https://github.com/algorandfoundation/specs/tree/5615adc36bad610c7f165fa2967f4ecfa75125f0",
"Comment": ""
}
diff --git a/gen/walletData.go b/gen/walletData.go
index 3efd6d6b3a..b077be0402 100644
--- a/gen/walletData.go
+++ b/gen/walletData.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/installer/config.json.example b/installer/config.json.example
index 58459753ac..c0b5eef526 100644
--- a/installer/config.json.example
+++ b/installer/config.json.example
@@ -14,6 +14,7 @@
"EnableIncomingMessageFilter": false,
"EnableMetricReporting": false,
"EnableOutgoingNetworkMessageFiltering": true,
+ "EnableProfiler": false,
"EnableRequestLogger": false,
"EnableTopAccountsReporting": false,
"EndpointAddress": "127.0.0.1:0",
@@ -40,6 +41,7 @@
"RunHosted": false,
"SuggestedFeeBlockHistory": 3,
"SuggestedFeeSlidingWindowSize": 50,
+ "TelemetryToLog": true,
"TxPoolExponentialIncreaseFactor": 2,
"TxPoolSize": 15000,
"TxSyncIntervalSeconds": 60,
diff --git a/ledger/accountdb.go b/ledger/accountdb.go
index 3b663c0cdc..b9350c9735 100644
--- a/ledger/accountdb.go
+++ b/ledger/accountdb.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/accountdb_test.go b/ledger/accountdb_test.go
index 4ffe3845ef..db6babcda0 100644
--- a/ledger/accountdb_test.go
+++ b/ledger/accountdb_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/acctupdates.go b/ledger/acctupdates.go
index bc6f5e12a0..05440629ed 100644
--- a/ledger/acctupdates.go
+++ b/ledger/acctupdates.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/acctupdates_test.go b/ledger/acctupdates_test.go
index e1270325b3..d218526bbc 100644
--- a/ledger/acctupdates_test.go
+++ b/ledger/acctupdates_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/archival_test.go b/ledger/archival_test.go
index d6c8199718..853450e996 100644
--- a/ledger/archival_test.go
+++ b/ledger/archival_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/blockdb.go b/ledger/blockdb.go
index a18e960ce8..aabaf2b3e6 100644
--- a/ledger/blockdb.go
+++ b/ledger/blockdb.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -158,11 +158,6 @@ func blockGetAux(tx *sql.Tx, rnd basics.Round) (blk bookkeeping.Block, aux evalA
return
}
- err = protocol.Decode(auxbuf, &aux)
- if err != nil {
- return
- }
-
return
}
diff --git a/ledger/blockdb_test.go b/ledger/blockdb_test.go
index 8cb9b55ac1..d57a3ad558 100644
--- a/ledger/blockdb_test.go
+++ b/ledger/blockdb_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/blockqueue.go b/ledger/blockqueue.go
index 0f3b74602f..fb6609b62e 100644
--- a/ledger/blockqueue.go
+++ b/ledger/blockqueue.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/bulletin.go b/ledger/bulletin.go
index 01d2cb079f..688b864729 100644
--- a/ledger/bulletin.go
+++ b/ledger/bulletin.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/bulletin_test.go b/ledger/bulletin_test.go
index f67862287e..fb1c273157 100644
--- a/ledger/bulletin_test.go
+++ b/ledger/bulletin_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/cow.go b/ledger/cow.go
index 50d2be64fb..5fce59544a 100644
--- a/ledger/cow.go
+++ b/ledger/cow.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/cow_test.go b/ledger/cow_test.go
index 1d6f066ead..69444f96ec 100644
--- a/ledger/cow_test.go
+++ b/ledger/cow_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/dbcommon.go b/ledger/dbcommon.go
index 96acd8d5a2..e8c84722e5 100644
--- a/ledger/dbcommon.go
+++ b/ledger/dbcommon.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/error.go b/ledger/error.go
index ea901149e9..010d201d17 100644
--- a/ledger/error.go
+++ b/ledger/error.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval.go b/ledger/eval.go
index 1f96c97d15..d96c98a274 100644
--- a/ledger/eval.go
+++ b/ledger/eval.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval_test.go b/ledger/eval_test.go
index 718038c6d4..310f77e361 100644
--- a/ledger/eval_test.go
+++ b/ledger/eval_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledger.go b/ledger/ledger.go
index 267b1b166e..befee4f838 100644
--- a/ledger/ledger.go
+++ b/ledger/ledger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledger_test.go b/ledger/ledger_test.go
index ecfd1bd444..4925b397b4 100644
--- a/ledger/ledger_test.go
+++ b/ledger/ledger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/metrics.go b/ledger/metrics.go
index db59ca4d75..e694c84f98 100644
--- a/ledger/metrics.go
+++ b/ledger/metrics.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/notifier.go b/ledger/notifier.go
index e205795327..c77e88ec6f 100644
--- a/ledger/notifier.go
+++ b/ledger/notifier.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/perf_test.go b/ledger/perf_test.go
index d64f300299..becb1c8e5e 100644
--- a/ledger/perf_test.go
+++ b/ledger/perf_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/roundlru.go b/ledger/roundlru.go
index 8b5115ee4e..3b8311f3f5 100644
--- a/ledger/roundlru.go
+++ b/ledger/roundlru.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/roundlru_test.go b/ledger/roundlru_test.go
index 60e09bea89..c5f6dae3fb 100644
--- a/ledger/roundlru_test.go
+++ b/ledger/roundlru_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/time.go b/ledger/time.go
index bb92abe6a2..61e61d0666 100644
--- a/ledger/time.go
+++ b/ledger/time.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/totals.go b/ledger/totals.go
index 464d7af80e..987307ee86 100644
--- a/ledger/totals.go
+++ b/ledger/totals.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/tracker.go b/ledger/tracker.go
index 7098d73b74..55f8202424 100644
--- a/ledger/tracker.go
+++ b/ledger/tracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/txtail.go b/ledger/txtail.go
index 87ba67047c..bac5eb13ca 100644
--- a/ledger/txtail.go
+++ b/ledger/txtail.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/accounts.go b/libgoal/accounts.go
index 022848c23b..002aa3218c 100644
--- a/libgoal/accounts.go
+++ b/libgoal/accounts.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/error.go b/libgoal/error.go
index 27b1f93132..97b749a1ff 100644
--- a/libgoal/error.go
+++ b/libgoal/error.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/libgoal.go b/libgoal/libgoal.go
index d51726caac..cbf64dcced 100644
--- a/libgoal/libgoal.go
+++ b/libgoal/libgoal.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -672,6 +672,15 @@ func (c *Client) Block(round uint64) (resp v1.Block, err error) {
return
}
+// RawBlock takes a round and returns its block
+func (c *Client) RawBlock(round uint64) (resp v1.RawBlock, err error) {
+ algod, err := c.ensureAlgodClient()
+ if err == nil {
+ resp, err = algod.RawBlock(round)
+ }
+ return
+}
+
// HealthCheck returns an error if something is wrong
func (c *Client) HealthCheck() error {
algod, err := c.ensureAlgodClient()
diff --git a/libgoal/libgoal_test.go b/libgoal/libgoal_test.go
index 2f2541ee20..9800845d24 100644
--- a/libgoal/libgoal_test.go
+++ b/libgoal/libgoal_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/lockedFile.go b/libgoal/lockedFile.go
new file mode 100644
index 0000000000..36a96b2d7b
--- /dev/null
+++ b/libgoal/lockedFile.go
@@ -0,0 +1,104 @@
+// Copyright (C) 2019-2020 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see .
+
+package libgoal
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+)
+
+type locker interface {
+ tryRLock(fd *os.File) error
+ tryLock(fd *os.File) error
+ unlock(fd *os.File) error
+}
+
+func newLockedFile(path string) *lockedFile {
+ return &lockedFile{
+ path: path,
+ locker: makeLocker(),
+ }
+}
+
+// lockedFile implementation
+// It a platform-agnostic with appropriate locker implementation.
+// Each platform needs own specific `newLockedFile`
+
+type lockedFile struct {
+ path string
+ locker locker
+}
+
+func (f *lockedFile) read() (bytes []byte, err error) {
+ fd, err := os.Open(f.path)
+ if err != nil {
+ return
+ }
+ defer func() {
+ err2 := fd.Close()
+ if err2 != nil {
+ err = err2
+ }
+ }()
+
+ err = f.locker.tryRLock(fd)
+ if err != nil {
+ err = fmt.Errorf("Can't acquire read lock for %s: %s", f.path, err.Error())
+ return
+ }
+ defer func() {
+ err2 := f.locker.unlock(fd)
+ if err2 != nil {
+ err = fmt.Errorf("Can't unlock for %s: %s", f.path, err2.Error())
+ }
+ }()
+
+ bytes, err = ioutil.ReadAll(fd)
+ return
+}
+
+func (f *lockedFile) write(data []byte, perm os.FileMode) (err error) {
+ fd, err := os.OpenFile(f.path, os.O_WRONLY|os.O_CREATE, perm)
+ if err != nil {
+ return
+ }
+ defer func() {
+ err2 := fd.Close()
+ if err2 != nil {
+ err = err2
+ }
+ }()
+
+ err = f.locker.tryLock(fd)
+ if err != nil {
+ return fmt.Errorf("Can't acquire lock for %s: %s", f.path, err.Error())
+ }
+ defer func() {
+ err2 := f.locker.unlock(fd)
+ if err2 != nil {
+ err = fmt.Errorf("Can't unlock for %s: %s", f.path, err2.Error())
+ }
+ }()
+
+ err = fd.Truncate(0)
+ if err != nil {
+ return
+ }
+ _, err = fd.Write(data)
+ return
+}
diff --git a/libgoal/lockedFileLinux.go b/libgoal/lockedFileLinux.go
new file mode 100644
index 0000000000..5330723351
--- /dev/null
+++ b/libgoal/lockedFileLinux.go
@@ -0,0 +1,71 @@
+// Copyright (C) 2019-2020 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see .
+
+// +build linux
+
+package libgoal
+
+import (
+ "io"
+ "os"
+ "syscall"
+
+ "golang.org/x/sys/unix"
+)
+
+type linuxLocker struct {
+}
+
+// makeLocker create a unix file locker.
+// note that the desired way is to use the OFD locker, which locks on the file descriptor level.
+// falling back to the non-OFD lock would allow obtaining two locks by the same process. If this becomes
+// and issue, we might want to use flock, which wouldn't work across NFS.
+func makeLocker() *linuxLocker {
+ locker := &linuxLocker{}
+ return locker
+}
+
+// the FcntlFlock has the most consistent behaviour across platforms,
+// and supports both local and network file systems.
+func (f *linuxLocker) tryRLock(fd *os.File) error {
+ flock := &syscall.Flock_t{
+ Type: syscall.F_RDLCK,
+ Whence: int16(io.SeekStart),
+ Start: 0,
+ Len: 0,
+ }
+ return syscall.FcntlFlock(fd.Fd(), unix.F_OFD_SETLKW, flock)
+}
+
+func (f *linuxLocker) tryLock(fd *os.File) error {
+ flock := &syscall.Flock_t{
+ Type: syscall.F_WRLCK,
+ Whence: int16(io.SeekStart),
+ Start: 0,
+ Len: 0,
+ }
+ return syscall.FcntlFlock(fd.Fd(), unix.F_OFD_SETLKW, flock)
+}
+
+func (f *linuxLocker) unlock(fd *os.File) error {
+ flock := &syscall.Flock_t{
+ Type: syscall.F_UNLCK,
+ Whence: int16(io.SeekStart),
+ Start: 0,
+ Len: 0,
+ }
+ return syscall.FcntlFlock(fd.Fd(), unix.F_OFD_SETLKW, flock)
+}
diff --git a/libgoal/lockedFileUnix.go b/libgoal/lockedFileUnix.go
new file mode 100644
index 0000000000..917d63209a
--- /dev/null
+++ b/libgoal/lockedFileUnix.go
@@ -0,0 +1,77 @@
+// Copyright (C) 2019-2020 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see .
+
+// +build !linux,!windows
+
+package libgoal
+
+import (
+ "io"
+ "os"
+ "syscall"
+)
+
+type unixLocker struct {
+ setLockWait int
+}
+
+// makeLocker create a unix file locker.
+// note that the desired way is to use the OFD locker, which locks on the file descriptor level.
+// falling back to the non-OFD lock would allow obtaining two locks by the same process. If this becomes
+// and issue, we might want to use flock, which wouldn't work across NFS.
+func makeLocker() *unixLocker {
+ locker := &unixLocker{}
+ getlk := syscall.Flock_t{Type: syscall.F_RDLCK}
+ if err := syscall.FcntlFlock(0, 36 /*F_OFD_GETLK*/, &getlk); err == nil {
+ // constants from /usr/include/bits/fcntl-linux.h
+ locker.setLockWait = 38 // F_OFD_SETLKW
+ } else {
+ locker.setLockWait = syscall.F_SETLKW
+ }
+ return locker
+}
+
+// the FcntlFlock has the most unixLocker behaviour across platforms,
+// and supports both local and network file systems.
+func (f *unixLocker) tryRLock(fd *os.File) error {
+ flock := &syscall.Flock_t{
+ Type: syscall.F_RDLCK,
+ Whence: int16(io.SeekStart),
+ Start: 0,
+ Len: 0,
+ }
+ return syscall.FcntlFlock(fd.Fd(), f.setLockWait, flock)
+}
+
+func (f *unixLocker) tryLock(fd *os.File) error {
+ flock := &syscall.Flock_t{
+ Type: syscall.F_WRLCK,
+ Whence: int16(io.SeekStart),
+ Start: 0,
+ Len: 0,
+ }
+ return syscall.FcntlFlock(fd.Fd(), f.setLockWait, flock)
+}
+
+func (f *unixLocker) unlock(fd *os.File) error {
+ flock := &syscall.Flock_t{
+ Type: syscall.F_UNLCK,
+ Whence: int16(io.SeekStart),
+ Start: 0,
+ Len: 0,
+ }
+ return syscall.FcntlFlock(fd.Fd(), f.setLockWait, flock)
+}
diff --git a/libgoal/participation.go b/libgoal/participation.go
index 3fd7ed2a21..53b9d20c23 100644
--- a/libgoal/participation.go
+++ b/libgoal/participation.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/system.go b/libgoal/system.go
index 6b73a1d82a..58238bfe8b 100644
--- a/libgoal/system.go
+++ b/libgoal/system.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/transactions.go b/libgoal/transactions.go
index 538a109ed6..65a838614b 100644
--- a/libgoal/transactions.go
+++ b/libgoal/transactions.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/unencryptedWallet.go b/libgoal/unencryptedWallet.go
index 2fce2396ec..d9d10a0dcc 100644
--- a/libgoal/unencryptedWallet.go
+++ b/libgoal/unencryptedWallet.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/walletHandles.go b/libgoal/walletHandles.go
index cdc1b18ee8..5a5bd5e4b1 100644
--- a/libgoal/walletHandles.go
+++ b/libgoal/walletHandles.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -18,7 +18,6 @@ package libgoal
import (
"encoding/json"
- "io/ioutil"
"os"
"path/filepath"
)
@@ -31,14 +30,21 @@ type walletHandles struct {
Handles map[string]string
}
+func readLocked(path string) ([]byte, error) {
+ lf := newLockedFile(path)
+ return lf.read()
+}
+
+func writeLocked(path string, data []byte, perm os.FileMode) error {
+ lf := newLockedFile(path)
+ return lf.write(data, perm)
+}
+
func (whs *walletHandles) loadFromDisk(cacheDir string) error {
- cachePath, err := walletHandlesCachePath(cacheDir)
- if err != nil {
- return err
- }
- _, err = os.Stat(cachePath)
+ path := walletHandlesCachePath(cacheDir)
+ _, err := os.Stat(path)
if !os.IsNotExist(err) {
- raw, err := ioutil.ReadFile(cachePath)
+ raw, err := readLocked(path)
if err != nil {
return err
}
@@ -56,20 +62,16 @@ func (whs *walletHandles) dumpToDisk(cacheDir string) error {
return err
}
- path, err := walletHandlesCachePath(cacheDir)
- if err != nil {
- return err
- }
-
- err = ioutil.WriteFile(path, raw, 0600)
+ path := walletHandlesCachePath(cacheDir)
+ err = writeLocked(path, raw, 0600)
if err != nil {
return err
}
return nil
}
-func walletHandlesCachePath(cacheDir string) (string, error) {
- return filepath.Join(cacheDir, walletHandlesJSONName), nil
+func walletHandlesCachePath(cacheDir string) string {
+ return filepath.Join(cacheDir, walletHandlesJSONName)
}
func loadWalletHandleFromDisk(walletID []byte, cacheDir string) ([]byte, error) {
diff --git a/libgoal/wallets.go b/libgoal/wallets.go
index ef21f4f8f3..008ef7cfad 100644
--- a/libgoal/wallets.go
+++ b/libgoal/wallets.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/collector.go b/logging/collector.go
index 6eb9e4bf9e..fb44346509 100644
--- a/logging/collector.go
+++ b/logging/collector.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/cyclicWriter.go b/logging/cyclicWriter.go
index ad54bead0c..fb6cf9e49a 100644
--- a/logging/cyclicWriter.go
+++ b/logging/cyclicWriter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/cyclicWriter_test.go b/logging/cyclicWriter_test.go
index 173ded9a13..c771e430f7 100644
--- a/logging/cyclicWriter_test.go
+++ b/logging/cyclicWriter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/log.go b/logging/log.go
index aa99c20dce..182e18799f 100644
--- a/logging/log.go
+++ b/logging/log.go
@@ -366,13 +366,16 @@ func NewLogger() Logger {
}
func (l logger) EnableTelemetry(cfg TelemetryConfig) (err error) {
- if l.loggerState.telemetry != nil || !cfg.Enable {
+ if l.loggerState.telemetry != nil || (!cfg.Enable && !cfg.SendToLog) {
return nil
}
return EnableTelemetry(cfg, &l)
}
func (l logger) UpdateTelemetryURI(uri string) (err error) {
+ if l.loggerState.telemetry.hook == nil {
+ return nil
+ }
err = l.loggerState.telemetry.hook.UpdateHookURI(uri)
if err == nil {
telemetryConfig.URI = uri
diff --git a/logging/logBuffer.go b/logging/logBuffer.go
index 02902b4336..5a76ea680e 100644
--- a/logging/logBuffer.go
+++ b/logging/logBuffer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/logBuffer_test.go b/logging/logBuffer_test.go
index 53b41c882c..598d4ffae2 100644
--- a/logging/logBuffer_test.go
+++ b/logging/logBuffer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/log_test.go b/logging/log_test.go
index c15613c867..c03aa7d1e2 100644
--- a/logging/log_test.go
+++ b/logging/log_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/logspec/agreement.go b/logging/logspec/agreement.go
index 911425ab8d..cf590a3e61 100644
--- a/logging/logspec/agreement.go
+++ b/logging/logspec/agreement.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/logspec/ledger.go b/logging/logspec/ledger.go
index 3f49897c18..2059ad69fc 100644
--- a/logging/logspec/ledger.go
+++ b/logging/logspec/ledger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/logspec/root.go b/logging/logspec/root.go
index d1a025a4e5..88b2593aeb 100644
--- a/logging/logspec/root.go
+++ b/logging/logspec/root.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetry.go b/logging/telemetry.go
index 9509ca812b..d195f9d39b 100644
--- a/logging/telemetry.go
+++ b/logging/telemetry.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -48,7 +48,9 @@ func EnableTelemetry(cfg TelemetryConfig, l *logger) (err error) {
func enableTelemetryState(telemetry *telemetryState, l *logger) {
l.loggerState.telemetry = telemetry
// Hook our normal logging to send desired types to telemetry
- l.AddHook(telemetry.hook)
+ if telemetry.hook != nil {
+ l.AddHook(telemetry.hook)
+ }
// Wrap current logger Output writer to capture history
l.setOutput(telemetry.wrapOutput(l.getOutput()))
}
@@ -71,19 +73,19 @@ func makeLevels(min logrus.Level) []logrus.Level {
}
func makeTelemetryState(cfg TelemetryConfig, hookFactory hookFactory) (*telemetryState, error) {
- history := createLogBuffer(logBufferDepth)
- if cfg.SessionGUID == "" {
- cfg.SessionGUID = uuid.NewV4().String()
- }
- hook, err := createTelemetryHook(cfg, history, hookFactory)
- if err != nil {
- return nil, err
- }
-
- telemetry := &telemetryState{
- history,
- createAsyncHookLevels(hook, 32, 100, makeLevels(cfg.MinLogLevel)),
+ telemetry := &telemetryState{}
+ telemetry.history = createLogBuffer(logBufferDepth)
+ if cfg.Enable {
+ if cfg.SessionGUID == "" {
+ cfg.SessionGUID = uuid.NewV4().String()
+ }
+ hook, err := createTelemetryHook(cfg, telemetry.history, hookFactory)
+ if err != nil {
+ return nil, err
+ }
+ telemetry.hook = createAsyncHookLevels(hook, 32, 100, makeLevels(cfg.MinLogLevel))
}
+ telemetry.sendToLog = cfg.SendToLog
return telemetry, nil
}
@@ -222,7 +224,12 @@ func (t *telemetryState) logTelemetry(l logger, message string, details interfac
entry.Level = logrus.InfoLevel
entry.Message = message
- t.hook.Fire(entry)
+ if t.sendToLog {
+ entry.Info(message)
+ }
+ if t.hook != nil {
+ t.hook.Fire(entry)
+ }
}
func (t *telemetryState) Close() {
diff --git a/logging/telemetryCommon.go b/logging/telemetryCommon.go
index 3a2025fd30..1e8762c172 100644
--- a/logging/telemetryCommon.go
+++ b/logging/telemetryCommon.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -36,13 +36,15 @@ type TelemetryOperation struct {
}
type telemetryState struct {
- history *logBuffer
- hook *asyncTelemetryHook
+ history *logBuffer
+ hook *asyncTelemetryHook
+ sendToLog bool
}
// TelemetryConfig represents the configuration of Telemetry logging
type TelemetryConfig struct {
Enable bool
+ SendToLog bool
URI string
Name string
GUID string
diff --git a/logging/telemetryConfig.go b/logging/telemetryConfig.go
index fad202b241..439d05dcf4 100644
--- a/logging/telemetryConfig.go
+++ b/logging/telemetryConfig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryConfig_test.go b/logging/telemetryConfig_test.go
index 5c4583dc3f..d19a3cd719 100644
--- a/logging/telemetryConfig_test.go
+++ b/logging/telemetryConfig_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryFilteredHook.go b/logging/telemetryFilteredHook.go
index 33bbe82eda..11fa0286a9 100644
--- a/logging/telemetryFilteredHook.go
+++ b/logging/telemetryFilteredHook.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryOperation.go b/logging/telemetryOperation.go
index 57689f59e9..1cbd21b071 100644
--- a/logging/telemetryOperation.go
+++ b/logging/telemetryOperation.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetry_test.go b/logging/telemetry_test.go
index 7e1532287c..1a806fffb0 100644
--- a/logging/telemetry_test.go
+++ b/logging/telemetry_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryhook.go b/logging/telemetryhook.go
index d3a9e5855e..801ac75d54 100644
--- a/logging/telemetryhook.go
+++ b/logging/telemetryhook.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryhook_test.go b/logging/telemetryhook_test.go
index c4b999ad30..57f8848f0f 100644
--- a/logging/telemetryhook_test.go
+++ b/logging/telemetryhook_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryspec/category.go b/logging/telemetryspec/category.go
index aaf4e049ad..e93efbb5c0 100644
--- a/logging/telemetryspec/category.go
+++ b/logging/telemetryspec/category.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryspec/event.go b/logging/telemetryspec/event.go
index 206023cffa..c809b5704c 100644
--- a/logging/telemetryspec/event.go
+++ b/logging/telemetryspec/event.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryspec/eventTiming.go b/logging/telemetryspec/eventTiming.go
index 4a887f1e20..470e13d8c3 100644
--- a/logging/telemetryspec/eventTiming.go
+++ b/logging/telemetryspec/eventTiming.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryspec/metric.go b/logging/telemetryspec/metric.go
index a2dda53912..4828a2a6e7 100644
--- a/logging/telemetryspec/metric.go
+++ b/logging/telemetryspec/metric.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryspec/operation.go b/logging/telemetryspec/operation.go
index 148d27668f..0def2d9371 100644
--- a/logging/telemetryspec/operation.go
+++ b/logging/telemetryspec/operation.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/testingLogger.go b/logging/testingLogger.go
index 41542c3405..d17268691b 100644
--- a/logging/testingLogger.go
+++ b/logging/testingLogger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/usage.go b/logging/usage.go
index 1b156d6f0e..ec9e1fdd91 100644
--- a/logging/usage.go
+++ b/logging/usage.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/network.go b/netdeploy/network.go
index 2876bb4186..06eead476f 100644
--- a/netdeploy/network.go
+++ b/netdeploy/network.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -48,59 +48,19 @@ type NetworkCfg struct {
// Network represents an instance of a deployed network
type Network struct {
- rootDir string
- cfg NetworkCfg
- nodeDirs map[string]string // mapping between the node name and the directories where the node is operation on (not including RelayDirs)
- gen gen.GenesisData
-}
-
-// Name returns the name of the private network
-func (n Network) Name() string {
- return n.cfg.Name
-}
-
-// PrimaryDataDir returns the primary data directory for the network
-func (n Network) PrimaryDataDir() string {
- return n.getNodeFullPath(n.cfg.RelayDirs[0])
-}
-
-// NodeDataDirs returns an array of node data directories (not the relays)
-func (n Network) NodeDataDirs() []string {
- var directories []string
- for _, nodeDir := range n.nodeDirs {
- directories = append(directories, n.getNodeFullPath(nodeDir))
- }
- return directories
-}
-
-// GetNodeDir returns the node directory that is associated with the given node name.
-func (n Network) GetNodeDir(nodeName string) (string, error) {
- possibleDir := n.getNodeFullPath(nodeName)
- if isNodeDir(possibleDir) {
- return possibleDir, nil
- }
- return "", fmt.Errorf("no node exists that is named '%s'", nodeName)
-}
-
-func isNodeDir(path string) bool {
- if util.IsDir(path) {
- if util.FileExists(filepath.Join(path, config.GenesisJSONFile)) {
- return true
- }
- }
- return false
-}
-
-// Genesis returns the genesis data for this network
-func (n Network) Genesis() gen.GenesisData {
- return n.gen
+ rootDir string
+ cfg NetworkCfg
+ nodeDirs map[string]string // mapping between the node name and the directories where the node is operation on (not including RelayDirs)
+ gen gen.GenesisData
+ nodeExitCallback nodecontrol.AlgodExitErrorCallback
}
// CreateNetworkFromTemplate uses the specified template to deploy a new private network
// under the specified root directory.
-func CreateNetworkFromTemplate(name, rootDir, templateFile, binDir string, importKeys bool) (Network, error) {
+func CreateNetworkFromTemplate(name, rootDir, templateFile, binDir string, importKeys bool, nodeExitCallback nodecontrol.AlgodExitErrorCallback) (Network, error) {
n := Network{
- rootDir: rootDir,
+ rootDir: rootDir,
+ nodeExitCallback: nodeExitCallback,
}
n.cfg.Name = name
n.cfg.TemplateFile = templateFile
@@ -133,21 +93,6 @@ func CreateNetworkFromTemplate(name, rootDir, templateFile, binDir string, impor
return n, err
}
-func isValidNetworkDir(rootDir string) bool {
- cfgFile := filepath.Join(rootDir, configFileName)
- fileExists := util.FileExists(cfgFile)
-
- // If file exists, network assumed to exist
- if !fileExists {
- return false
- }
-
- // Now check for genesis.json file too
- cfgFile = filepath.Join(rootDir, genesisFileName)
- fileExists = util.FileExists(cfgFile)
- return fileExists
-}
-
// LoadNetwork loads and initializes the Network state representing
// an existing deployed network.
func LoadNetwork(rootDir string) (Network, error) {
@@ -183,6 +128,63 @@ func loadNetworkCfg(configFile string) (NetworkCfg, error) {
return cfg, err
}
+// Name returns the name of the private network
+func (n Network) Name() string {
+ return n.cfg.Name
+}
+
+// PrimaryDataDir returns the primary data directory for the network
+func (n Network) PrimaryDataDir() string {
+ return n.getNodeFullPath(n.cfg.RelayDirs[0])
+}
+
+// NodeDataDirs returns an array of node data directories (not the relays)
+func (n Network) NodeDataDirs() []string {
+ var directories []string
+ for _, nodeDir := range n.nodeDirs {
+ directories = append(directories, n.getNodeFullPath(nodeDir))
+ }
+ return directories
+}
+
+// GetNodeDir returns the node directory that is associated with the given node name.
+func (n Network) GetNodeDir(nodeName string) (string, error) {
+ possibleDir := n.getNodeFullPath(nodeName)
+ if isNodeDir(possibleDir) {
+ return possibleDir, nil
+ }
+ return "", fmt.Errorf("no node exists that is named '%s'", nodeName)
+}
+
+func isNodeDir(path string) bool {
+ if util.IsDir(path) {
+ if util.FileExists(filepath.Join(path, config.GenesisJSONFile)) {
+ return true
+ }
+ }
+ return false
+}
+
+// Genesis returns the genesis data for this network
+func (n Network) Genesis() gen.GenesisData {
+ return n.gen
+}
+
+func isValidNetworkDir(rootDir string) bool {
+ cfgFile := filepath.Join(rootDir, configFileName)
+ fileExists := util.FileExists(cfgFile)
+
+ // If file exists, network assumed to exist
+ if !fileExists {
+ return false
+ }
+
+ // Now check for genesis.json file too
+ cfgFile = filepath.Join(rootDir, genesisFileName)
+ fileExists = util.FileExists(cfgFile)
+ return fileExists
+}
+
// Save persists the network state in the root directory (in network.json)
func (n Network) Save(rootDir string) error {
cfgFile := filepath.Join(rootDir, configFileName)
@@ -248,11 +250,15 @@ func (n Network) Start(binDir string, redirectOutput bool) error {
// Start Prime Relay and get its listening address
var peerAddressListBuilder strings.Builder
-
+ var relayAddress string
+ var err error
for _, relayDir := range n.cfg.RelayDirs {
- nc := nodecontrol.MakeNodeController(binDir, n.getNodeFullPath(relayDir))
+ nodeFulllPath := n.getNodeFullPath(relayDir)
+ nc := nodecontrol.MakeNodeController(binDir, nodeFulllPath)
args := nodecontrol.AlgodStartArgs{
- RedirectOutput: redirectOutput,
+ RedirectOutput: redirectOutput,
+ ExitErrorCallback: n.nodeExitCallback,
+ PeerAddress: relayAddress, // on the first iteration it would be empty, which is ok. subsequent iterations would link all the relays.
}
_, err := nc.StartAlgod(args)
@@ -260,7 +266,7 @@ func (n Network) Start(binDir string, redirectOutput bool) error {
return err
}
- relayAddress, err := n.getRelayAddress(nc)
+ relayAddress, err = n.getRelayAddress(nc)
if err != nil {
return err
}
@@ -272,7 +278,7 @@ func (n Network) Start(binDir string, redirectOutput bool) error {
}
peerAddressList := peerAddressListBuilder.String()
- err := n.startNodes(binDir, peerAddressList, redirectOutput)
+ err = n.startNodes(binDir, peerAddressList, redirectOutput)
return err
}
@@ -308,8 +314,9 @@ func (n Network) GetPeerAddresses(binDir string) []string {
func (n Network) startNodes(binDir, relayAddress string, redirectOutput bool) error {
args := nodecontrol.AlgodStartArgs{
- PeerAddress: relayAddress,
- RedirectOutput: redirectOutput,
+ PeerAddress: relayAddress,
+ RedirectOutput: redirectOutput,
+ ExitErrorCallback: n.nodeExitCallback,
}
for _, nodeDir := range n.nodeDirs {
nc := nodecontrol.MakeNodeController(binDir, n.getNodeFullPath(nodeDir))
@@ -339,19 +346,25 @@ func (n Network) StartNode(binDir, nodeDir string, redirectOutput bool) (err err
// No return code - we try to kill them if we can (if we read valid PID file)
func (n Network) Stop(binDir string) {
c := make(chan struct{}, len(n.cfg.RelayDirs)+len(n.nodeDirs))
- stopNodeContoller := func(nc nodecontrol.NodeController) {
+ stopNodeContoller := func(nc *nodecontrol.NodeController) {
defer func() {
c <- struct{}{}
}()
nc.FullStop()
}
for _, relayDir := range n.cfg.RelayDirs {
- nc := nodecontrol.MakeNodeController(binDir, n.getNodeFullPath(relayDir))
- go stopNodeContoller(nc)
+ relayDataDir := n.getNodeFullPath(relayDir)
+ nc := nodecontrol.MakeNodeController(binDir, relayDataDir)
+ algodKmdPath, _ := filepath.Abs(filepath.Join(relayDataDir, libgoal.DefaultKMDDataDir))
+ nc.SetKMDDataDir(algodKmdPath)
+ go stopNodeContoller(&nc)
}
for _, nodeDir := range n.nodeDirs {
- nc := nodecontrol.MakeNodeController(binDir, n.getNodeFullPath(nodeDir))
- go stopNodeContoller(nc)
+ nodeDataDir := n.getNodeFullPath(nodeDir)
+ nc := nodecontrol.MakeNodeController(binDir, nodeDataDir)
+ algodKmdPath, _ := filepath.Abs(filepath.Join(nodeDataDir, libgoal.DefaultKMDDataDir))
+ nc.SetKMDDataDir(algodKmdPath)
+ go stopNodeContoller(&nc)
}
// wait until we finish stopping all the node controllers.
for i := cap(c); i > 0; i-- {
diff --git a/netdeploy/networkTemplate.go b/netdeploy/networkTemplate.go
index 33227751e0..8462bdd70f 100644
--- a/netdeploy/networkTemplate.go
+++ b/netdeploy/networkTemplate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -221,7 +221,7 @@ func (t NetworkTemplate) Validate() error {
func (node nodeConfig) createConfigFile(configFile string, numNodes int) error {
// Override default :8080 REST endpoint, and disable SRV lookup
configString := `{ "GossipFanout": ` + fmt.Sprintf("%d", numNodes) +
- `, "EndpointAddress": "127.0.0.1:0", "DNSBootstrapID": ""`
+ `, "EndpointAddress": "127.0.0.1:0", "DNSBootstrapID": "", "EnableProfiler": true`
if node.IsRelay {
// Have relays listen on any localhost port
configString += `, "NetAddress": "127.0.0.1:0"`
diff --git a/netdeploy/networkTemplates_test.go b/netdeploy/networkTemplates_test.go
index 2c89e682ac..042b244359 100644
--- a/netdeploy/networkTemplates_test.go
+++ b/netdeploy/networkTemplates_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/network_test.go b/netdeploy/network_test.go
index 1c97e18e99..53a498b488 100644
--- a/netdeploy/network_test.go
+++ b/netdeploy/network_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/buildConfig.go b/netdeploy/remote/buildConfig.go
index 323486fa6d..c62fa0580e 100644
--- a/netdeploy/remote/buildConfig.go
+++ b/netdeploy/remote/buildConfig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/deployedNetwork.go b/netdeploy/remote/deployedNetwork.go
index 854569bf27..f29391de5c 100644
--- a/netdeploy/remote/deployedNetwork.go
+++ b/netdeploy/remote/deployedNetwork.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/hostConfig.go b/netdeploy/remote/hostConfig.go
index 2fd9051489..c620a91d36 100644
--- a/netdeploy/remote/hostConfig.go
+++ b/netdeploy/remote/hostConfig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/hostTemplate.go b/netdeploy/remote/hostTemplate.go
index bbee6b8769..ad7e4f2f0d 100644
--- a/netdeploy/remote/hostTemplate.go
+++ b/netdeploy/remote/hostTemplate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/nodeConfig.go b/netdeploy/remote/nodeConfig.go
index 6a13dbf9ce..5d70f367bb 100644
--- a/netdeploy/remote/nodeConfig.go
+++ b/netdeploy/remote/nodeConfig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/nodeWalletData.go b/netdeploy/remote/nodeWalletData.go
index 76f849e2f3..d211cfbb8d 100644
--- a/netdeploy/remote/nodeWalletData.go
+++ b/netdeploy/remote/nodeWalletData.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/nodecfg/nodeConfigurator.go b/netdeploy/remote/nodecfg/nodeConfigurator.go
index 144fddd012..30a88f1b56 100644
--- a/netdeploy/remote/nodecfg/nodeConfigurator.go
+++ b/netdeploy/remote/nodecfg/nodeConfigurator.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/nodecfg/nodeDir.go b/netdeploy/remote/nodecfg/nodeDir.go
index 7b4965e4eb..73ef46c884 100644
--- a/netdeploy/remote/nodecfg/nodeDir.go
+++ b/netdeploy/remote/nodecfg/nodeDir.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/topology.go b/netdeploy/remote/topology.go
index b2cc24730c..b5b9eb34e6 100644
--- a/netdeploy/remote/topology.go
+++ b/netdeploy/remote/topology.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/limited_reader_slurper.go b/network/limited_reader_slurper.go
index 56c370a3a1..216a7bbaca 100644
--- a/network/limited_reader_slurper.go
+++ b/network/limited_reader_slurper.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/messageFilter.go b/network/messageFilter.go
index dd956c8fc4..164498b392 100644
--- a/network/messageFilter.go
+++ b/network/messageFilter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/multiplexer.go b/network/multiplexer.go
index ca4b85c450..4533d2fdee 100644
--- a/network/multiplexer.go
+++ b/network/multiplexer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/multiplexer_test.go b/network/multiplexer_test.go
index 9f741bf011..ae1c50f56f 100644
--- a/network/multiplexer_test.go
+++ b/network/multiplexer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/netprio.go b/network/netprio.go
index 34e0a9e208..37295f589f 100644
--- a/network/netprio.go
+++ b/network/netprio.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/netprio_test.go b/network/netprio_test.go
index dc307629b4..7f6cc457f7 100644
--- a/network/netprio_test.go
+++ b/network/netprio_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/peersheap.go b/network/peersheap.go
index 2f5d08a4f4..94dd378174 100644
--- a/network/peersheap.go
+++ b/network/peersheap.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/phonebook.go b/network/phonebook.go
index 435cc6f3c9..aabe08eb57 100644
--- a/network/phonebook.go
+++ b/network/phonebook.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/phonebook_test.go b/network/phonebook_test.go
index 73cb93ebe3..196d41caca 100644
--- a/network/phonebook_test.go
+++ b/network/phonebook_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/ping.go b/network/ping.go
index 84d00f4837..0988f61d00 100644
--- a/network/ping.go
+++ b/network/ping.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/ping_test.go b/network/ping_test.go
index 6a0386804f..870c056c5b 100644
--- a/network/ping_test.go
+++ b/network/ping_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/requestLogger.go b/network/requestLogger.go
index aabd4debfc..38fe9f6e6e 100644
--- a/network/requestLogger.go
+++ b/network/requestLogger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/requestLogger_test.go b/network/requestLogger_test.go
index 912a940534..0e0b19088c 100644
--- a/network/requestLogger_test.go
+++ b/network/requestLogger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/requestTracker.go b/network/requestTracker.go
index 2a4aca89b5..5fae77ce7e 100644
--- a/network/requestTracker.go
+++ b/network/requestTracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/requestTracker_test.go b/network/requestTracker_test.go
index 5611a23191..e1f9d51489 100644
--- a/network/requestTracker_test.go
+++ b/network/requestTracker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/wsNetwork.go b/network/wsNetwork.go
index d74084933e..a369b9332f 100644
--- a/network/wsNetwork.go
+++ b/network/wsNetwork.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/wsNetwork_test.go b/network/wsNetwork_test.go
index 4322c67ead..b4d6780f57 100644
--- a/network/wsNetwork_test.go
+++ b/network/wsNetwork_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -54,9 +54,11 @@ func TestMain(m *testing.M) {
}
func debugMetrics(t *testing.T) {
- var buf strings.Builder
- metrics.DefaultRegistry().WriteMetrics(&buf, "")
- t.Log(buf.String())
+ if t.Failed() {
+ var buf strings.Builder
+ metrics.DefaultRegistry().WriteMetrics(&buf, "")
+ t.Log(buf.String())
+ }
}
type emptyPhonebook struct{}
@@ -472,17 +474,24 @@ func TestSlowHandlers(t *testing.T) {
ipi++
}
ok := false
- for i := 0; i < 10; i++ {
- time.Sleep(time.Millisecond)
+ lastnw := -1
+ totalWait := 0
+ for i := 0; i < 7; i++ {
+ waitTime := int(1 << uint64(i))
+ time.Sleep(time.Duration(waitTime) * time.Millisecond)
+ totalWait += waitTime
nw := slowCounter.numWaiters()
if nw == incomingThreads {
ok = true
break
}
- t.Logf("%dms %d waiting", i+1, nw)
+ if lastnw != nw {
+ t.Logf("%dms %d waiting", totalWait, nw)
+ lastnw = nw
+ }
}
if !ok {
- t.Errorf("timeout waiting for %d threads to block on slow handler, have %d", incomingThreads, slowCounter.numWaiters())
+ t.Errorf("timeout waiting for %d threads to block on slow handler, have %d", incomingThreads, lastnw)
}
require.Equal(t, 0, fastCounter.Count())
diff --git a/network/wsPeer.go b/network/wsPeer.go
index e6c912b43c..379f02198e 100644
--- a/network/wsPeer.go
+++ b/network/wsPeer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/wsPeer_test.go b/network/wsPeer_test.go
index 7084b0aa44..8524412a7e 100644
--- a/network/wsPeer_test.go
+++ b/network/wsPeer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/impls.go b/node/impls.go
index 44d6d3812b..92176bf68c 100644
--- a/node/impls.go
+++ b/node/impls.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -22,6 +22,7 @@ import (
"time"
"github.com/algorand/go-algorand/agreement"
+ "github.com/algorand/go-algorand/catchup"
"github.com/algorand/go-algorand/data"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
@@ -30,16 +31,11 @@ import (
"github.com/algorand/go-algorand/ledger"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/logging/telemetryspec"
- "github.com/algorand/go-algorand/network"
- "github.com/algorand/go-algorand/protocol"
- "github.com/algorand/go-algorand/rpcs"
"github.com/algorand/go-algorand/util/execpool"
)
// TODO these implementations should be pushed down into the corresponding structs or alternatively turned into new structs in the correct subpackages
-const blockQueryPeerLimit = 10
-
type blockAuthenticatorImpl struct {
*data.Ledger
*agreement.AsyncVoteVerifier
@@ -145,9 +141,14 @@ func (vb validatedBlock) Block() bookkeeping.Block {
// agreementLedger implements the agreement.Ledger interface.
type agreementLedger struct {
*data.Ledger
+ UnmatchedPendingCertificates chan catchup.PendingUnmatchedCertificate
+}
- ff rpcs.FetcherFactory
- n network.GossipNode
+func makeAgreementLedger(ledger *data.Ledger) agreementLedger {
+ return agreementLedger{
+ Ledger: ledger,
+ UnmatchedPendingCertificates: make(chan catchup.PendingUnmatchedCertificate, 1),
+ }
}
// EnsureBlock implements agreement.LedgerWriter.EnsureBlock.
@@ -161,108 +162,44 @@ func (l agreementLedger) EnsureValidatedBlock(ve agreement.ValidatedBlock, c agr
}
// EnsureDigest implements agreement.LedgerWriter.EnsureDigest.
-// TODO: Get rid of EnsureDigest -- instead the ledger should expose what blocks it's waiting on, and a separate service should fetch them and call EnsureBlock
-// should "retry until cert matches" logic live here or in the abstract fetcher?
func (l agreementLedger) EnsureDigest(cert agreement.Certificate, quit chan struct{}, verifier *agreement.AsyncVoteVerifier) {
- round := cert.Round
- blockHash := bookkeeping.BlockHash(cert.Proposal.BlockDigest) // semantic digest (i.e., hash of the block header), not byte-for-byte digest
- logging.Base().Debug("consensus was reached on a block we don't have yet: ", blockHash)
- for {
- // Ask the fetcher to get the block somehow
- block, fetchedCert, err := l.FetchBlockByDigest(round, quit)
- if err != nil {
- select {
- case <-quit:
- logging.Base().Debugf("EnsureDigest was asked to quit before we could acquire the block")
- return
- default:
- }
- logging.Base().Panicf("EnsureDigest could not acquire block, fetcher errored out: %v", err)
- }
-
- if block.Hash() == blockHash && block.ContentsMatchHeader() {
- l.EnsureBlock(block, cert)
- return
- }
- // Otherwise, fetcher gave us the wrong block
- logging.Base().Warnf("fetcher gave us bad/wrong block (for round %d): fetched hash %v; want hash %v", round, block.Hash(), blockHash)
-
- // As a failsafe, if the cert we fetched is valid but for the wrong block, panic as loudly as possible
- if cert.Round == fetchedCert.Round &&
- cert.Proposal.BlockDigest != fetchedCert.Proposal.BlockDigest &&
- fetchedCert.Authenticate(block, l, verifier) == nil {
- s := "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
- s += "!!!!!!!!!! FORK DETECTED !!!!!!!!!!!\n"
- s += "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
- s += "EnsureDigest called with a cert authenticating block with hash %v.\n"
- s += "We fetched a valid cert authenticating a different block, %v. This indicates a fork.\n\n"
- s += "Cert from our agreement service:\n%#v\n\n"
- s += "Cert from the fetcher:\n%#v\n\n"
- s += "Block from the fetcher:\n%#v\n\n"
- s += "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
- s += "!!!!!!!!!! FORK DETECTED !!!!!!!!!!!\n"
- s += "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
- s = fmt.Sprintf(s, cert.Proposal.BlockDigest, fetchedCert.Proposal.BlockDigest, cert, fetchedCert, block)
- fmt.Println(s)
- logging.Base().Error(s)
- }
+ certRoundReachedCh := l.Wait(cert.Round)
+ // clear out the pending certificates ( if any )
+ select {
+ case pendingCert := <-l.UnmatchedPendingCertificates:
+ logging.Base().Debugf("agreementLedger.EnsureDigest has flushed out pending request for certificate for round %d in favor of recent certificate for round %d", pendingCert.Cert.Round, cert.Round)
+ default:
}
-}
-func (l agreementLedger) innerFetch(fetcher rpcs.Fetcher, round basics.Round, quit chan struct{}) (*bookkeeping.Block, *agreement.Certificate, error) {
- ctx, cancel := context.WithTimeout(context.Background(), rpcs.DefaultFetchTimeout)
- defer cancel()
- type fbreturn struct {
- block *bookkeeping.Block
- cert *agreement.Certificate
- err error
- }
- localdone := make(chan fbreturn, 1)
- go func() {
- block, cert, _, err := fetcher.FetchBlock(ctx, round)
- localdone <- fbreturn{block, cert, err}
- }()
+ // if the quit channel is closed, we want to exit here before placing the request on the UnmatchedPendingCertificates
+ // channel.
select {
- case ret := <-localdone:
- return ret.block, ret.cert, ret.err
case <-quit:
- return nil, nil, nil
- case <-l.Wait(round):
- return nil, nil, nil
+ logging.Base().Debugf("EnsureDigest was asked to quit before we enqueue the certificate request")
+ return
+ default:
}
-}
-// FetchBlockByDigest is a helper for EnsureDigest.
-// TODO This is a kludge. Instead we should have a service that sees what the ledger is waiting on, fetches it, and calls EnsureBlock on it.
-// TODO this doesn't actually use the digest from cert!
-func (l agreementLedger) FetchBlockByDigest(round basics.Round, quit chan struct{}) (bookkeeping.Block, agreement.Certificate, error) {
- fetcher := l.ff.NewOverGossip(protocol.UniEnsBlockReqTag)
+ // The channel send to UnmatchedPendingCertificates is guaranteed to be non-blocking since due to the fact that -
+ // 1. the channel capacity is 1
+ // 2. we just cleared a single item off this channel ( if there was any )
+ // 3. the EnsureDigest method is being called with the agreeement service guarantee
+ // 4. no other senders to this channel exists
+ // we want to have this as a select statement to check if we neeed to exit before enqueueing the task to the catchup service.
+ l.UnmatchedPendingCertificates <- catchup.PendingUnmatchedCertificate{Cert: cert, VoteVerifier: verifier}
+
defer func() {
- fetcher.Close()
- }()
- for {
- if fetcher.OutOfPeers(round) {
- fetcher.Close()
- // refresh peers and try again
- logging.Base().Warn("fetchBlockByDigest found no outgoing peers")
- l.n.RequestConnectOutgoing(true, quit)
- fetcher = l.ff.NewOverGossip(protocol.UniEnsBlockReqTag)
- }
- block, cert, err := l.innerFetch(fetcher, round, quit)
- if err == nil {
- if block == nil || cert == nil {
- // nil error, nil block = async write
- logging.Base().Debugf("async write of block from round %v to ledger (or quit)", round)
- return l.BlockCert(round) // err is nil because ledger.Wait returned
- }
- return *block, *cert, nil
- }
+ // clear out the content of the UnmatchedPendingCertificates channel if we somehow managed to get this round aquired by a different method ( i.e. regular catchup )
select {
- case <-quit:
- return bookkeeping.Block{}, agreement.Certificate{}, fmt.Errorf("asked to abort")
+ case <-l.UnmatchedPendingCertificates:
default:
- logging.Base().Debugf("error fetching block (%v), trying again", err)
- // todo: consider rate-limiting here if a node is completely offline.
}
+ }()
+
+ select {
+ case <-quit:
+ logging.Base().Debugf("EnsureDigest was asked to quit before we could acquire the block")
+ case <-certRoundReachedCh:
+ // great! we've reached the desired round.
}
}
diff --git a/node/indexer/db.go b/node/indexer/db.go
index d308aa00e1..5cea65cbb8 100644
--- a/node/indexer/db.go
+++ b/node/indexer/db.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/indexer/indexer.go b/node/indexer/indexer.go
index 38b39736b9..4f4f74dab2 100644
--- a/node/indexer/indexer.go
+++ b/node/indexer/indexer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/indexer/indexer_test.go b/node/indexer/indexer_test.go
index 571a1edb98..c640be5fab 100644
--- a/node/indexer/indexer_test.go
+++ b/node/indexer/indexer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/netprio.go b/node/netprio.go
index 236c631f3e..dc6a4466da 100644
--- a/node/netprio.go
+++ b/node/netprio.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/node.go b/node/node.go
index ae021c9cf1..8b7bbd2a20 100644
--- a/node/node.go
+++ b/node/node.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -54,15 +54,16 @@ const participationKeyCheckSecs = 60
// StatusReport represents the current basic status of the node
type StatusReport struct {
- LastRound basics.Round
- LastVersion protocol.ConsensusVersion
- NextVersion protocol.ConsensusVersion
- NextVersionRound basics.Round
- NextVersionSupported bool
- LastRoundTimestamp time.Time
- SynchronizingTime time.Duration
- CatchupTime time.Duration
- HasSyncedSinceStartup bool
+ LastRound basics.Round
+ LastVersion protocol.ConsensusVersion
+ NextVersion protocol.ConsensusVersion
+ NextVersionRound basics.Round
+ NextVersionSupported bool
+ LastRoundTimestamp time.Time
+ SynchronizingTime time.Duration
+ CatchupTime time.Duration
+ HasSyncedSinceStartup bool
+ StoppedAtUnsupportedRound bool
}
// TimeSinceLastRound returns the time since the last block was approved (locally), or 0 if no blocks seen
@@ -229,14 +230,14 @@ func MakeFull(log logging.Logger, rootDir string, cfg config.Local, phonebookDir
blockFactory := makeBlockFactory(node.ledger, node.transactionPool, node.config.EnableProcessBlockStats, node.highPriorityCryptoVerificationPool)
blockValidator := blockValidatorImpl{l: node.ledger, tp: node.transactionPool, verificationPool: node.highPriorityCryptoVerificationPool}
- agreementLedger := agreementLedger{Ledger: node.ledger, ff: rpcs.MakeNetworkFetcherFactory(node.net, blockQueryPeerLimit, node.wsFetcherService), n: node.net}
+ agreementLedger := makeAgreementLedger(node.ledger)
agreementParameters := agreement.Parameters{
Logger: log,
Accessor: crashAccess,
Clock: timers.MakeMonotonicClock(time.Now()),
Local: node.config,
- Network: gossip.WrapNetwork(node.net),
+ Network: gossip.WrapNetwork(node.net, log),
Ledger: agreementLedger,
BlockFactory: blockFactory,
BlockValidator: blockValidator,
@@ -246,7 +247,7 @@ func MakeFull(log logging.Logger, rootDir string, cfg config.Local, phonebookDir
}
node.algorandService = agreement.MakeService(agreementParameters)
- node.syncer = catchup.MakeService(node.log, node.config, p2pNode, node.ledger, node.wsFetcherService, blockAuthenticatorImpl{Ledger: node.ledger, AsyncVoteVerifier: agreement.MakeAsyncVoteVerifier(node.lowPriorityCryptoVerificationPool)})
+ node.syncer = catchup.MakeService(node.log, node.config, p2pNode, node.ledger, node.wsFetcherService, blockAuthenticatorImpl{Ledger: node.ledger, AsyncVoteVerifier: agreement.MakeAsyncVoteVerifier(node.lowPriorityCryptoVerificationPool)}, agreementLedger.UnmatchedPendingCertificates)
node.txPoolSyncer = rpcs.MakeTxSyncer(node.transactionPool, node.net, node.txHandler.SolicitedTxHandler(), time.Duration(cfg.TxSyncIntervalSeconds)*time.Second, time.Duration(cfg.TxSyncTimeoutSeconds)*time.Second, cfg.TxSyncServeResponseSize)
err = node.loadParticipationKeys()
@@ -554,6 +555,8 @@ func (node *AlgorandFullNode) Status() (s StatusReport, err error) {
s.LastRoundTimestamp = node.lastRoundTimestamp
s.CatchupTime = node.syncer.SynchronizingTime()
s.HasSyncedSinceStartup = node.hasSyncedSinceStartup
+ s.StoppedAtUnsupportedRound = s.LastRound+1 == s.NextVersionRound && !s.NextVersionSupported
+
return
}
diff --git a/node/nodeContext.go b/node/nodeContext.go
index 587a081730..7d73a86bb2 100644
--- a/node/nodeContext.go
+++ b/node/nodeContext.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/node_test.go b/node/node_test.go
index d702d9d0a7..d4ede125a4 100644
--- a/node/node_test.go
+++ b/node/node_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/poolStats.go b/node/poolStats.go
index 00b134b751..dcde4eaefd 100644
--- a/node/poolStats.go
+++ b/node/poolStats.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/topAccountListener.go b/node/topAccountListener.go
index 2e86732e6d..8e5de8f8a2 100644
--- a/node/topAccountListener.go
+++ b/node/topAccountListener.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/topAccountListener_test.go b/node/topAccountListener_test.go
index 3d3c9e0a13..2e56218c4e 100644
--- a/node/topAccountListener_test.go
+++ b/node/topAccountListener_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/nodecontrol/LaggedStdIo.go b/nodecontrol/LaggedStdIo.go
index 4f917a1034..b0b16e9e14 100644
--- a/nodecontrol/LaggedStdIo.go
+++ b/nodecontrol/LaggedStdIo.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/nodecontrol/NodeController.go b/nodecontrol/NodeController.go
index 10ebfce4d5..8467bf5ff6 100644
--- a/nodecontrol/NodeController.go
+++ b/nodecontrol/NodeController.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -50,6 +50,10 @@ func MakeNodeController(binDir, algodDataDir string) NodeController {
return nc
}
+// AlgodExitErrorCallback is the callback function from the node controller that reports upstream
+// in case there was a change with the algod running state.
+type AlgodExitErrorCallback func(*NodeController, error)
+
// AlgodStartArgs are the possible arguments for starting algod
type AlgodStartArgs struct {
PeerAddress string
@@ -57,6 +61,7 @@ type AlgodStartArgs struct {
RedirectOutput bool
RunUnderHost bool
TelemetryOverride string
+ ExitErrorCallback AlgodExitErrorCallback
}
// KMDStartArgs are the possible arguments for starting kmd
diff --git a/nodecontrol/algodControl.go b/nodecontrol/algodControl.go
index c0236dc5ac..7563b95c92 100644
--- a/nodecontrol/algodControl.go
+++ b/nodecontrol/algodControl.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -184,18 +184,28 @@ func (nc *NodeController) StartAlgod(args AlgodStartArgs) (alreadyRunning bool,
}
// Wait on the algod process and check if exits
- c := make(chan bool)
+ algodExitChan := make(chan struct{})
+ startAlgodCompletedChan := make(chan struct{})
+ defer close(startAlgodCompletedChan)
go func() {
// this Wait call is important even beyond the scope of this function; it allows the system to
// move the process from a "zombie" state into "done" state, and is required for the Signal(0) test.
- algodCmd.Wait()
- c <- true
+ err := algodCmd.Wait()
+ select {
+ case <-startAlgodCompletedChan:
+ // we've already exited this function, so we want to report to the error to the callback.
+ if args.ExitErrorCallback != nil {
+ args.ExitErrorCallback(nc, err)
+ }
+ default:
+ }
+ algodExitChan <- struct{}{}
}()
success := false
for !success {
select {
- case <-c:
+ case <-algodExitChan:
return false, errAlgodExitedEarly
case <-time.After(time.Millisecond * 100):
// If we can't talk to the API yet, spin
diff --git a/nodecontrol/kmdControl.go b/nodecontrol/kmdControl.go
index 22bf068a84..00123add48 100644
--- a/nodecontrol/kmdControl.go
+++ b/nodecontrol/kmdControl.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -240,6 +240,22 @@ func (kc *KMDController) StartKMD(args KMDStartArgs) (alreadyRunning bool, err e
// Check if we exited because kmd is already running
if exitCode == codes.ExitCodeKMDAlreadyRunning {
+ kmdClient, err := kc.KMDClient()
+ if err != nil {
+ // kmd told us it's running, but we couldn't construct a client.
+ // we want to keep waiting until the kmd would write out the
+ // file.
+ continue
+ }
+
+ // See if the server is up by requesting the versions endpoint
+ req := kmdapi.VersionsRequest{}
+ resp := kmdapi.VersionsResponse{}
+ err = kmdClient.DoV1Request(req, &resp)
+ if err != nil {
+ return false, err
+ }
+ // cool; kmd is up and running, and responding to version queries.
return true, nil
}
diff --git a/nodecontrol/nodeControlErrors.go b/nodecontrol/nodeControlErrors.go
index c15fc0f1c5..8d0a53762b 100644
--- a/nodecontrol/nodeControlErrors.go
+++ b/nodecontrol/nodeControlErrors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/codec.go b/protocol/codec.go
index 3e50f334e0..cc5f087e51 100644
--- a/protocol/codec.go
+++ b/protocol/codec.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/codec_test.go b/protocol/codec_test.go
index 12fdc47b19..4058f95212 100644
--- a/protocol/codec_test.go
+++ b/protocol/codec_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/consensus.go b/protocol/consensus.go
index dd7c5db965..38d9a3da2d 100644
--- a/protocol/consensus.go
+++ b/protocol/consensus.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -148,6 +148,16 @@ const ConsensusTestRapidRewardRecalculation = ConsensusVersion("test-fast-reward
// that decreases the MaxBalLookback greatly.
const ConsensusTestShorterLookback = ConsensusVersion("test-shorter-lookback")
+// ConsensusTestUnupgradedProtocol is a version of ConsensusCurrentVersion
+// that allows the control of the upgrade from ConsensusTestUnupgradedProtocol to
+// ConsensusTestUnupgradedProtocol
+const ConsensusTestUnupgradedProtocol = ConsensusVersion("test-unupgraded-protocol")
+
+// ConsensusTestUnupgradedToProtocol is a version of ConsensusCurrentVersion
+// It is used as an upgrade from ConsensusTestUnupgradedProtocol
+const ConsensusTestUnupgradedToProtocol = ConsensusVersion("test-unupgradedto-protocol")
+
+
// ConsensusTestFastUpgrade is meant for testing of protocol upgrades:
// during testing, it is equivalent to another protocol with the exception
// of the upgrade parameters, which allow for upgrades to take place after
diff --git a/protocol/encodebench_test.go b/protocol/encodebench_test.go
index f1b458b828..06b542b86b 100644
--- a/protocol/encodebench_test.go
+++ b/protocol/encodebench_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/hash.go b/protocol/hash.go
index cec479b567..b42bfc1e89 100644
--- a/protocol/hash.go
+++ b/protocol/hash.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/networks.go b/protocol/networks.go
index 8276f776a6..50ea9fedc4 100644
--- a/protocol/networks.go
+++ b/protocol/networks.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/tags.go b/protocol/tags.go
index 43d34f27c6..04ceee02aa 100644
--- a/protocol/tags.go
+++ b/protocol/tags.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/msgpacktool/core.go b/protocol/transcode/core.go
similarity index 89%
rename from cmd/msgpacktool/core.go
rename to protocol/transcode/core.go
index 3ebc52fcb4..a81206c36e 100644
--- a/cmd/msgpacktool/core.go
+++ b/protocol/transcode/core.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with go-algorand. If not, see .
-package main
+package transcode
import (
"encoding/base32"
@@ -32,7 +32,8 @@ type decoder interface {
Decode(v interface{}) error
}
-func transcode(mpToJSON bool, in io.ReadCloser, out io.WriteCloser) error {
+// Transcode turns msgpack to JSON or JSON to msgpack
+func Transcode(mpToJSON bool, base32Encoding, strictJSON bool, in io.Reader, out io.Writer) error {
canonicalMsgpackHandle := new(codec.MsgpackHandle)
canonicalMsgpackHandle.ErrorIfNoField = true
canonicalMsgpackHandle.ErrorIfNoArrayExpand = true
@@ -62,9 +63,6 @@ func transcode(mpToJSON bool, in io.ReadCloser, out io.WriteCloser) error {
enc = codec.NewEncoder(out, canonicalMsgpackHandle)
}
- defer in.Close()
- defer out.Close()
-
for {
var a interface{}
err := dec.Decode(&a)
@@ -77,7 +75,7 @@ func transcode(mpToJSON bool, in io.ReadCloser, out io.WriteCloser) error {
}
if mpToJSON {
- a = toJSON(a)
+ a = toJSON(a, base32Encoding, strictJSON)
} else {
a = fromJSON(a)
}
@@ -93,7 +91,7 @@ func transcode(mpToJSON bool, in io.ReadCloser, out io.WriteCloser) error {
}
}
-func toJSON(a interface{}) interface{} {
+func toJSON(a interface{}, base32Encoding, strictJSON bool) interface{} {
switch v := a.(type) {
case map[interface{}]interface{}:
r := make(map[interface{}]interface{})
@@ -106,16 +104,18 @@ func toJSON(a interface{}) interface{} {
eb, ok2 := e.([]byte)
if ok1 && ok2 {
- if *base32Encoding {
+ if base32Encoding {
r[fmt.Sprintf("%s:b32", ks)] = base32.StdEncoding.EncodeToString(eb)
} else {
r[fmt.Sprintf("%s:b64", ks)] = base64.StdEncoding.EncodeToString(eb)
}
} else {
- if *strictJSON {
+ if strictJSON {
k = fmt.Sprintf("%v", k)
}
- r[toJSON(k)] = toJSON(e)
+ kenc := toJSON(k, base32Encoding, strictJSON)
+ eenc := toJSON(e, base32Encoding, strictJSON)
+ r[kenc] = eenc
}
}
return r
@@ -123,7 +123,8 @@ func toJSON(a interface{}) interface{} {
case []interface{}:
r := make([]interface{}, 0)
for _, e := range v {
- r = append(r, toJSON(e))
+ eenc := toJSON(e, base32Encoding, strictJSON)
+ r = append(r, eenc)
}
return r
diff --git a/cmd/msgpacktool/core_test.go b/protocol/transcode/core_test.go
similarity index 97%
rename from cmd/msgpacktool/core_test.go
rename to protocol/transcode/core_test.go
index a6f703a8b7..17ef93b63b 100644
--- a/cmd/msgpacktool/core_test.go
+++ b/protocol/transcode/core_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with go-algorand. If not, see .
-package main
+package transcode
import (
"encoding/base32"
@@ -30,7 +30,9 @@ import (
)
func transcodeNoError(t *testing.T, mpToJSON bool, in io.ReadCloser, out io.WriteCloser) {
- err := transcode(mpToJSON, in, out)
+ defer in.Close()
+ defer out.Close()
+ err := Transcode(mpToJSON, false, false, in, out)
require.NoError(t, err)
}
diff --git a/protocol/txntype.go b/protocol/txntype.go
index 8310f5c203..b1c7047be3 100644
--- a/protocol/txntype.go
+++ b/protocol/txntype.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/fetcher.go b/rpcs/fetcher.go
index e0d147a6e1..56b30da5d4 100644
--- a/rpcs/fetcher.go
+++ b/rpcs/fetcher.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/fetcher_test.go b/rpcs/fetcher_test.go
index 298eec4113..67766eb646 100644
--- a/rpcs/fetcher_test.go
+++ b/rpcs/fetcher_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -45,8 +45,6 @@ type MockRunner struct {
txgroups [][]transactions.SignedTxn
}
-const goExecTime = 100 * time.Millisecond
-
type MockRPCClient struct {
client *MockRunner
closed bool
@@ -188,6 +186,7 @@ func TestSelectValidRemote(t *testing.T) {
type dummyFetcher struct {
failWithNil bool
failWithError bool
+ fetchTimeout time.Duration
}
// FetcherClient interface
@@ -198,13 +197,9 @@ func (df *dummyFetcher) GetBlockBytes(ctx context.Context, r basics.Round) (data
if df.failWithError {
return nil, errors.New("failing call")
}
- timer := time.NewTimer(goExecTime)
+
+ timer := time.NewTimer(df.fetchTimeout)
defer timer.Stop()
- select {
- case <-timer.C:
- case <-ctx.Done():
- return nil, ctx.Err()
- }
// Fill in the dummy response with the correct round
dummyBlock := EncodedBlockCert{
@@ -218,7 +213,15 @@ func (df *dummyFetcher) GetBlockBytes(ctx context.Context, r basics.Round) (data
},
}
- return protocol.Encode(dummyBlock), nil
+ encodedData := protocol.Encode(dummyBlock)
+
+ select {
+ case <-timer.C:
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+
+ return encodedData, nil
}
// FetcherClient interface
@@ -233,10 +236,10 @@ func (df *dummyFetcher) Close() error {
return nil
}
-func makeDummyFetchers(failWithNil bool, failWithError bool) []FetcherClient {
+func makeDummyFetchers(failWithNil bool, failWithError bool, timeout time.Duration) []FetcherClient {
out := make([]FetcherClient, numberOfPeers)
for i := range out {
- out[i] = &dummyFetcher{failWithNil, failWithError}
+ out[i] = &dummyFetcher{failWithNil, failWithError, timeout}
}
return out
}
@@ -245,7 +248,7 @@ func TestFetchBlock(t *testing.T) {
fetcher := &NetworkFetcher{
roundUpperBound: make(map[FetcherClient]basics.Round),
activeFetches: make(map[FetcherClient]int),
- peers: makeDummyFetchers(false, false),
+ peers: makeDummyFetchers(false, false, 100*time.Millisecond),
log: logging.TestingLog(t),
}
@@ -261,8 +264,8 @@ func TestFetchBlock(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, client)
end := time.Now()
- require.True(t, end.Sub(start) > goExecTime)
- require.True(t, end.Sub(start) < goExecTime+10*time.Millisecond)
+ require.True(t, end.Sub(start) > 100*time.Millisecond)
+ require.True(t, end.Sub(start) < 100*time.Millisecond+5*time.Second) // we want to have a higher margin here, as the machine we're running on might be slow.
if err == nil {
require.NotEqual(t, nil, block)
require.NotEqual(t, nil, cert)
@@ -279,7 +282,7 @@ func TestFetchBlockFail(t *testing.T) {
fetcher := &NetworkFetcher{
roundUpperBound: make(map[FetcherClient]basics.Round),
activeFetches: make(map[FetcherClient]int),
- peers: makeDummyFetchers(true, false),
+ peers: makeDummyFetchers(true, false, 100*time.Millisecond),
log: logging.TestingLog(t),
}
@@ -295,45 +298,46 @@ func TestFetchBlockAborted(t *testing.T) {
fetcher := &NetworkFetcher{
roundUpperBound: make(map[FetcherClient]basics.Round),
activeFetches: make(map[FetcherClient]int),
- peers: makeDummyFetchers(false, false),
+ peers: makeDummyFetchers(false, false, 2*time.Second),
log: logging.TestingLog(t),
}
- start := time.Now()
- ctx, cf := context.WithTimeout(context.Background(), goExecTime/2)
+ ctx, cf := context.WithCancel(context.Background())
defer cf()
+ go func() {
+ cf()
+ }()
+ start := time.Now()
_, _, client, err := fetcher.FetchBlock(ctx, basics.Round(1))
end := time.Now()
- require.Error(t, err)
+ require.True(t, strings.Contains(err.Error(), context.Canceled.Error()))
require.Nil(t, client)
- require.True(t, end.Sub(start) > goExecTime/2)
- require.True(t, end.Sub(start) < goExecTime/2+10*time.Millisecond)
+ require.True(t, end.Sub(start) < 10*time.Second)
}
func TestFetchBlockTimeout(t *testing.T) {
fetcher := &NetworkFetcher{
roundUpperBound: make(map[FetcherClient]basics.Round),
activeFetches: make(map[FetcherClient]int),
- peers: makeDummyFetchers(false, false),
+ peers: makeDummyFetchers(false, false, 10*time.Second),
log: logging.TestingLog(t),
}
-
start := time.Now()
- ctx, cf := context.WithTimeout(context.Background(), goExecTime/2)
+ ctx, cf := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cf()
_, _, client, err := fetcher.FetchBlock(ctx, basics.Round(1))
end := time.Now()
- require.Error(t, err)
+ require.True(t, strings.Contains(err.Error(), context.DeadlineExceeded.Error()))
require.Nil(t, client)
- require.True(t, end.Sub(start) > goExecTime/2)
- require.True(t, end.Sub(start) < goExecTime/2+10*time.Millisecond)
+ require.True(t, end.Sub(start) >= 500*time.Millisecond)
+ require.True(t, end.Sub(start) < 10*time.Second)
}
func TestFetchBlockErrorCall(t *testing.T) {
fetcher := &NetworkFetcher{
roundUpperBound: make(map[FetcherClient]basics.Round),
activeFetches: make(map[FetcherClient]int),
- peers: makeDummyFetchers(false, true),
+ peers: makeDummyFetchers(false, true, 10*time.Millisecond),
log: logging.TestingLog(t),
}
@@ -347,7 +351,7 @@ func TestFetchBlockComposedNoOp(t *testing.T) {
f := &NetworkFetcher{
roundUpperBound: make(map[FetcherClient]basics.Round),
activeFetches: make(map[FetcherClient]int),
- peers: makeDummyFetchers(false, false),
+ peers: makeDummyFetchers(false, false, 1*time.Millisecond),
log: logging.TestingLog(t),
}
fetcher := &ComposedFetcher{fetchers: []Fetcher{f, nil}}
@@ -364,8 +368,8 @@ func TestFetchBlockComposedNoOp(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, client)
end := time.Now()
- require.True(t, end.Sub(start) > goExecTime)
- require.True(t, end.Sub(start) < goExecTime+10*time.Millisecond)
+ require.True(t, end.Sub(start) >= 1*time.Millisecond)
+ require.True(t, end.Sub(start) < 1*time.Millisecond+10*time.Second) // we take a very high margin here for the fetcher to complete.
if err == nil {
require.NotEqual(t, nil, block)
require.NotEqual(t, nil, cert)
@@ -383,13 +387,13 @@ func TestFetchBlockComposedFail(t *testing.T) {
f := &NetworkFetcher{
roundUpperBound: make(map[FetcherClient]basics.Round),
activeFetches: make(map[FetcherClient]int),
- peers: makeDummyFetchers(true, false),
+ peers: makeDummyFetchers(true, false, 1*time.Millisecond),
log: logging.TestingLog(t),
}
f2 := &NetworkFetcher{
roundUpperBound: make(map[FetcherClient]basics.Round),
activeFetches: make(map[FetcherClient]int),
- peers: makeDummyFetchers(false, false),
+ peers: makeDummyFetchers(false, false, 1*time.Millisecond),
log: logging.TestingLog(t),
}
fetcher := &ComposedFetcher{fetchers: []Fetcher{f, f2}}
diff --git a/rpcs/httpFetcher.go b/rpcs/httpFetcher.go
index 4f32a7db34..18bd05e4a9 100644
--- a/rpcs/httpFetcher.go
+++ b/rpcs/httpFetcher.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -104,7 +104,7 @@ func (hf *HTTPFetcher) GetBlockBytes(ctx context.Context, r basics.Round) (data
// TODO: Temporarily allow old and new content types so we have time for lazy upgrades
// Remove this 'old' string after next release.
const ledgerResponseContentTypeOld = "application/algorand-block-v1"
- if contentTypes[0] != ledgerResponseContentType && contentTypes[0] != ledgerResponseContentTypeOld {
+ if contentTypes[0] != LedgerResponseContentType && contentTypes[0] != ledgerResponseContentTypeOld {
hf.log.Warnf("http block fetcher response has an invalid content type : %s", contentTypes[0])
response.Body.Close()
return nil, fmt.Errorf("http block fetcher invalid content type '%s'", contentTypes[0])
diff --git a/rpcs/httpTxSync.go b/rpcs/httpTxSync.go
index 50e7564852..75a6cc0389 100644
--- a/rpcs/httpTxSync.go
+++ b/rpcs/httpTxSync.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/ledgerService.go b/rpcs/ledgerService.go
index a67690b1bc..6237b15eb1 100644
--- a/rpcs/ledgerService.go
+++ b/rpcs/ledgerService.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -36,7 +36,8 @@ import (
"github.com/algorand/go-algorand/protocol"
)
-const ledgerResponseContentType = "application/x-algorand-block-v1"
+// LedgerResponseContentType is the HTTP Content-Type header for a raw binary block
+const LedgerResponseContentType = "application/x-algorand-block-v1"
const ledgerResponseHasBlockCacheControl = "public, max-age=31536000, immutable" // 31536000 seconds are one year.
const ledgerResponseMissingBlockCacheControl = "public, max-age=1, must-revalidate" // cache for 1 second, and force revalidation afterward
const ledgerServerMaxBodyLength = 512 // we don't really pass meaningful content here, so 512 bytes should be a safe limit
@@ -160,7 +161,7 @@ func (ls *LedgerService) ServeHTTP(response http.ResponseWriter, request *http.R
response.WriteHeader(http.StatusBadRequest)
return
}
- encodedBlockCert, err := ls.encodedBlockCert(round)
+ encodedBlockCert, err := RawBlockBytes(ls.ledger, basics.Round(round))
if err != nil {
switch err.(type) {
case ledger.ErrNoEntry:
@@ -176,7 +177,7 @@ func (ls *LedgerService) ServeHTTP(response http.ResponseWriter, request *http.R
}
}
- response.Header().Set("Content-Type", ledgerResponseContentType)
+ response.Header().Set("Content-Type", LedgerResponseContentType)
response.Header().Set("Content-Length", strconv.Itoa(len(encodedBlockCert)))
response.Header().Set("Cache-Control", ledgerResponseHasBlockCacheControl)
response.WriteHeader(http.StatusOK)
@@ -236,7 +237,8 @@ func (ls *LedgerService) handleCatchupReq(ctx context.Context, reqMsg network.In
return
}
res.Round = req.Round
- encodedBlob, err := ls.encodedBlockCert(req.Round)
+ encodedBlob, err := RawBlockBytes(ls.ledger, basics.Round(req.Round))
+
if err != nil {
res.Error = err.Error()
return
@@ -254,8 +256,9 @@ func (ls *LedgerService) sendCatchupRes(ctx context.Context, target network.Unic
}
}
-func (ls *LedgerService) encodedBlockCert(round uint64) ([]byte, error) {
- blk, cert, err := ls.ledger.EncodedBlockCert(basics.Round(round))
+// RawBlockBytes return the msgpack bytes for a block
+func RawBlockBytes(ledger *data.Ledger, round basics.Round) ([]byte, error) {
+ blk, cert, err := ledger.EncodedBlockCert(round)
if err != nil {
return nil, err
}
diff --git a/rpcs/ledgerService_test.go b/rpcs/ledgerService_test.go
index 8b783f3e84..f70c4fab53 100644
--- a/rpcs/ledgerService_test.go
+++ b/rpcs/ledgerService_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -113,10 +113,11 @@ func TestGetBlockHTTP(t *testing.T) {
start := time.Now()
block, cert, client, err = fetcher.FetchBlock(context.Background(), next)
+ end := time.Now()
require.NotNil(t, client)
require.NoError(t, err)
- end := time.Now()
- require.True(t, end.Sub(start) < goExecTime+10*time.Millisecond)
+
+ require.True(t, end.Sub(start) < 10*time.Second)
require.Equal(t, &b, block)
if err == nil {
require.NotEqual(t, nil, block)
@@ -211,7 +212,7 @@ func TestGetBlockWS(t *testing.T) {
require.NotNil(t, client)
require.NoError(t, err)
end := time.Now()
- require.True(t, end.Sub(start) < goExecTime+10*time.Millisecond)
+ require.True(t, end.Sub(start) < 10*time.Second)
require.Equal(t, &b, block)
if err == nil {
require.NotEqual(t, nil, block)
diff --git a/rpcs/registrar.go b/rpcs/registrar.go
index bd3ffcfbb7..066758e391 100644
--- a/rpcs/registrar.go
+++ b/rpcs/registrar.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/txService.go b/rpcs/txService.go
index 7dec5e235e..9e1fa23388 100644
--- a/rpcs/txService.go
+++ b/rpcs/txService.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/txService_test.go b/rpcs/txService_test.go
index 292581095c..9ae78ab5e7 100644
--- a/rpcs/txService_test.go
+++ b/rpcs/txService_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/txSyncer.go b/rpcs/txSyncer.go
index cef74b8a58..6686ba72a7 100644
--- a/rpcs/txSyncer.go
+++ b/rpcs/txSyncer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/txSyncer_test.go b/rpcs/txSyncer_test.go
index 955c6fbcbd..ecb523f49a 100644
--- a/rpcs/txSyncer_test.go
+++ b/rpcs/txSyncer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/wsFetcher.go b/rpcs/wsFetcher.go
index 77f97cea9d..7005a1bb34 100644
--- a/rpcs/wsFetcher.go
+++ b/rpcs/wsFetcher.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/wsFetcherService.go b/rpcs/wsFetcherService.go
index f8f095fbd6..140e1d9528 100644
--- a/rpcs/wsFetcherService.go
+++ b/rpcs/wsFetcherService.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 Algorand, Inc.
+// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/scripts/LICENSE_HEADER b/scripts/LICENSE_HEADER
index a2027f171b..9fc9a8473c 100644
--- a/scripts/LICENSE_HEADER
+++ b/scripts/LICENSE_HEADER
@@ -1,4 +1,4 @@
-// Copyright (C) {DATE_Y} Algorand, Inc.
+// Copyright (C) 2019-{DATE_Y} Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/scripts/build_release.sh b/scripts/build_release.sh
deleted file mode 100755
index 2a5beaa3e5..0000000000
--- a/scripts/build_release.sh
+++ /dev/null
@@ -1,230 +0,0 @@
-#!/usr/bin/env bash
-#
-# This script needs to be run in a terminal with a human watching to
-# be prompted for GPG key password at a couple points.
-#
-# Externally settable env vars:
-# S3_PREFIX= where to upload build artifacts (no trailing /)
-# RSTAMP= `scripts/reverse_hex_timestamp`
-# AWS_ACCESS_KEY_ID=
-# AWS_SECRET_ACCESS_KEY=
-
-date "+build_release start %Y%m%d_%H%M%S"
-
-set -e
-set -x
-
-# Anchor our repo root reference location
-REPO_ROOT="$( cd "$(dirname "$0")" ; pwd -P )"/..
-
-# a previous docker centos build can leave junk owned by root. chown and clean
-sudo chown -R ${USER} ${GOPATH}
-if [ -f ${REPO_ROOT}/crypto/libsodium-fork/Makefile ]; then
- (cd ${REPO_ROOT}/crypto/libsodium-fork && make distclean)
-fi
-rm -rf ${REPO_ROOT}/crypto/lib
-
-
-cd ${REPO_ROOT}
-export RELEASE_GENESIS_PROCESS=true
-PLATFORM=$(./scripts/osarchtype.sh)
-PLATFORM_SPLIT=(${PLATFORM//\// })
-OS=${PLATFORM_SPLIT[0]}
-ARCH=${PLATFORM_SPLIT[1]}
-export BRANCH=$(./scripts/compute_branch.sh)
-export CHANNEL=$(./scripts/compute_branch_channel.sh ${BRANCH})
-export DEFAULTNETWORK=$(./scripts/compute_branch_network.sh)
-export PKG_ROOT=${HOME}/node_pkg
-export VARIATIONS="base"
-# tell underlying 'build' scripts we already built
-export NO_BUILD=true
-if [ -z "${RSTAMP}" ]; then
- RSTAMP=$(scripts/reverse_hex_timestamp)
- echo RSTAMP=${RSTAMP} > "${HOME}/rstamp"
-fi
-# What's my default IP address?
-# get the datacenter IP address for this EC2 host.
-# this might equivalently be gotten from `netstat -rn` and `ifconfig -a`
-if [ -z "${DC_IP}" ]; then
- DC_IP=$(curl --silent http://169.254.169.254/latest/meta-data/local-ipv4)
-fi
-if [ -z "${DC_IP}" ]; then
- echo "ERROR: need DC_IP to be set to your local (but not localhost) IP"
- exit 1
-fi
-
-# Update version file for this build
-if [ ! -z "${BUILD_NUMBER}" ]; then
- echo "using externally set BUILD_NUMBER=${BUILD_NUMBER} without incrementing"
-else
- if [ -e buildnumber.dat ]; then
- BUILD_NUMBER=$(cat ./buildnumber.dat)
- BUILD_NUMBER=$((${BUILD_NUMBER} + 1))
- else
- BUILD_NUMBER=0
- fi
- echo ${BUILD_NUMBER} > ./buildnumber.dat
- git add -A
- git commit -m "Build ${BUILD_NUMBER}"
-fi
-export FULLVERSION=$(./scripts/compute_build_number.sh -f)
-
-# a bash user might `source build_env` to manually continue a broken build
-cat <${HOME}/build_env
-export RELEASE_GENESIS_PROCESS=${RELEASE_GENESIS_PROCESS}
-PLATFORM=${PLATFORM}
-OS=${OS}
-ARCH=${ARCH}
-export BRANCH=${BRANCH}
-export CHANNEL=${CHANNEL}
-export DEFAULTNETWORK=${DEFAULTNETWORK}
-export PKG_ROOT=${PKG_ROOT}
-export VARIATIONS=${VARIATIONS}
-RSTAMP=${RSTAMP}
-BUILD_NUMBER=${BUILD_NUMBER}
-export FULLVERSION=${FULLVERSION}
-DC_IP=${DC_IP}
-EOF
-# strip leading 'export ' for docker --env-file
-sed 's/^export //g' < ${HOME}/build_env > ${HOME}/build_env_docker
-
-# Build!
-scripts/configure_dev.sh
-
-make crypto/lib/libsodium.a
-
-make build
-
-export BUILD_DEB=1
-scripts/build_packages.sh "${PLATFORM}"
-
-# build docker release package
-cd ${REPO_ROOT}/docker/release
-sg docker "./build_algod_docker.sh ${HOME}/node_pkg/node_${CHANNEL}_${OS}-${ARCH}_${FULLVERSION}.tar.gz"
-cd ${REPO_ROOT}/scripts
-
-# Test .deb installer
-
-. get_centos_gpg.sh
-
-export GNUPGHOME=${HOME}/tkey
-gpgconf --kill gpg-agent
-rm -rf ${GNUPGHOME}
-mkdir -p ${GNUPGHOME}
-chmod 700 ${GNUPGHOME}
-cat >${HOME}/tkey/keygenscript<${HOME}/tkey/rpmkeygenscript<${GNUPGHOME}/gpg-agent.conf
-extra-socket ${GNUPGHOME}/S.gpg-agent.extra
-# inable unattended daemon mode
-allow-preset-passphrase
-# cache password 30 days
-default-cache-ttl 2592000
-max-cache-ttl 2592000
-EOF
-gpg --gen-key --batch ${HOME}/tkey/keygenscript
-gpg --gen-key --batch ${HOME}/tkey/rpmkeygenscript
-gpg --export -a dev@algorand.com > "${HOME}/docker_test_resources/key.pub"
-gpg --export -a rpm@algorand.com > "${HOME}/docker_test_resources/rpm.pub"
-
-gpgconf --kill gpg-agent
-gpgconf --launch gpg-agent
-
-gpgp=$(ls /usr/lib/gnupg{2,,1}/gpg-preset-passphrase|head -1)
-KEYGRIP=$(gpg -K --with-keygrip --textmode dev@algorand.com|grep Keygrip|head -1|awk '{ print $3 }')
-echo foogorand|${gpgp} --verbose --preset ${KEYGRIP}
-KEYGRIP=$(gpg -K --with-keygrip --textmode rpm@algorand.com|grep Keygrip|head -1|awk '{ print $3 }')
-echo foogorand|${gpgp} --verbose --preset ${KEYGRIP}
-
-# copy previous installers into ~/docker_test_resources
-cd "${HOME}/docker_test_resources"
-if [ "${TEST_UPGRADE}" == "no" -o -z "${S3_PREFIX}" ]; then
- echo "upgrade test disabled"
-else
- python3 ${REPO_ROOT}/scripts/get_current_installers.py "${S3_PREFIX}/${CHANNEL}"
-fi
-
-echo "TEST_UPGRADE=${TEST_UPGRADE}" >> ${HOME}/build_env_docker
-
-rm -rf ${HOME}/dummyaptly
-mkdir -p ${HOME}/dummyaptly
-cat <${HOME}/dummyaptly.conf
-{
- "rootDir": "${HOME}/dummyaptly",
- "downloadConcurrency": 4,
- "downloadSpeedLimit": 0,
- "architectures": [],
- "dependencyFollowSuggests": false,
- "dependencyFollowRecommends": false,
- "dependencyFollowAllVariants": false,
- "dependencyFollowSource": false,
- "dependencyVerboseResolve": false,
- "gpgDisableSign": false,
- "gpgDisableVerify": false,
- "gpgProvider": "gpg",
- "downloadSourcePackages": false,
- "skipLegacyPool": true,
- "ppaDistributorID": "ubuntu",
- "ppaCodename": "",
- "skipContentsPublishing": false,
- "FileSystemPublishEndpoints": {},
- "S3PublishEndpoints": {},
- "SwiftPublishEndpoints": {}
-}
-EOF
-aptly -config=${HOME}/dummyaptly.conf repo create -distribution=stable -component=main algodummy
-aptly -config=${HOME}/dummyaptly.conf repo add algodummy ${HOME}/node_pkg/*.deb
-SNAPSHOT=algodummy-$(date +%Y%m%d_%H%M%S)
-aptly -config=${HOME}/dummyaptly.conf snapshot create ${SNAPSHOT} from repo algodummy
-aptly -config=${HOME}/dummyaptly.conf publish snapshot -origin=Algorand -label=Algorand ${SNAPSHOT}
-
-${REPO_ROOT}/scripts/build_release_run_ubuntu_docker_build_test.sh
-
-date "+build_release done building ubuntu %Y%m%d_%H%M%S"
-
-# Run RPM bulid in Centos7 Docker container
-sg docker "docker build -t algocentosbuild - < ${REPO_ROOT}/scripts/centos-build.Dockerfile"
-
-# cleanup our libsodium build
-if [ -f ${REPO_ROOT}/crypto/libsodium-fork/Makefile ]; then
- (cd ${REPO_ROOT}/crypto/libsodium-fork && make distclean)
-fi
-rm -rf ${REPO_ROOT}/crypto/lib
-
-# do the RPM build, sign and validate it
-
-sudo rm -rf ${HOME}/dummyrepo
-mkdir -p ${HOME}/dummyrepo
-
-cat <${HOME}/dummyrepo/algodummy.repo
-[algodummy]
-name=Algorand
-baseurl=http://${DC_IP}:8111/
-enabled=1
-gpgcheck=1
-gpgkey=https://releases.algorand.com/rpm/rpm_algorand.pub
-EOF
-(cd ${HOME}/dummyrepo && python3 ${REPO_ROOT}/scripts/httpd.py --pid ${HOME}/phttpd.pid) &
-trap ${REPO_ROOT}/scripts/kill_httpd.sh 0
-
-sg docker "docker run --rm --env-file ${HOME}/build_env_docker --mount type=bind,src=${GNUPGHOME}/S.gpg-agent.extra,dst=/S.gpg-agent --mount type=bind,src=${HOME}/dummyrepo,dst=/dummyrepo --mount type=bind,src=${HOME}/docker_test_resources,dst=/stuff --mount type=bind,src=${GOPATH}/src,dst=/root/go/src --mount type=bind,src=${HOME},dst=/root/subhome --mount type=bind,src=/usr/local/go,dst=/usr/local/go algocentosbuild /root/go/src/github.com/algorand/go-algorand/scripts/build_release_centos_docker.sh"
-
-date "+build_release done building centos %Y%m%d_%H%M%S"
-
-# NEXT: build_release_sign.sh
diff --git a/scripts/build_release_centos_docker.sh b/scripts/build_release_centos_docker.sh
deleted file mode 100644
index cf9c9ef7fc..0000000000
--- a/scripts/build_release_centos_docker.sh
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/env bash
-# build centos rpm from inside docker
-#
-# mount src from outside
-# --mount type=bind,src=${GOPATH}/src,dst=/root/go/src
-#
-# mount golang install from outside
-# --mount type=bind,src=/usr/local/go,dst=/usr/local/go
-#
-# output copied to /root/subhome/node_pkg
-# --mount type=bind,src=${HOME},dst=/root/subhome
-
-set -e
-set -x
-
-export HOME=/root
-mkdir -p ${HOME}/go
-mkdir -p ${HOME}/go/bin
-export GOPATH=${HOME}/go
-export PATH=${GOPATH}/bin:/usr/local/go/bin:${PATH}
-
-# Anchor our repo root reference location
-REPO_DIR="$( cd "$(dirname "$0")" ; pwd -P )"/..
-
-${REPO_DIR}/scripts/configure_dev-deps.sh
-
-cd ${REPO_DIR}
-
-# definitely rebuild libsodium which could link to external C libraries
-if [ -f ${REPO_DIR}/crypto/libsodium-fork/Makefile ]; then
- (cd ${REPO_DIR}/crypto/libsodium-fork && make distclean)
-fi
-rm -rf ${REPO_DIR}/crypto/lib
-make crypto/lib/libsodium.a
-
-make build
-
-export NO_BUILD=1
-
-RPMTMP=$(mktemp -d 2>/dev/null || mktemp -d -t "rpmtmp")
-trap "rm -rf ${RPMTMP}" 0
-scripts/build_rpm.sh ${RPMTMP}
-cp -p ${RPMTMP}/*/*.rpm /root/subhome/node_pkg
-
-(cd ${HOME} && tar jxf /stuff/gnupg*.tar.bz2)
-export PATH="${HOME}/gnupg2/bin:${PATH}"
-export LD_LIBRARY_PATH=${HOME}/gnupg2/lib
-
-umask 0077
-mkdir -p ~/.gnupg
-umask 0022
-
-touch "${HOME}/.gnupg/gpg.conf"
-if grep -q no-autostart "${HOME}/.gnupg/gpg.conf"; then
- echo ""
-else
- echo "no-autostart" >> "${HOME}/.gnupg/gpg.conf"
-fi
-rm -f ${HOME}/.gnupg/S.gpg-agent
-(cd ~/.gnupg && ln -s /S.gpg-agent S.gpg-agent)
-
-gpg --import /stuff/key.pub
-gpg --import /stuff/rpm.pub
-gpg --import ${REPO_DIR}/installer/rpm/RPM-GPG-KEY-Algorand
-rpmkeys --import /stuff/rpm.pub
-echo "wat"|gpg -u rpm@algorand.com --clearsign
-
-cat <"${HOME}/.rpmmacros"
-%_gpg_name Algorand RPM
-%__gpg ${HOME}/gnupg2/bin/gpg
-%__gpg_check_password_cmd true
-EOF
-
-cat <"${HOME}/rpmsign.py"
-import rpm
-import sys
-rpm.addSign(sys.argv[1], '')
-EOF
-
-NEWEST_RPM=$(ls -t /root/subhome/node_pkg/*rpm|head -1)
-python2 "${HOME}/rpmsign.py" "${NEWEST_RPM}"
-
-cp -p "${NEWEST_RPM}" /dummyrepo
-createrepo --database /dummyrepo
-rm -f /dummyrepo/repodata/repomd.xml.asc
-gpg -u rpm@algorand.com --detach-sign --armor /dummyrepo/repodata/repomd.xml
-
-OLDRPM=$(ls -t /stuff/*.rpm|head -1)
-if [ -f "${OLDRPM}" ]; then
- yum install -y "${OLDRPM}"
- algod -v
- if algod -v | grep -q ${FULLVERSION}; then
- echo "already installed current version. wat?"
- false
- fi
-
- mkdir -p /root/testnode
- cp -p /var/lib/algorand/genesis/testnet/genesis.json /root/testnode
-
- goal node start -d /root/testnode
- goal node wait -d /root/testnode -w 120
- goal node stop -d /root/testnode
-fi
-
-
-yum-config-manager --add-repo http://${DC_IP}:8111/algodummy.repo
-
-yum install -y algorand
-algod -v
-# check that the installed version is now the current version
-algod -v | grep -q ${FULLVERSION}.${CHANNEL}
-
-if [ ! -d /root/testnode ]; then
- mkdir -p /root/testnode
- cp -p /var/lib/algorand/genesis/testnet/genesis.json /root/testnode
-fi
-
-goal node start -d /root/testnode
-goal node wait -d /root/testnode -w 120
-goal node stop -d /root/testnode
-
-
-echo CENTOS_DOCKER_TEST_OK
diff --git a/scripts/build_release_local.sh b/scripts/build_release_local.sh
deleted file mode 100644
index 9374c5f0e4..0000000000
--- a/scripts/build_release_local.sh
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/env bash
-#
-# This is a file of commands to copy and paste to run build_release.sh on an AWS EC2 instance.
-# Should work on Ubuntu 16.04 ro 18.04
-#
-# Externally settable env vars:
-# S3_PREFIX_BUILDLOG= where upload build log (no trailing /)
-
-echo "this is a file of commands to copy and paste to run build_release.sh on an AWS EC2 instance"
-exit 1
-
-# use AWS console to create a new t3.large with the latest official Ubuntu 18.04
-
-# ec2 public address here:
-TARGET=
-
-cd ${GOPATH}/src/github.com/algorand/go-algorand
-
-git fetch
-git checkout rel/stable
-git merge origin/rel/stable
-scp -p ${GOPATH}/src/github.com/algorand/go-algorand/scripts/build_release_setup.sh ubuntu@${TARGET}:~/
-
-# upload the latest public key
-GTMPDIR=$(mktemp -d 2>/dev/null || mktemp -d -t "rpmtmp")
-gpg --export --armor -o "${GTMPDIR}/key.gpg" dev@algorand.com
-scp -p "${GTMPDIR}/key.gpg" "ubuntu@${TARGET}:~/key.gpg"
-rm -rf ${GTMPDIR}
-
-ssh -A ubuntu@${TARGET} bash build_release_setup.sh
-
-# setup GPG key forwarding https://wiki.gnupg.org/AgentForwarding
-umask 0077
-mkdir -p ${HOME}/.gnupg
-touch ${HOME}/.gnupg/gpg-agent.conf
-if grep -q extra-socket ${HOME}/.gnupg/gpg-agent.conf; then
- echo "already have extra-socket"
-else
- cat <>${HOME}/.gnupg/gpg-agent.conf
-extra-socket ${HOME}/.gnupg/S.gpg-agent.extra
-default-cache-ttl 3600
-EOF
-fi
-umask 0002
-
-# this will require your key password, and export a private key file protected by the same password
-
-# warm up your local gpg-agent
-gpg -u dev@algorand.com --clearsign
-type some stuff
-^D
-
-gpg -u rpm@algorand.com --clearsign
-
-
-# TODO: use simpler expression when we can rely on gpg 2.2 on ubuntu >= 18.04
-#REMOTE_GPG_SOCKET=$(ssh ubuntu@${TARGET} gpgconf --list-dir agent-socket)
-#REMOTE_GPG_SOCKET=$(ssh ubuntu@${TARGET} "gpgconf --list-dirs|grep agent-socket|awk -F: '{ print \$2 }'")
-REMOTE_GPG_SOCKET=$(ssh ubuntu@${TARGET} gpgbin/remote_gpg_socket)
-LOCAL_GPG_SOCKET=$(gpgconf --list-dir agent-extra-socket)
-ssh -A -R "${REMOTE_GPG_SOCKET}:${LOCAL_GPG_SOCKET}" ubuntu@${TARGET}
-
-# check gpg agent connection
-gpg -u dev@algorand.com --clearsign
-blah blah
-^D
-
-
-# set AWS credentials so we can upload to S3 and connect to EFS
-export AWS_ACCESS_KEY_ID=
-export AWS_SECRET_ACCESS_KEY=
-
-# where we store persistent scratch space for aptly
-export AWS_EFS_MOUNT=
-
-# build_release.sh needs to be run in a terminal with a human watching
-# to be prompted for GPG key password at a couple points.
-# It can still steal the outer terminal from within piping the output to tee. Nifty, huh?
-BUILDTIMESTAMP=$(cat "${HOME}/buildtimestamp")
-(bash "${HOME}/go/src/github.com/algorand/go-algorand/scripts/build_release.sh" 2>&1)|tee -a "${HOME}/buildlog_${BUILDTIMESTAMP}"
-(bash "${HOME}/go/src/github.com/algorand/go-algorand/scripts/build_release_sign.sh" 2>&1)|tee -a "${HOME}/buildlog_${BUILDTIMESTAMP}"
-(bash "${HOME}/go/src/github.com/algorand/go-algorand/scripts/build_release_upload.sh" 2>&1)|tee -a "${HOME}/buildlog_${BUILDTIMESTAMP}"
-if [ -f "${HOME}/rstamp" ]; then
- . "${HOME}/rstamp"
-fi
-if [ -z "${RSTAMP}" ]; then
- RSTAMP=$(${HOME}/go/src/github.com/algorand/go-algorand/scripts/reverse_hex_timestamp)
-fi
-if [ -z "${RSTAMP}" ]; then
- echo "could not figure out RSTAMP, script must have failed early"
- exit 1
-fi
-gzip "${HOME}/buildlog_${BUILDTIMESTAMP}"
-if [ ! -z "${S3_PREFIX_BUILDLOG}" ]; then
- aws s3 cp "${HOME}/buildlog_${BUILDTIMESTAMP}.gz" "${S3_PREFIX_BUILDLOG}/${RSTAMP}/buildlog_${BUILDTIMESTAMP}.gz"
-fi
diff --git a/scripts/build_release_run_ubuntu_docker_build_test.sh b/scripts/build_release_run_ubuntu_docker_build_test.sh
deleted file mode 100755
index eb92e4f2e2..0000000000
--- a/scripts/build_release_run_ubuntu_docker_build_test.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env bash
-#
-# This script exists to give a trap atexit context for killing the httpd so that we're not waiting on that
-
-set -e
-set -x
-
-(cd ${HOME}/dummyaptly/public && python3 ${GOPATH}/src/github.com/algorand/go-algorand/scripts/httpd.py --pid ${HOME}/phttpd.pid) &
-trap ${GOPATH}/src/github.com/algorand/go-algorand/scripts/kill_httpd.sh 0
-
-# Ubuntu 16 binaries are deprecated. Should still work to build from source for it.
-#sg docker "docker run --rm --env-file ${HOME}/build_env_docker --mount type=bind,src=${HOME}/docker_test_resources,dst=/stuff --mount type=bind,src=${GOPATH}/src,dst=/root/go/src --mount type=bind,src=/usr/local/go,dst=/usr/local/go ubuntu:16.04 bash /root/go/src/github.com/algorand/go-algorand/scripts/build_release_ubuntu_test_docker.sh"
-sg docker "docker run --rm --env-file ${HOME}/build_env_docker --mount type=bind,src=${HOME}/docker_test_resources,dst=/stuff --mount type=bind,src=${GOPATH}/src,dst=/root/go/src --mount type=bind,src=/usr/local/go,dst=/usr/local/go ubuntu:18.04 bash /root/go/src/github.com/algorand/go-algorand/scripts/build_release_ubuntu_test_docker.sh"
-
-export DC_IP
-
-sg docker "${GOPATH}/src/github.com/algorand/go-algorand/scripts/debian/start_docker_debian_test.sh ${HOME}/docker_test_resources"
diff --git a/scripts/build_release_setup.sh b/scripts/build_release_setup.sh
deleted file mode 100644
index d1183ad5f2..0000000000
--- a/scripts/build_release_setup.sh
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/usr/bin/env bash
-#
-# Externally settable env vars:
-# GIT_REPO_PATH= something to `git clone` from
-# GIT_CHECKOUT_LABEL= something to `git checkout` and build from (branch or tag or hash)
-
-if [ -z "${BUILDTIMESTAMP}" ]; then
- date "+%Y%m%d_%H%M%S" > "${HOME}/buildtimestamp"
- BUILDTIMESTAMP=$(cat "${HOME}/buildtimestamp")
- export BUILDTIMESTAMP
- echo run "${0}" with output to ${HOME}/buildlog_${BUILDTIMESTAMP}
- (bash "${0}" 2>&1) | tee ${HOME}/buildlog_${BUILDTIMESTAMP}
- exit 0
-fi
-
-date "+setup start %Y%m%d_%H%M%S"
-
-set -e
-set -x
-
-if [ -z "${GIT_REPO_PATH}" ]; then
- GIT_REPO_PATH=git@github.com:algorand/go-algorand.git
-fi
-
-if [ -z "${GIT_CHECKOUT_LABEL}" ]; then
- GIT_CHECKOUT_LABEL="rel/stable"
-fi
-
-export DEBIAN_FRONTEND=noninteractive
-
-sudo apt-get update -q
-sudo apt-get upgrade -q -y
-
-if [ -f /etc/lsb-release ]; then
- . /etc/lsb-release
-fi
-
-mkdir -p ${HOME}/go
-mkdir -p ${HOME}/gpgbin
-
-cat <${HOME}/gpgbin/remote_gpg_socket
-export GOPATH=\${HOME}/go
-export PATH=\${HOME}/gpgbin:${GOPATH}/bin:/usr/local/go/bin:${PATH}
-gpgconf --list-dirs|grep agent-socket|awk -F: '{ print \$2 }'
-EOF
-chmod +x ${HOME}/gpgbin/remote_gpg_socket
-
-if [ "${DISTRIB_ID}" = "Ubuntu" ]; then
- if [ "${DISTRIB_RELEASE}" = "16.04" ]; then
- echo "WARNING: Ubuntu 16.04 is DEPRECATED"
- sudo apt-get install -y autoconf awscli docker.io g++ fakeroot git gnupg2 gpgv2 make nfs-common python3 rpm sqlite3 python3-boto3 rng-tools
- cat <${HOME}/gpgbin/gpg
-#!/usr/bin/env bash
-exec /usr/bin/gpg2 "\$@"
-EOF
- cat <${HOME}/gpgbin/gpgv
-#!/usr/bin/env bash
-exec /usr/bin/gpgv2 "\$@"
-EOF
- chmod +x ${HOME}/gpgbin/*
- elif [ "${DISTRIB_RELEASE}" = "18.04" ]; then
- sudo apt-get install -y autoconf awscli docker.io git gpg nfs-common python3 rpm sqlite3 python3-boto3 make g++ libtool rng-tools
- else
- echo "don't know how to build on Ubuntu ${DISTRIB_RELEASE}"
- exit 1
- fi
-else
- echo "don't know how to build non Ubuntu, /etc/lsb-release[DISTRIB_ID]=${DISTRIB_ID}"
- exit 1
-fi
-
-sudo rngd -r /dev/urandom
-
-export GOPATH=${HOME}/go
-export PATH=${HOME}/gpgbin:${GOPATH}/bin:/usr/local/go/bin:${PATH}
-
-# please keep packages sorted
-
-# This real name and email must precisely match GPG key
-git config --global user.name "Algorand developers"
-git config --global user.email dev@algorand.com
-
-# configure GnuPG to rely on forwarded remote gpg-agent
-umask 0077
-mkdir -p "${HOME}/.gnupg"
-touch "${HOME}/.gnupg/gpg.conf"
-if grep -q no-autostart "${HOME}/.gnupg/gpg.conf"; then
- echo ""
-else
- echo "no-autostart" >> "${HOME}/.gnupg/gpg.conf"
-fi
-
-if [ -f "${HOME}/key.gpg" ]; then
- gpg --import "${HOME}/key.gpg"
-fi
-# we had a tight umask for gpg setup, but need wider for git clone below
-umask 0002
-
-# allow ssh to clobber unix domain sockets for gpg-agent forwarding
-if grep -q ^StreamLocalBindUnlink /etc/ssh/sshd_config; then
- echo already have StreamLocalBindUnlink sshd config
-else
- sudo bash -c "echo 'StreamLocalBindUnlink yes' >> /etc/ssh/sshd_config"
- sudo systemctl restart sshd
-fi
-
-sudo usermod -a -G docker ubuntu
-sg docker "docker pull centos:7"
-sg docker "docker pull ubuntu:18.04"
-sg docker "docker pull ubuntu:16.04"
-
-touch ~/.ssh/known_hosts
-chmod 644 ~/.ssh/known_hosts
-if grep -q github.com ~/.ssh/known_hosts; then
- echo already have github in known hosts
-else
-cat<> ~/.ssh/known_hosts
-github.com,192.30.253.113 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
-EOF
-fi
-
-# Check out
-mkdir -p ${GOPATH}/src/github.com/algorand
-if [ ! -d "${GOPATH}/src/github.com/algorand/go-algorand/.git" ]; then
- (cd ${GOPATH}/src/github.com/algorand && git clone "${GIT_REPO_PATH}" go-algorand)
-fi
-cd ${GOPATH}/src/github.com/algorand/go-algorand
-git checkout "${GIT_CHECKOUT_LABEL}"
-# TODO: if we are checking out a release tag, `git tag --verify` it
-
-gpg --import ${GOPATH}/src/github.com/algorand/go-algorand/installer/rpm/RPM-GPG-KEY-Algorand
-
-# Install latest Go
-cd $HOME
-# TODO: make a config file in root of repo with single source of truth for Go major-minor version
-if [ ! -e /usr/local/go/bin/go ]; then
- python3 ${GOPATH}/src/github.com/algorand/go-algorand/scripts/get_latest_go.py --version-prefix=1.12
- # $HOME will be interpreted by the outer shell to create the string passed to sudo bash
- sudo bash -c "cd /usr/local && tar zxf ${HOME}/go*.tar.gz"
-fi
-
-cat<> "${HOME}/.bashrc"
-export EDITOR=vi
-EOF
-
-cat<> "${HOME}/.profile"
-export GOPATH=\${HOME}/go
-export PATH=\${HOME}/gpgbin:\${GOPATH}/bin:/usr/local/go/bin:\${PATH}
-EOF
-
-# Install aptly for building debian repo
-mkdir -p $GOPATH/src/github.com/aptly-dev
-if [ ! -d $GOPATH/src/github.com/aptly-dev/aptly ]; then
- git clone https://github.com/aptly-dev/aptly $GOPATH/src/github.com/aptly-dev/aptly
-fi
-(cd $GOPATH/src/github.com/aptly-dev/aptly && git fetch)
-# As of 2019-06-06 release tag v1.3.0 is 2018-May, GnuPG 2 support was added in October but they haven't tagged a new release yet. Hash below seems to work so far.
-# 2019-07-06 v1.4.0
-(cd $GOPATH/src/github.com/aptly-dev/aptly && git checkout v1.4.0)
-(cd $GOPATH/src/github.com/aptly-dev/aptly && make install)
-
-
-date "+setup finish %Y%m%d_%H%M%S"
diff --git a/scripts/build_release_sign.sh b/scripts/build_release_sign.sh
deleted file mode 100644
index e7b887ca9c..0000000000
--- a/scripts/build_release_sign.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env bash
-. ${HOME}/build_env
-set -e
-set -x
-
-# Anchor our repo root reference location
-REPO_ROOT="$( cd "$(dirname "$0")" ; pwd -P )"/..
-
-cd ${REPO_ROOT}
-
-# Tag Source
-TAG=${BRANCH}-${FULLVERSION}
-echo "TAG=${TAG}" >> ${HOME}/build_env
-# creating a signed tag is now a manual process upstream of this build
-# git tag -s -u "${SIGNING_KEY_ADDR}" ${TAG} -m "Genesis Timestamp: $(cat ./genesistimestamp.dat)"
-
-git archive --prefix=algorand-${FULLVERSION}/ "${TAG}" | gzip > ${PKG_ROOT}/algorand_${CHANNEL}_source_${FULLVERSION}.tar.gz
-
-# create *.sig gpg signatures
-cd ${PKG_ROOT}
-for i in *.tar.gz *.deb *.rpm; do
- gpg -u "${SIGNING_KEY_ADDR}" --detach-sign "${i}"
-done
-HASHFILE=hashes_${CHANNEL}_${OS}_${ARCH}_${FULLVERSION}
-rm -f "${HASHFILE}"
-touch "${HASHFILE}"
-md5sum *.tar.gz *.deb *.rpm >> "${HASHFILE}"
-shasum -a 256 *.tar.gz *.deb *.rpm >> "${HASHFILE}"
-shasum -a 512 *.tar.gz *.deb *.rpm >> "${HASHFILE}"
-gpg -u "${SIGNING_KEY_ADDR}" --detach-sign "${HASHFILE}"
-gpg -u "${SIGNING_KEY_ADDR}" --clearsign "${HASHFILE}"
-
-sudo rm -rf ${HOME}/prodrepo
-mkdir -p ${HOME}/prodrepo
-cp -p ${REPO_ROOT}/installer/rpm/algorand.repo ${HOME}/prodrepo/algorand.repo
-
-. ${REPO_ROOT}/scripts/get_centos_gpg.sh
-gpg --export -a dev@algorand.com > "${HOME}/docker_test_resources/key.pub"
-gpg --export -a rpm@algorand.com > "${HOME}/docker_test_resources/rpm.pub"
-
-GPG_AGENT_SOCKET=$(${HOME}/gpgbin/remote_gpg_socket)
-
-sg docker "docker run --rm --env-file ${HOME}/build_env_docker --mount type=bind,src=${GPG_AGENT_SOCKET},dst=/S.gpg-agent --mount type=bind,src=${HOME}/prodrepo,dst=/dummyrepo --mount type=bind,src=${HOME}/docker_test_resources,dst=/stuff --mount type=bind,src=${GOPATH}/src,dst=/root/go/src --mount type=bind,src=${HOME},dst=/root/subhome --mount type=bind,src=/usr/local/go,dst=/usr/local/go algocentosbuild /root/go/src/github.com/algorand/go-algorand/scripts/sign_centos_docker.sh"
-
-date "+build_release done signing %Y%m%d_%H%M%S"
-
-# NEXT: build_release_upload.sh
diff --git a/scripts/build_release_upload.sh b/scripts/build_release_upload.sh
deleted file mode 100644
index f1b4fc1d50..0000000000
--- a/scripts/build_release_upload.sh
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/env bash
-# S3_PREFIX_BUILDLOG= where upload build log (no trailing /)
-# AWS_EFS_MOUNT= NFS to mount for `aptly` persistent state and scratch storage
-
-. ${HOME}/build_env
-set -e
-set -x
-
-# persistent storage of repo manager scratch space is on EFS
-if [ ! -z "${AWS_EFS_MOUNT}" ]; then
- if mount|grep -q /data; then
- echo /data already mounted
- else
- sudo mkdir -p /data
- sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport "${AWS_EFS_MOUNT}":/ /data
- # make environment for release_deb.sh
- sudo mkdir -p /data/_aptly
- sudo chown -R ${USER} /data/_aptly
- export APTLY_DIR=/data/_aptly
- fi
-fi
-
-cd ${PKG_ROOT}
-
-if [ ! -z "${S3_PREFIX}" ]; then
- aws s3 sync --quiet --exclude dev\* --exclude master\* --exclude nightly\* --exclude stable\* --acl public-read ./ ${S3_PREFIX}/${CHANNEL}/${RSTAMP}_${FULLVERSION}/
-fi
-
-# copy .rpm file to intermediate yum repo scratch space, actual publish manually later
-if [ ! -d /data/yumrepo ]; then
- sudo mkdir -p /data/yumrepo
- sudo chown ${USER} /data/yumrepo
-fi
-cp -p -n *.rpm *.rpm.sig /data/yumrepo
-
-cd ${HOME}
-STATUSFILE=build_status_${CHANNEL}_${FULLVERSION}
-echo "ami-id:" > "${STATUSFILE}"
-curl --silent http://169.254.169.254/latest/meta-data/ami-id >> "${STATUSFILE}"
-cat <>"${STATUSFILE}"
-
-
-go version:
-EOF
-go version >>"${STATUSFILE}"
-cat <>"${STATUSFILE}"
-
-go env:
-EOF
-go env >>"${STATUSFILE}"
-cat <>"${STATUSFILE}"
-
-build_env:
-EOF
-cat <${HOME}/build_env>>"${STATUSFILE}"
-cat <>"${STATUSFILE}"
-
-dpkg-l:
-EOF
-dpkg -l >>"${STATUSFILE}"
-gpg --clearsign "${STATUSFILE}"
-gzip "${STATUSFILE}.asc"
-if [ ! -z "${S3_PREFIX_BUILDLOG}" ]; then
- aws s3 cp --quiet "${STATUSFILE}.asc.gz" "${S3_PREFIX_BUILDLOG}/${RSTAMP}/${STATUSFILE}.asc.gz"
-fi
-
-date "+build_release done uploading %Y%m%d_%H%M%S"
-
-# NEXT: release_deb.sh
diff --git a/scripts/build_rpm.sh b/scripts/build_rpm.sh
deleted file mode 100755
index 1e897029c6..0000000000
--- a/scripts/build_rpm.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/bash -e
-
-# build_rpm.sh - Build a .deb package for one platform.
-#
-# Syntax: build_rpm.sh