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  }