-
Notifications
You must be signed in to change notification settings - Fork 176
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2765238
commit 5b84a44
Showing
19 changed files
with
624 additions
and
154 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package migrations | ||
|
||
import ( | ||
fvm "github.com/onflow/flow-go/fvm/state" | ||
"github.com/onflow/flow-go/ledger" | ||
"github.com/onflow/flow-go/ledger/common/utils" | ||
"github.com/onflow/flow-go/model/flow" | ||
) | ||
|
||
// iterates through registers keeping a map of register sizes | ||
// after it has reached the end it add storage used and storage capacity for each address | ||
func StorageFeesMigration(payload []ledger.Payload) ([]ledger.Payload, error) { | ||
storageUsed := make(map[string]uint64) | ||
newPayload := make([]ledger.Payload, len(payload)) | ||
|
||
for i, p := range payload { | ||
err := incrementStorageUsed(p, storageUsed) | ||
if err != nil { | ||
return nil, err | ||
} | ||
newPayload[i] = p | ||
} | ||
|
||
for s, u := range storageUsed { | ||
// this is the storage used by the storage_used register we are about to add | ||
storageUsedByStorageUsed := fvm.RegisterSize( | ||
flow.BytesToAddress([]byte(s)), | ||
false, "storage_used", | ||
make([]byte, 8)) | ||
u = u + uint64(storageUsedByStorageUsed) | ||
|
||
newPayload = append(newPayload, ledger.Payload{ | ||
Key: registerIDToKey(flow.RegisterID{ | ||
Owner: s, | ||
Controller: "", | ||
Key: "storage_used", | ||
}), | ||
Value: utils.Uint64ToBinary(u), | ||
}) | ||
} | ||
return newPayload, nil | ||
} | ||
|
||
func incrementStorageUsed(p ledger.Payload, used map[string]uint64) error { | ||
id, err := keyToRegisterID(p.Key) | ||
if err != nil { | ||
return err | ||
} | ||
if len([]byte(id.Owner)) != flow.AddressLength { | ||
// not an address | ||
return nil | ||
} | ||
if _, ok := used[id.Owner]; !ok { | ||
used[id.Owner] = 0 | ||
} | ||
used[id.Owner] = used[id.Owner] + uint64(registerSize(id, p)) | ||
return nil | ||
} | ||
|
||
func registerSize(id flow.RegisterID, p ledger.Payload) int { | ||
address := flow.BytesToAddress([]byte(id.Owner)) | ||
isController := len(id.Controller) > 0 | ||
key := id.Key | ||
return fvm.RegisterSize(address, isController, key, p.Value) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package migrations | ||
|
||
import ( | ||
"math" | ||
"strings" | ||
|
||
"github.com/rs/zerolog" | ||
|
||
"github.com/onflow/flow-go/ledger" | ||
"github.com/onflow/flow-go/ledger/common/utils" | ||
"github.com/onflow/flow-go/model/flow" | ||
) | ||
|
||
// iterates through registers keeping a map of register sizes | ||
// reports on storage metrics | ||
type StorageReporter struct { | ||
Log zerolog.Logger | ||
} | ||
|
||
func (r StorageReporter) Report(payload []ledger.Payload) error { | ||
r.Log.Info().Msg("Running Storage Reporter") | ||
storageUsed := make(map[string]uint64) | ||
average := 0.0 | ||
max := uint64(0) | ||
|
||
for i, p := range payload { | ||
id, err := keyToRegisterID(p.Key) | ||
if err != nil { | ||
return err | ||
} | ||
if len([]byte(id.Owner)) != flow.AddressLength { | ||
// not an address | ||
continue | ||
} | ||
if id.Key != "storage_used" { | ||
continue | ||
} | ||
u, _, err := utils.ReadUint64(p.Value) | ||
if err != nil { | ||
return err | ||
} | ||
storageUsed[id.Owner] = u | ||
average = average + (float64(u)-average)/(float64(i)+1.0) | ||
if u > max { | ||
max = u | ||
} | ||
} | ||
r.Log.Info(). | ||
Msgf("Average storage used %g", average) | ||
r.Log.Info(). | ||
Msgf("Max storage used %d", max) | ||
|
||
bins := 150 | ||
binHeight := 30 | ||
w := float64(max) / float64(bins) | ||
distribution := make([]float64, bins) | ||
|
||
var maxBin = float64(0) | ||
|
||
for s, u := range storageUsed { | ||
var i = int(float64(u) / w) | ||
if i >= bins { | ||
i = bins - 1 | ||
} | ||
distribution[i] = distribution[i] + 1 | ||
|
||
if maxBin < distribution[i] { | ||
maxBin = distribution[i] | ||
} | ||
if i == bins-1 { | ||
r.Log.Info(). | ||
Msgf("High storage usage address: %s, used: %d bytes", flow.BytesToAddress([]byte(s)), u) | ||
} | ||
} | ||
maxBinAccounts := maxBin | ||
maxBin = math.Log10(maxBin) | ||
|
||
graph := make([]int, bins) | ||
|
||
for i, d := range distribution { | ||
var v float64 | ||
if d <= 0 { | ||
v = 0 | ||
} else { | ||
v = math.Log10(d) | ||
} | ||
|
||
graph[i] = int(math.Ceil((v / maxBin) * float64(binHeight))) | ||
} | ||
|
||
r.Log.Info(). | ||
Msgf("Logarithmic account storage distribution x[storage used] / y[log number of accounts (max = %f accounts)]:", maxBinAccounts) | ||
|
||
var sb strings.Builder | ||
for j := binHeight; j >= 0; j-- { | ||
sb.WriteRune('\n') | ||
for i := 0; i < bins; i++ { | ||
if graph[i] >= j { | ||
sb.WriteRune('#') | ||
} else { | ||
sb.WriteRune('.') | ||
} | ||
} | ||
} | ||
|
||
r.Log.Info(). | ||
Msg(sb.String()) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package migrations | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/onflow/flow-go/engine/execution/state" | ||
"github.com/onflow/flow-go/ledger" | ||
"github.com/onflow/flow-go/model/flow" | ||
) | ||
|
||
func keyToRegisterID(key ledger.Key) (flow.RegisterID, error) { | ||
if len(key.KeyParts) != 3 || | ||
key.KeyParts[0].Type != state.KeyPartOwner || | ||
key.KeyParts[1].Type != state.KeyPartController || | ||
key.KeyParts[2].Type != state.KeyPartKey { | ||
return flow.RegisterID{}, fmt.Errorf("key not in expected format %s", key.String()) | ||
} | ||
|
||
return flow.NewRegisterID( | ||
string(key.KeyParts[0].Value), | ||
string(key.KeyParts[1].Value), | ||
string(key.KeyParts[2].Value), | ||
), nil | ||
} | ||
|
||
func registerIDToKey(registerID flow.RegisterID) ledger.Key { | ||
newKey := ledger.Key{} | ||
newKey.KeyParts = []ledger.KeyPart{ | ||
{ | ||
Type: state.KeyPartOwner, | ||
Value: []byte(registerID.Owner), | ||
}, | ||
{ | ||
Type: state.KeyPartController, | ||
Value: []byte(registerID.Controller), | ||
}, | ||
{ | ||
Type: state.KeyPartKey, | ||
Value: []byte(registerID.Key), | ||
}, | ||
} | ||
return newKey | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.