Skip to content

Commit

Permalink
compute network specific storage costs
Browse files Browse the repository at this point in the history
  • Loading branch information
peterjah committed Oct 18, 2023
1 parent 3a4bbbc commit 49a20e4
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 42 deletions.
1 change: 0 additions & 1 deletion int/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
4 changes: 2 additions & 2 deletions int/config/config_network.yaml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
8 changes: 5 additions & 3 deletions int/config/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,20 @@ 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+)`

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)
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/convert/byteConverter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)
Expand Down
52 changes: 41 additions & 11 deletions pkg/node/sendoperation/sendoperation.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
b64 "encoding/base64"
"encoding/binary"
"fmt"
"strconv"
"strings"

"github.com/massalabs/station/pkg/node"
Expand All @@ -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
Expand Down Expand Up @@ -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
}
81 changes: 59 additions & 22 deletions pkg/onchain/website/uploader.go
Original file line number Diff line number Diff line change
Expand Up @@ -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/"

Expand All @@ -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)

Expand Down Expand Up @@ -75,7 +92,7 @@ func PrepareForUpload(

// Set DNS.
_, err = dns.SetRecord(
config,
network,
client,
nickname,
url,
Expand All @@ -94,26 +111,25 @@ 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
}

return operations, nil
}

//nolint:funlen
func upload(
client *node.Client,
network config.NetworkInfos,
addr string,
chunks [][]byte,
nickname string,
Expand All @@ -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
Expand All @@ -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
}

Expand Down Expand Up @@ -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,
Expand All @@ -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, ",")

Expand All @@ -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
}

Expand Down

0 comments on commit 49a20e4

Please sign in to comment.