From 49a20e4b39e012e5c9c71fa3d7c10218c5216bf0 Mon Sep 17 00:00:00 2001 From: Pierre Seznec Date: Wed, 18 Oct 2023 11:37:33 +0200 Subject: [PATCH] compute network specific storage costs --- int/api/server.go | 1 - int/config/config_network.yaml | 4 +- int/config/network.go | 8 ++- pkg/convert/byteConverter.go | 7 ++- pkg/node/sendoperation/sendoperation.go | 52 ++++++++++++---- pkg/onchain/website/uploader.go | 81 ++++++++++++++++++------- 6 files changed, 111 insertions(+), 42 deletions(-) diff --git a/int/api/server.go b/int/api/server.go index 5c80a8156..95aea2542 100644 --- a/int/api/server.go +++ b/int/api/server.go @@ -98,7 +98,6 @@ func NewServer(flags StartServerFlags) *Server { // Starts the server. // This function starts the server in a new goroutine to avoid blocking the main thread. func (server *Server) Start(networkManager *config.NetworkManager, pluginManager *plugin.Manager) { - initLocalAPI(server.localAPI, networkManager, pluginManager) server.api.ConfigureMassaStationAPI(*networkManager.Network(), server.shutdown) diff --git a/int/config/config_network.yaml b/int/config/config_network.yaml index fe378260a..5d056aafe 100644 --- a/int/config/config_network.yaml +++ b/int/config/config_network.yaml @@ -1,12 +1,12 @@ testnet: DNS: AS12MGDGVB3xNDqzGidJM5fcAbjF1ZP5XAecm5ww4RU7sfQd4cMKk URLs: - - https://test.massa.net/api/v2 + - http://81.49.155.238:33035 buildnet: DNS: AS1pzpVk79cubdM7Zk9pNdg1JR4qKooVa6usyquiCEQhPeRWD9k7 URLs: - - https://buildnet.massa.net/api/v2 + - https://buildnet.massa.net/api/v2 Default: true labnet: diff --git a/int/config/network.go b/int/config/network.go index 4af73907d..88c0c2c09 100644 --- a/int/config/network.go +++ b/int/config/network.go @@ -78,11 +78,12 @@ func NewNetworkManager() (*NetworkManager, error) { return networkManager, nil } -func (n *NetworkManager) Version(nodeUrl string) (*string, error) { - client := node.NewClient(nodeUrl) +func (n *NetworkManager) Version(nodeURL string) (*string, error) { + client := node.NewClient(nodeURL) + status, err := node.Status(client) if err != nil { - return nil, fmt.Errorf("failed to retrive node status: %w", err) + return nil, fmt.Errorf("failed to retrieve node status: %w", err) } pattern := `.+\.(\d+\.\d+)` @@ -90,6 +91,7 @@ func (n *NetworkManager) Version(nodeUrl string) (*string, error) { re := regexp.MustCompile(pattern) matches := re.FindStringSubmatch(*status.Version) + //nolint:gomnd if len(matches) != 2 { return nil, fmt.Errorf("failed to parse node version from: %s", *status.Version) } diff --git a/pkg/convert/byteConverter.go b/pkg/convert/byteConverter.go index 30f67a307..e7a750933 100644 --- a/pkg/convert/byteConverter.go +++ b/pkg/convert/byteConverter.go @@ -7,7 +7,10 @@ import ( "unicode/utf16" ) -const BytesPerUint64 = 8 +const ( + BytesPerUint64 = 8 + BytesPerUint32 = 4 +) // Encode uint64 to byte array. func U64ToBytes(nb int) (bytes []byte) { @@ -18,8 +21,6 @@ func U64ToBytes(nb int) (bytes []byte) { return } -const BytesPerUint32 = 4 - // Encode uint32 to byte array. func U32ToBytes(nb int) (bytes []byte) { u32 := uint32(nb) diff --git a/pkg/node/sendoperation/sendoperation.go b/pkg/node/sendoperation/sendoperation.go index 49f36027c..dd131d7a6 100644 --- a/pkg/node/sendoperation/sendoperation.go +++ b/pkg/node/sendoperation/sendoperation.go @@ -6,6 +6,7 @@ import ( b64 "encoding/base64" "encoding/binary" "fmt" + "strconv" "strings" "github.com/massalabs/station/pkg/node" @@ -14,17 +15,12 @@ import ( ) const ( - DefaultGasLimit = 700_000_000 - DefaultExpiryInSlot = 3 - DefaultFee = 0 - // To be updated when storage costs reduction will be deployed (testnet 26?) - AccountCreationStorageCost = 10_000_000 - StorageCostPerByte = 1_000_000 - // Today, the cost of storage to create a new storagekey is fixed to 10*StorageCostPerByte - // This should be updated when key creation cost will be charged for actual size. - chargedBytesForKey = 10 - StorageKeyCreationCost = chargedBytesForKey * StorageCostPerByte - OneMassa = 1_000_000_000 + DefaultGasLimit = 700_000_000 + DefaultExpiryInSlot = 3 + DefaultFee = 0 + accountCreationStorageCost = 1_000_000 + StorageCostPerByte = 100_000 + OneMassa = 1_000_000_000 ) //nolint:tagliatelle @@ -223,3 +219,37 @@ func DecodeOperationID(data []byte) (uint64, error) { return opID, nil } + +func StorageCostForEntry(nodeVersion string, keyByteLengh, valueByteLenght int) (int, error) { + versionFloat, err := strconv.ParseFloat(nodeVersion, 64) + if err != nil { + return 0, fmt.Errorf("failed to parse nodeversion %s: %w", nodeVersion, err) + } + + //nolint:gomnd + if versionFloat < 26 { + lecagyStorageCost := 1_000_000 + // key bytes are charged at the fixed price of 10 bytes + //nolint:gomnd + return (valueByteLenght + 10) * lecagyStorageCost, nil + } + + return (valueByteLenght + keyByteLengh) * StorageCostPerByte, nil +} + +func AccountCreationStorageCost(nodeVersion string) (int, error) { + versionFloat, err := strconv.ParseFloat(nodeVersion, 64) + if err != nil { + return 0, fmt.Errorf("failed to parse nodeversion %s: %w", nodeVersion, err) + } + + //nolint:gomnd + if versionFloat < 26 { + // current version is lower than 0.26.0 + lecacyAccountCreationStorageCost := 10_000_000 + + return lecacyAccountCreationStorageCost, nil + } + + return accountCreationStorageCost, nil +} diff --git a/pkg/onchain/website/uploader.go b/pkg/onchain/website/uploader.go index f812db1b2..f6efe60f7 100644 --- a/pkg/onchain/website/uploader.go +++ b/pkg/onchain/website/uploader.go @@ -19,16 +19,20 @@ import ( //go:embed sc var content embed.FS -const blockLength = 260000 +const ( + blockLength = 260000 + nbChunkKey = "NB_CHUNKS" + ownerKey = "OWNER" +) //nolint:funlen func PrepareForUpload( - config config.NetworkInfos, + network config.NetworkInfos, url string, description string, nickname string, ) (string, string, error) { - client := node.NewClient(config.NodeURL) + client := node.NewClient(network.NodeURL) basePath := "sc/" @@ -44,9 +48,22 @@ func PrepareForUpload( // webSiteInitCost correspond to the cost of owner initialization //nolint:lll,gomnd - webSiteInitCost := sendOperation.StorageKeyCreationCost + 53 /*owner Addr max byteLenght*/ *sendOperation.StorageCostPerByte - deployCost := sendOperation.AccountCreationStorageCost + (len(websiteStorer) * sendOperation.StorageCostPerByte) - totalStorageCost := webSiteInitCost + deployCost + webSiteInitCost, err := sendOperation.StorageCostForEntry(network.Version, len([]byte(ownerKey)), 53 /*owner Addr max byteLenght*/) + if err != nil { + return "", "", fmt.Errorf("unable to compute storage cost for website init: %w", err) + } + + deployCost, err := sendOperation.StorageCostForEntry(network.Version, 0, len(websiteStorer)) + if err != nil { + return "", "", fmt.Errorf("unable to compute storage cost for website deployment: %w", err) + } + + accountCreationCost, err := sendOperation.AccountCreationStorageCost(network.Version) + if err != nil { + return "", "", fmt.Errorf("unable to compute storage cost for account creation: %w", err) + } + + totalStorageCost := webSiteInitCost + deployCost + accountCreationCost logger.Debug("Website deployment cost estimation: ", totalStorageCost) @@ -75,7 +92,7 @@ func PrepareForUpload( // Set DNS. _, err = dns.SetRecord( - config, + network, client, nickname, url, @@ -94,17 +111,15 @@ func PrepareForUpload( } func Upload( - config config.NetworkInfos, + network config.NetworkInfos, atAddress string, content []byte, nickname string, operationBatch sendOperation.OperationBatch, ) ([]string, error) { - client := node.NewClient(config.NodeURL) - blocks := chunk(content, blockLength) - operations, err := upload(client, atAddress, blocks, nickname, operationBatch) + operations, err := upload(network, atAddress, blocks, nickname, operationBatch) if err != nil { return nil, err } @@ -112,8 +127,9 @@ func Upload( return operations, nil } +//nolint:funlen func upload( - client *node.Client, + network config.NetworkInfos, addr string, chunks [][]byte, nickname string, @@ -122,6 +138,8 @@ func upload( nbChunks := len(chunks) operations := make([]string, nbChunks) + client := node.NewClient(network.NodeURL) + for chunkIndex := 0; chunkIndex < nbChunks; chunkIndex++ { chunkSize := len(chunks[chunkIndex]) // Chunk ID encoding @@ -133,12 +151,21 @@ func upload( // Chunk data encoding params = append(params, chunks[chunkIndex]...) - // Total cost is the cost for storage bytes plus a fixed cost for key creation - uploadCost := sendOperation.StorageKeyCreationCost + sendOperation.StorageCostPerByte*chunkSize + uploadCost, err := sendOperation.StorageCostForEntry(network.Version, convert.BytesPerUint32, chunkSize) + if err != nil { + return nil, fmt.Errorf("unable to compute storage cost chunk upload: %w", err) + } if chunkIndex == 0 { // if chunkID == 0, we need to add the cost of the key creation for the NB_CHUNKS key - chunkKeyCost := sendOperation.StorageKeyCreationCost + sendOperation.StorageCostPerByte*convert.BytesPerUint32 + chunkKeyCost, err := sendOperation.StorageCostForEntry( + network.Version, + len([]byte(nbChunkKey)), + convert.BytesPerUint32) + if err != nil { + return nil, fmt.Errorf("unable to compute storage cost for chunk key creation: %w", err) + } + uploadCost += chunkKeyCost } @@ -176,12 +203,10 @@ func UploadMissedChunks( missedChunks string, operationBatch sendOperation.OperationBatch, ) ([]string, error) { - client := node.NewClient(config.NodeURL) - blocks := chunk(content, blockLength) operations, err := uploadMissedChunks( - client, + config, atAddress, blocks, missedChunks, @@ -195,14 +220,17 @@ func UploadMissedChunks( return operations, nil } +//nolint:funlen func uploadMissedChunks( - client *node.Client, + network config.NetworkInfos, addr string, chunks [][]byte, missedChunks string, nickname string, operationBatch sendOperation.OperationBatch, ) ([]string, error) { + client := node.NewClient(network.NodeURL) + operations := make([]string, len(chunks)+1) arrMissedChunks := strings.Split(missedChunks, ",") @@ -223,12 +251,21 @@ func uploadMissedChunks( //nolint:ineffassign,nolintlint params = append(params, chunks[chunkID]...) - // Total cost is the cost for storage bytes plus a fixed cost for key creation - uploadCost := sendOperation.StorageKeyCreationCost + sendOperation.StorageCostPerByte*chunkSize + uploadCost, err := sendOperation.StorageCostForEntry(network.Version, convert.BytesPerUint32, chunkSize) + if err != nil { + return nil, fmt.Errorf("unable to compute storage cost for chunk upload: %w", err) + } if chunkID == 0 { // if chunkID == 0, we may need to add the cost of the key creation for the NB_CHUNKS key - chunkKeyCost := sendOperation.StorageKeyCreationCost + sendOperation.StorageCostPerByte*convert.BytesPerUint32 + chunkKeyCost, err := sendOperation.StorageCostForEntry( + network.Version, + len([]byte(nbChunkKey)), + convert.BytesPerUint32) + if err != nil { + return nil, fmt.Errorf("unable to compute storage cost for chunk key creation: %w", err) + } + uploadCost += chunkKeyCost }