Skip to content

Commit d7a6743

Browse files
authored
Merge branch 'master' into jordan/6485-epoch-boundary-index
2 parents 12f0668 + 77a2863 commit d7a6743

File tree

218 files changed

+5756
-9650
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

218 files changed

+5756
-9650
lines changed

LicensingApproach.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Flow's Approach to Licensing
2+
3+
The founding team for Flow suggests that all open-source software built on or for Flow should adhere to the "[Coherent Open Source Licensing](https://licenseuse.org)" philosophy.
4+
To that end, we encourage the use of one of the following three licenses, as applicable by the use case (order from most permissive, to most restrictive):
5+
6+
- Apache 2.0
7+
- LGPL 3
8+
- Affero GPL 3
9+
10+
These licenses are all approved by both the Free Software Foundation and the Open Source Initiative and contain clauses regarding software patenting to avoid hidden patent concerns. Additionally, they are all compatible with each other meaning there is no conflict using them together in any project (provided the project as a whole meets the requirements of the most restrictive of the licenses included).
11+
12+
13+
### Apache 2.0
14+
15+
Apache 2.0 is the most permissive, and allows reuse - with customization - in proprietary software. We recommend that this should be the default for any code that has significant potential use for off-chain tools and/or applications. In particular, all sample code (including smart contracts), SDKs, utility libraries and tools should default to Apache 2.0.
16+
17+
18+
### LGPL 3
19+
20+
LGPL 3 allows use in proprietary software, provided that any customizations to the licensed code are shared. We considered LGPL for Cadence to avoid a proprietary fork of the language, but decided to use the more permissive Apache 2.0 license to emphasize that we hope Cadence can be adopted outside of Flow. LGPL can be used for other parts of Flow where necessary (e.g. if the component is itself a modification of other LGPL-licensed code).
21+
22+
23+
### Affero GPL 3
24+
25+
Affero GPL 3 (AGPL) should be used for all code that exists primarily to power node software. In particular, the core consensus and computation layers should be provided via AGPL where possible. We chose this license because we interpret the clauses in the AGPL regarding "public use [...] on a publicly accessible server" as covering the operation of a node in the public Flow network. By requiring all modifications to the core node software to be made publicly available, we increase the security of the network (allowing any custom modifications to undergo public scrutiny), while also ensuring that improvements to the core infrastructure benefit all participants in the network.
26+
27+
28+
### Using the Unlicense
29+
30+
For small snippets of sample code, we can provide access via the Unlicense.
31+
Broadly speaking, Apache 2.0 gives essentially the same rights to the receiver of the code as Unlicense, except that Apache protects the author(s) a bit more robustly, and protects the receiver against patent lawsuits. But, some people aren't aware of this, and using the "Unlicense" makes it very clear to anyone that the original authors aren't claiming ownership of derivative works. For any "complex" code that we want to be free, we should use Apache. For simple code snippets and examples, the Unlicense will probably make casual/inexperienced developers feel more comfortable.

admin/command_runner.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,3 +324,7 @@ func (r *CommandRunner) runCommand(ctx context.Context, command string, data int
324324

325325
return handleResult, nil
326326
}
327+
328+
func (r *CommandRunner) GrpcAddress() string {
329+
return r.grpcAddress
330+
}

cmd/access/node_builder/access_node_builder.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -236,14 +236,7 @@ func (builder *FlowAccessNodeBuilder) buildFollowerState() *FlowAccessNodeBuilde
236236
return fmt.Errorf("only implementations of type badger.State are currently supported but read-only state has type %T", node.State)
237237
}
238238

239-
followerState, err := badgerState.NewFollowerState(
240-
state,
241-
node.Storage.Index,
242-
node.Storage.Payloads,
243-
node.Tracer,
244-
node.ProtocolEvents,
245-
blocktimer.DefaultBlockTimer,
246-
)
239+
followerState, err := badgerState.NewFollowerState(state, node.Storage.Index, node.Storage.Payloads, node.Tracer, node.ProtocolEvents, blocktimer.DefaultBlockTimer)
247240
builder.FollowerState = followerState
248241

249242
return err

cmd/bootstrap/cmd/qc.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ func constructRootQC(block *flow.Block, votes []*model.Vote, allNodes, internalN
2020
log.Fatal().Err(err).Msg("failed to generate QC participant data")
2121
}
2222

23-
qc, err := run.GenerateRootQC(block, votes, participantData, identities)
23+
qc, invalidVotesErr, err := run.GenerateRootQC(block, votes, participantData, identities)
24+
if len(invalidVotesErr) > 0 {
25+
for _, err := range invalidVotesErr {
26+
log.Warn().Err(err).Msg("invalid vote")
27+
}
28+
}
29+
2430
if err != nil {
2531
log.Fatal().Err(err).Msg("generating root QC failed")
2632
}

cmd/bootstrap/run/qc.go

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,18 @@ func (pd *ParticipantData) Identities() flow.IdentityList {
4444
// which assumes that only consensus participants construct QCs, which also have produce votes.
4545
//
4646
// TODO: modularize QC construction code (and code to verify QC) to be instantiated without needing private keys.
47-
func GenerateRootQC(block *flow.Block, votes []*model.Vote, participantData *ParticipantData, identities flow.IdentityList) (*flow.QuorumCertificate, error) {
47+
// It returns (qc, nil, nil) if a QC can be constructed with enough votes, and there is no invalid votes
48+
// It returns (qc, invalidVotes, nil) if there are some invalid votes, but a QC can still be constructed
49+
// It returns (nil, invalidVotes, err) if no qc can be constructed with not enough votes or running any any exception
50+
func GenerateRootQC(block *flow.Block, votes []*model.Vote, participantData *ParticipantData, identities flow.IdentityList) (
51+
*flow.QuorumCertificate, // the constructed QC
52+
[]error, // return invalid votes error
53+
error, // exception or could not construct qc
54+
) {
4855
// create consensus committee's state
4956
committee, err := committees.NewStaticCommittee(identities, flow.Identifier{}, participantData.Lookup, participantData.GroupKey)
5057
if err != nil {
51-
return nil, err
58+
return nil, nil, err
5259
}
5360

5461
// STEP 1: create VoteProcessor
@@ -58,34 +65,44 @@ func GenerateRootQC(block *flow.Block, votes []*model.Vote, participantData *Par
5865
createdQC = qc
5966
})
6067
if err != nil {
61-
return nil, fmt.Errorf("could not CombinedVoteProcessor processor: %w", err)
68+
return nil, nil, fmt.Errorf("could not CombinedVoteProcessor processor: %w", err)
6269
}
6370

71+
invalidVotes := make([]error, 0, len(votes))
6472
// STEP 2: feed the votes into the vote processor to create QC
6573
for _, vote := range votes {
6674
err := processor.Process(vote)
75+
76+
// in case there are invalid votes, we continue process more votes,
77+
// so that finalizing block won't be interrupted by any invalid vote.
78+
// if no enough votes are collected, finalize will fail and exit anyway, because
79+
// no QC will be built.
6780
if err != nil {
68-
return nil, fmt.Errorf("fail to process vote %v for block %v from signer %v: %w",
81+
if model.IsInvalidVoteError(err) {
82+
invalidVotes = append(invalidVotes, err)
83+
continue
84+
}
85+
return nil, invalidVotes, fmt.Errorf("fail to process vote %v for block %v from signer %v: %w",
6986
vote.ID(),
70-
block.ID(),
87+
vote.BlockID,
7188
vote.SignerID,
7289
err)
7390
}
7491
}
7592

7693
if createdQC == nil {
77-
return nil, fmt.Errorf("QC is not created, total number of votes %v, expect to have 2/3 votes of %v participants",
94+
return nil, invalidVotes, fmt.Errorf("QC is not created, total number of votes %v, expect to have 2/3 votes of %v participants",
7895
len(votes), len(identities))
7996
}
8097

8198
// STEP 3: validate constructed QC
8299
val, err := createValidator(committee)
83100
if err != nil {
84-
return nil, err
101+
return nil, invalidVotes, err
85102
}
86103
err = val.ValidateQC(createdQC)
87104

88-
return createdQC, err
105+
return createdQC, invalidVotes, err
89106
}
90107

91108
// GenerateRootBlockVotes generates votes for root block based on participantData

cmd/bootstrap/run/qc_test.go

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,31 @@ import (
1717
func TestGenerateRootQC(t *testing.T) {
1818
participantData := createSignerData(t, 3)
1919

20-
block := unittest.BlockFixture()
21-
block.Payload.Guarantees = nil
22-
block.Payload.Seals = nil
23-
block.Header.Height = 0
24-
block.Header.ParentID = flow.ZeroID
25-
block.Header.View = 3
26-
block.Header.PayloadHash = block.Payload.Hash()
27-
28-
votes, err := GenerateRootBlockVotes(&block, participantData)
20+
block := unittest.GenesisFixture()
21+
22+
votes, err := GenerateRootBlockVotes(block, participantData)
23+
require.NoError(t, err)
24+
25+
_, invalid, err := GenerateRootQC(block, votes, participantData, participantData.Identities())
2926
require.NoError(t, err)
27+
require.Len(t, invalid, 0) // no invalid votes
28+
}
29+
30+
func TestGenerateRootQCWithSomeInvalidVotes(t *testing.T) {
31+
participantData := createSignerData(t, 10)
32+
33+
block := unittest.GenesisFixture()
34+
35+
votes, err := GenerateRootBlockVotes(block, participantData)
36+
require.NoError(t, err)
37+
38+
// make 2 votes invalid
39+
votes[0].SigData = unittest.SignatureFixture() // make invalid signature
40+
votes[1].SignerID = unittest.IdentifierFixture() // make invalid signer
3041

31-
_, err = GenerateRootQC(&block, votes, participantData, participantData.Identities())
42+
_, invalid, err := GenerateRootQC(block, votes, participantData, participantData.Identities())
3243
require.NoError(t, err)
44+
require.Len(t, invalid, 2) // 2 invalid votes
3345
}
3446

3547
func createSignerData(t *testing.T, n int) *ParticipantData {

cmd/collection/main.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,7 @@ func main() {
180180
if !ok {
181181
return fmt.Errorf("only implementations of type badger.State are currently supported but read-only state has type %T", node.State)
182182
}
183-
followerState, err = badgerState.NewFollowerState(
184-
state,
185-
node.Storage.Index,
186-
node.Storage.Payloads,
187-
node.Tracer,
188-
node.ProtocolEvents,
189-
blocktimer.DefaultBlockTimer,
190-
)
183+
followerState, err = badgerState.NewFollowerState(state, node.Storage.Index, node.Storage.Payloads, node.Tracer, node.ProtocolEvents, blocktimer.DefaultBlockTimer)
191184
return err
192185
}).
193186
Module("transactions mempool", func(node *cmd.NodeConfig) error {

cmd/consensus/main.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -241,15 +241,7 @@ func main() {
241241
return err
242242
}
243243

244-
mutableState, err = badgerState.NewFullConsensusState(
245-
state,
246-
node.Storage.Index,
247-
node.Storage.Payloads,
248-
node.Tracer,
249-
node.ProtocolEvents,
250-
blockTimer,
251-
receiptValidator,
252-
sealValidator)
244+
mutableState, err = badgerState.NewFullConsensusState(state, node.Storage.Index, node.Storage.Payloads, node.Tracer, node.ProtocolEvents, blockTimer, receiptValidator, sealValidator)
253245
return err
254246
}).
255247
Module("random beacon key", func(node *cmd.NodeConfig) error {

cmd/execution_builder.go

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import (
5151
"github.com/onflow/flow-go/engine/execution/state/bootstrap"
5252
"github.com/onflow/flow-go/engine/execution/state/delta"
5353
"github.com/onflow/flow-go/fvm"
54+
fvmState "github.com/onflow/flow-go/fvm/state"
5455
"github.com/onflow/flow-go/fvm/systemcontracts"
5556
"github.com/onflow/flow-go/ledger/common/pathfinder"
5657
ledger "github.com/onflow/flow-go/ledger/complete"
@@ -219,14 +220,7 @@ func (exeNode *ExecutionNode) LoadMutableFollowerState(node *NodeConfig) error {
219220
return fmt.Errorf("only implementations of type badger.State are currently supported but read-only state has type %T", node.State)
220221
}
221222
var err error
222-
exeNode.followerState, err = badgerState.NewFollowerState(
223-
bState,
224-
node.Storage.Index,
225-
node.Storage.Payloads,
226-
node.Tracer,
227-
node.ProtocolEvents,
228-
blocktimer.DefaultBlockTimer,
229-
)
223+
exeNode.followerState, err = badgerState.NewFollowerState(bState, node.Storage.Index, node.Storage.Payloads, node.Tracer, node.ProtocolEvents, blocktimer.DefaultBlockTimer)
230224
return err
231225
}
232226

@@ -519,16 +513,26 @@ func (exeNode *ExecutionNode) LoadProviderEngine(
519513
ctx := context.Background()
520514
_, blockID, err := exeNode.executionState.GetHighestExecutedBlockID(ctx)
521515
if err != nil {
522-
return nil, fmt.Errorf("cannot get the latest executed block id: %w", err)
516+
return nil, fmt.Errorf(
517+
"cannot get the latest executed block id: %w",
518+
err)
523519
}
524-
stateCommit, err := exeNode.executionState.StateCommitmentByBlockID(ctx, blockID)
520+
stateCommit, err := exeNode.executionState.StateCommitmentByBlockID(
521+
ctx,
522+
blockID)
525523
if err != nil {
526-
return nil, fmt.Errorf("cannot get the state commitment at latest executed block id %s: %w", blockID.String(), err)
524+
return nil, fmt.Errorf(
525+
"cannot get the state commitment at latest executed block id %s: %w",
526+
blockID.String(),
527+
err)
527528
}
528-
blockView := exeNode.executionState.NewView(stateCommit)
529+
blockSnapshot := exeNode.executionState.NewStorageSnapshot(stateCommit)
529530

530531
// Get the epoch counter from the smart contract at the last executed block.
531-
contractEpochCounter, err := getContractEpochCounter(exeNode.computationManager.VM(), vmCtx, blockView)
532+
contractEpochCounter, err := getContractEpochCounter(
533+
exeNode.computationManager.VM(),
534+
vmCtx,
535+
blockSnapshot)
532536
// Failing to fetch the epoch counter from the smart contract is a fatal error.
533537
if err != nil {
534538
return nil, fmt.Errorf("cannot get epoch counter from the smart contract at block %s: %w", blockID.String(), err)
@@ -1076,8 +1080,16 @@ func (exeNode *ExecutionNode) LoadBootstrapper(node *NodeConfig) error {
10761080
return nil
10771081
}
10781082

1079-
// getContractEpochCounter Gets the epoch counters from the FlowEpoch smart contract from the view provided.
1080-
func getContractEpochCounter(vm fvm.VM, vmCtx fvm.Context, view *delta.View) (uint64, error) {
1083+
// getContractEpochCounter Gets the epoch counters from the FlowEpoch smart
1084+
// contract from the snapshot provided.
1085+
func getContractEpochCounter(
1086+
vm fvm.VM,
1087+
vmCtx fvm.Context,
1088+
snapshot fvmState.StorageSnapshot,
1089+
) (
1090+
uint64,
1091+
error,
1092+
) {
10811093
// Get the address of the FlowEpoch smart contract
10821094
sc, err := systemcontracts.SystemContractsForChain(vmCtx.Chain.ChainID())
10831095
if err != nil {
@@ -1092,7 +1104,7 @@ func getContractEpochCounter(vm fvm.VM, vmCtx fvm.Context, view *delta.View) (ui
10921104
script := fvm.Script(scriptCode)
10931105

10941106
// execute the script
1095-
err = vm.Run(vmCtx, script, view)
1107+
err = vm.Run(vmCtx, script, delta.NewDeltaView(snapshot))
10961108
if err != nil {
10971109
return 0, fmt.Errorf("could not read epoch counter, internal error while executing script: %w", err)
10981110
}

cmd/observer/node_builder/observer_builder.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -268,14 +268,7 @@ func (builder *ObserverServiceBuilder) buildFollowerState() *ObserverServiceBuil
268268
return fmt.Errorf("only implementations of type badger.State are currently supported but read-only state has type %T", node.State)
269269
}
270270

271-
followerState, err := badgerState.NewFollowerState(
272-
state,
273-
node.Storage.Index,
274-
node.Storage.Payloads,
275-
node.Tracer,
276-
node.ProtocolEvents,
277-
blocktimer.DefaultBlockTimer,
278-
)
271+
followerState, err := badgerState.NewFollowerState(state, node.Storage.Index, node.Storage.Payloads, node.Tracer, node.ProtocolEvents, blocktimer.DefaultBlockTimer)
279272
builder.FollowerState = followerState
280273

281274
return err

cmd/scaffold.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,7 @@ func (fnb *FlowNodeBuilder) initStorage() error {
928928
index := bstorage.NewIndex(fnb.Metrics.Cache, fnb.DB)
929929
payloads := bstorage.NewPayloads(fnb.DB, index, guarantees, seals, receipts, results)
930930
blocks := bstorage.NewBlocks(fnb.DB, headers, payloads)
931+
qcs := bstorage.NewQuorumCertificates(fnb.Metrics.Cache, fnb.DB, bstorage.DefaultCacheSize)
931932
transactions := bstorage.NewTransactions(fnb.Metrics.Cache, fnb.DB)
932933
collections := bstorage.NewCollections(fnb.DB, transactions)
933934
setups := bstorage.NewEpochSetups(fnb.Metrics.Cache, fnb.DB)
@@ -936,20 +937,21 @@ func (fnb *FlowNodeBuilder) initStorage() error {
936937
commits := bstorage.NewCommits(fnb.Metrics.Cache, fnb.DB)
937938

938939
fnb.Storage = Storage{
939-
Headers: headers,
940-
Guarantees: guarantees,
941-
Receipts: receipts,
942-
Results: results,
943-
Seals: seals,
944-
Index: index,
945-
Payloads: payloads,
946-
Blocks: blocks,
947-
Transactions: transactions,
948-
Collections: collections,
949-
Setups: setups,
950-
EpochCommits: epochCommits,
951-
Statuses: statuses,
952-
Commits: commits,
940+
Headers: headers,
941+
Guarantees: guarantees,
942+
Receipts: receipts,
943+
Results: results,
944+
Seals: seals,
945+
Index: index,
946+
Payloads: payloads,
947+
Blocks: blocks,
948+
QuorumCertificates: qcs,
949+
Transactions: transactions,
950+
Collections: collections,
951+
Setups: setups,
952+
EpochCommits: epochCommits,
953+
Statuses: statuses,
954+
Commits: commits,
953955
}
954956

955957
return nil
@@ -1008,6 +1010,7 @@ func (fnb *FlowNodeBuilder) initState() error {
10081010
fnb.Storage.Seals,
10091011
fnb.Storage.Results,
10101012
fnb.Storage.Blocks,
1013+
fnb.Storage.QuorumCertificates,
10111014
fnb.Storage.Setups,
10121015
fnb.Storage.EpochCommits,
10131016
fnb.Storage.Statuses,
@@ -1058,6 +1061,7 @@ func (fnb *FlowNodeBuilder) initState() error {
10581061
fnb.Storage.Seals,
10591062
fnb.Storage.Results,
10601063
fnb.Storage.Blocks,
1064+
fnb.Storage.QuorumCertificates,
10611065
fnb.Storage.Setups,
10621066
fnb.Storage.EpochCommits,
10631067
fnb.Storage.Statuses,

0 commit comments

Comments
 (0)