-
Notifications
You must be signed in to change notification settings - Fork 179
/
cluster.go
74 lines (59 loc) · 2.25 KB
/
cluster.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package unittest
import (
"fmt"
"sort"
"github.com/onflow/flow-go/model/flow"
"github.com/onflow/flow-go/model/flow/filter"
"github.com/onflow/flow-go/model/flow/order"
)
// TransactionForCluster generates a transaction that will be assigned to the
// target cluster ID.
func TransactionForCluster(clusters flow.ClusterList, target flow.IdentityList) flow.TransactionBody {
tx := TransactionBodyFixture()
return AlterTransactionForCluster(tx, clusters, target, func(*flow.TransactionBody) {})
}
// AlterTransactionForCluster modifies a transaction nonce until it is assigned
// to the target cluster.
//
// The `after` function is run after each modification to allow for any content
// dependent changes to the transaction (eg. signing it).
func AlterTransactionForCluster(tx flow.TransactionBody, clusters flow.ClusterList, target flow.IdentityList, after func(tx *flow.TransactionBody)) flow.TransactionBody {
// Bound to avoid infinite loop in case the routing algorithm is broken
for i := 0; i < 10000; i++ {
tx.Script = append(tx.Script, '/', '/')
if after != nil {
after(&tx)
}
routed, ok := clusters.ByTxID(tx.ID())
if !ok {
panic(fmt.Sprintf("unable to find cluster by txID: %x", tx.ID()))
}
if routed.Fingerprint() == target.Fingerprint() {
return tx
}
}
panic(fmt.Sprintf("unable to find transaction for target (%x) with %d clusters", target, len(clusters)))
}
// ClusterAssignment creates an assignment list with n clusters and with nodes
// evenly distributed among clusters.
func ClusterAssignment(n uint, nodes flow.IdentityList) flow.AssignmentList {
collectors := nodes.Filter(filter.HasRole(flow.RoleCollection))
// order, so the same list results in the same
sort.Slice(collectors, func(i, j int) bool {
return order.ByNodeIDAsc(collectors[i], collectors[j])
})
assignments := make(flow.AssignmentList, n)
for i, collector := range collectors {
index := uint(i) % n
assignments[index] = append(assignments[index], collector.NodeID)
}
return assignments
}
func ClusterList(n uint, nodes flow.IdentityList) flow.ClusterList {
assignments := ClusterAssignment(n, nodes)
clusters, err := flow.NewClusterList(assignments, nodes.Filter(filter.HasRole(flow.RoleCollection)))
if err != nil {
panic(err)
}
return clusters
}