github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/blueprints/epochs.go (about) 1 package blueprints 2 3 import ( 4 _ "embed" 5 "encoding/hex" 6 "fmt" 7 8 "github.com/onflow/cadence" 9 jsoncdc "github.com/onflow/cadence/encoding/json" 10 11 "github.com/onflow/flow-core-contracts/lib/go/templates" 12 13 flowsdk "github.com/onflow/flow-go-sdk" 14 sdktemplates "github.com/onflow/flow-go-sdk/templates" 15 16 "github.com/onflow/flow-go/model/bootstrap" 17 "github.com/onflow/flow-go/model/flow" 18 "github.com/onflow/flow-go/module/epochs" 19 ) 20 21 //go:embed scripts/deployIDTableStakingTransactionTemplate.cdc 22 var deployIDTableStakingTransactionTemplate string 23 24 //go:embed scripts/deployEpochTransactionTemplate.cdc 25 var deployEpochTransactionTemplate string 26 27 //go:embed scripts/setupAccountTemplate.cdc 28 var setupAccountTemplate string 29 30 //go:embed scripts/fundAccountTemplate.cdc 31 var fundAccountTemplate string 32 33 //go:embed scripts/deployLockedTokensTemplate.cdc 34 var deployLockedTokensTemplate string 35 36 // DeployEpochTransaction returns the transaction body for the deploy epoch transaction 37 func DeployEpochTransaction(service flow.Address, contract []byte, epochConfig epochs.EpochConfig) *flow.TransactionBody { 38 return flow.NewTransactionBody(). 39 SetScript([]byte( 40 templates.ReplaceAddresses( 41 deployEpochTransactionTemplate, 42 templates.Environment{ 43 QuorumCertificateAddress: service.Hex(), 44 }, 45 ), 46 )). 47 AddArgument(jsoncdc.MustEncode(cadence.String("FlowEpoch"))). 48 AddArgument(jsoncdc.MustEncode(cadence.String(hex.EncodeToString(contract)))). 49 AddArgument(jsoncdc.MustEncode(epochConfig.CurrentEpochCounter)). 50 AddArgument(jsoncdc.MustEncode(epochConfig.NumViewsInEpoch)). 51 AddArgument(jsoncdc.MustEncode(epochConfig.NumViewsInStakingAuction)). 52 AddArgument(jsoncdc.MustEncode(epochConfig.NumViewsInDKGPhase)). 53 AddArgument(jsoncdc.MustEncode(epochConfig.NumCollectorClusters)). 54 AddArgument(jsoncdc.MustEncode(epochConfig.FLOWsupplyIncreasePercentage)). 55 AddArgument(jsoncdc.MustEncode(epochConfig.RandomSource)). 56 AddArgument(epochs.EncodeClusterAssignments(epochConfig.CollectorClusters)). 57 AddAuthorizer(service) 58 } 59 60 // SetupAccountTransaction returns the transaction body for the setup account transaction 61 func SetupAccountTransaction( 62 fungibleToken flow.Address, 63 flowToken flow.Address, 64 accountAddress flow.Address, 65 ) *flow.TransactionBody { 66 return flow.NewTransactionBody(). 67 SetScript([]byte( 68 templates.ReplaceAddresses( 69 setupAccountTemplate, 70 templates.Environment{ 71 FungibleTokenAddress: fungibleToken.Hex(), 72 FlowTokenAddress: flowToken.Hex(), 73 }, 74 ), 75 )). 76 AddAuthorizer(accountAddress) 77 } 78 79 // DeployIDTableStakingTransaction returns the transaction body for the deploy id table staking transaction 80 func DeployIDTableStakingTransaction(service flow.Address, contract []byte, epochTokenPayout cadence.UFix64, rewardCut cadence.UFix64) *flow.TransactionBody { 81 return flow.NewTransactionBody(). 82 SetScript([]byte(deployIDTableStakingTransactionTemplate)). 83 AddArgument(jsoncdc.MustEncode(cadence.String(hex.EncodeToString(contract)))). 84 AddArgument(jsoncdc.MustEncode(epochTokenPayout)). 85 AddArgument(jsoncdc.MustEncode(rewardCut)). 86 AddAuthorizer(service) 87 } 88 89 // FundAccountTransaction returns the transaction body for the fund account transaction 90 func FundAccountTransaction( 91 service flow.Address, 92 fungibleToken flow.Address, 93 flowToken flow.Address, 94 nodeAddress flow.Address, 95 ) *flow.TransactionBody { 96 97 cdcAmount, err := cadence.NewUFix64(fmt.Sprintf("%d.0", 2_000_000)) 98 if err != nil { 99 panic(err) 100 } 101 102 return flow.NewTransactionBody(). 103 SetScript([]byte(templates.ReplaceAddresses( 104 fundAccountTemplate, 105 templates.Environment{ 106 FungibleTokenAddress: fungibleToken.Hex(), 107 FlowTokenAddress: flowToken.Hex(), 108 }, 109 ))). 110 AddArgument(jsoncdc.MustEncode(cdcAmount)). 111 AddArgument(jsoncdc.MustEncode(cadence.NewAddress(nodeAddress))). 112 AddAuthorizer(service) 113 } 114 115 // DeployLockedTokensTransaction returns the transaction body for the deploy locked tokens transaction 116 func DeployLockedTokensTransaction(service flow.Address, contract []byte, publicKeys []cadence.Value) *flow.TransactionBody { 117 return flow.NewTransactionBody(). 118 SetScript([]byte( 119 deployLockedTokensTemplate, 120 )). 121 AddArgument(jsoncdc.MustEncode(cadence.NewArray(publicKeys))). 122 AddArgument(jsoncdc.MustEncode(cadence.String(hex.EncodeToString(contract)))). 123 AddAuthorizer(service) 124 } 125 126 // RegisterNodeTransaction creates a new node struct object. 127 // Then, if the node is a collector node, creates a new account and adds a QC object to it 128 // If the node is a consensus node, it creates a new account and adds a DKG object to it 129 func RegisterNodeTransaction( 130 service flow.Address, 131 flowTokenAddress flow.Address, 132 fungibleTokenAddress flow.Address, 133 nodeAddress flow.Address, 134 id *flow.Identity, 135 ) *flow.TransactionBody { 136 137 env := templates.Environment{ 138 FlowTokenAddress: flowTokenAddress.HexWithPrefix(), 139 FungibleTokenAddress: fungibleTokenAddress.HexWithPrefix(), 140 IDTableAddress: service.HexWithPrefix(), 141 QuorumCertificateAddress: service.HexWithPrefix(), 142 DkgAddress: service.HexWithPrefix(), 143 EpochAddress: service.HexWithPrefix(), 144 } 145 146 // Use NetworkingKey as the public key of the machine account. 147 // We do this for tests/localnet but normally it should be a separate key. 148 accountKey := &flowsdk.AccountKey{ 149 PublicKey: id.NetworkPubKey, 150 SigAlgo: id.NetworkPubKey.Algorithm(), 151 HashAlgo: bootstrap.DefaultMachineAccountHashAlgo, 152 Weight: 1000, 153 } 154 155 cadenceCryptoKey, err := sdktemplates.AccountKeyToCadenceCryptoKey(accountKey) 156 if err != nil { 157 panic(err) 158 } 159 160 cadencePublicKeys := cadence.NewArray( 161 []cadence.Value{ 162 cadenceCryptoKey, 163 }, 164 ) 165 166 cdcAmount, err := cadence.NewUFix64("1250000.0") 167 if err != nil { 168 panic(err) 169 } 170 171 cdcNodeID, err := cadence.NewString(id.NodeID.String()) 172 if err != nil { 173 panic(err) 174 } 175 176 cdcAddress, err := cadence.NewString(id.Address) 177 if err != nil { 178 panic(err) 179 } 180 181 cdcNetworkPubKey, err := cadence.NewString(id.NetworkPubKey.String()[2:]) 182 if err != nil { 183 panic(err) 184 } 185 186 cdcStakingPubKey, err := cadence.NewString(id.StakingPubKey.String()[2:]) 187 if err != nil { 188 panic(err) 189 } 190 191 // register node 192 return flow.NewTransactionBody(). 193 SetScript(templates.GenerateEpochRegisterNodeScript(env)). 194 AddArgument(jsoncdc.MustEncode(cdcNodeID)). 195 AddArgument(jsoncdc.MustEncode(cadence.NewUInt8(uint8(id.Role)))). 196 AddArgument(jsoncdc.MustEncode(cdcAddress)). 197 AddArgument(jsoncdc.MustEncode(cdcNetworkPubKey)). 198 AddArgument(jsoncdc.MustEncode(cdcStakingPubKey)). 199 AddArgument(jsoncdc.MustEncode(cdcAmount)). 200 AddArgument(jsoncdc.MustEncode(cadencePublicKeys)). 201 AddAuthorizer(nodeAddress) 202 } 203 204 // SetStakingAllowlistTransaction returns transaction body for set staking allowlist transaction 205 func SetStakingAllowlistTransaction(idTableStakingAddr flow.Address, allowedNodeIDs []flow.Identifier) *flow.TransactionBody { 206 env := templates.Environment{ 207 IDTableAddress: idTableStakingAddr.HexWithPrefix(), 208 } 209 allowedNodesArg := SetStakingAllowlistTxArg(allowedNodeIDs) 210 return flow.NewTransactionBody(). 211 SetScript(templates.GenerateSetApprovedNodesScript(env)). 212 AddArgument(jsoncdc.MustEncode(allowedNodesArg)). 213 AddAuthorizer(idTableStakingAddr) 214 } 215 216 // SetStakingAllowlistTxArg returns the transaction argument for setting the staking allow-list. 217 func SetStakingAllowlistTxArg(allowedNodeIDs []flow.Identifier) cadence.Value { 218 cdcDictEntries := make([]cadence.KeyValuePair, 0, len(allowedNodeIDs)) 219 for _, id := range allowedNodeIDs { 220 cdcNodeID, err := cadence.NewString(id.String()) 221 if err != nil { 222 panic(err) 223 } 224 kvPair := cadence.KeyValuePair{ 225 Key: cdcNodeID, 226 Value: cadence.NewBool(true), 227 } 228 cdcDictEntries = append(cdcDictEntries, kvPair) 229 } 230 return cadence.NewDictionary(cdcDictEntries) 231 } 232 233 // BytesToCadenceArray converts byte slice to cadence array 234 func BytesToCadenceArray(b []byte) cadence.Array { 235 values := make([]cadence.Value, len(b)) 236 for i, v := range b { 237 values[i] = cadence.NewUInt8(v) 238 } 239 return cadence.NewArray(values) 240 }