scripts: add contract ID/prefix parsing to state dump comparator

I had this code locally for some time, let it be public.

The example output for key diff:
```
file BlockStorage_0/dump-block-0.json: block 0: key mismatch:
	Key: /////wz////4
	Contract ID: -1
	Item key (base64): DP////g=
	Item key (hex): 0cfffffff8
	Item key (bytes): [12 255 255 255 248]
vs
	Key: /////wz////5
	Contract ID: -1
	Item key (base64): DP////k=
	Item key (hex): 0cfffffff9
	Item key (bytes): [12 255 255 255 249]
```

The example output for state diff:
```
file BlockStorage_0/dump-block-0.json: block 0: state mismatch for key /////wz////4:
	Contract ID: -1
	Item key (base64): DP////g=
	Item key (hex): 0cfffffff8
	Item key (bytes): [12 255 255 255 248]
	Diff: Added vs Removed
```

The example output for value diff:
```
block 0: value mismatch for key /////wj1Y+pAvCg9TQ4FxI6jBbPyoHNA7w==:
	Contract ID: -1
	Item key (base64): CPVj6kC8KD1NDgXEjqMFs/Kgc0Dv
	Item key (hex): 08f563ea40bc283d4d0e05c48ea305b3f2a07340ef
	Item key (bytes): [8 245 99 234 64 188 40 61 77 14 5 196 142 163 5 179 242 160 115 64 239]
	Diff: QAUhAfshACgU9WPqQLwoPU0OBcSOowWz8qBzQO8o005FRjNuZW8tY29yZS12My4wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACFEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQHvz5gNBCCgITmVvVG9rZW5AAEgAQAEoBk5FUC0xN0ECQBNBBSgJYmFsYW5jZU9mQAFBAigHYWNjb3VudCEBFCEBESEAIAFBBSgIZGVjaW1hbHNAACEBESEBByABQQUoD2dldEFjY291bnRTdGF0ZUABQQIoB2FjY291bnQhARQhASAhAQ4gAUEFKBBnZXRBbGxDYW5kaWRhdGVzQAAhATAhARUgAUEFKBBnZXRDYW5kaWRhdGVWb3RlQAFBAigGcHViS2V5IQEWIQERIQEcIAFBBSgNZ2V0Q2FuZGlkYXRlc0AAIQEgIQEjIAFBBSgMZ2V0Q29tbWl0dGVlQAAhASAhASogAUEFKA5nZXRHYXNQZXJCbG9ja0AAIQERIQExIAFBBSgWZ2V0TmV4dEJsb2NrVmFsaWRhdG9yc0AAIQEgIQE4IAFBBSgQZ2V0UmVnaXN0ZXJQcmljZUAAIQERIQE/IAFBBSgRcmVnaXN0ZXJDYW5kaWRhdGVAAUECKAZwdWJrZXkhARYhARAhAUYgAEEFKA5zZXRHYXNQZXJCbG9ja0ABQQIoC2dhc1BlckJsb2NrIQERIQL/ACEBTSAAQQUoEHNldFJlZ2lzdGVyUHJpY2VAAUECKA1yZWdpc3RlclByaWNlIQERIQL/ACEBVCAAQQUoBnN5bWJvbEAAIQETIQFbIAFBBSgLdG90YWxTdXBwbHlAACEBESEBYiABQQUoCHRyYW5zZmVyQARBAigEZnJvbSEBFEECKAJ0byEBFEECKAZhbW91bnQhARFBAigEZGF0YSEAIQEQIQFpIABBBSgMdW5jbGFpbWVkR2FzQAJBAigHYWNjb3VudCEBFEECKANlbmQhAREhAREhAXAgAUEFKBN1bnJlZ2lzdGVyQ2FuZGlkYXRlQAFBAigGcHVia2V5IQEWIQEQIQF3IABBBSgEdm90ZUACQQIoB2FjY291bnQhARRBAigGdm90ZVRvIQEWIQEQIQF+IABAA0ECKBVDYW5kaWRhdGVTdGF0ZUNoYW5nZWRAA0ECKAZwdWJrZXkhARZBAigKcmVnaXN0ZXJlZCEBEEECKAV2b3RlcyEBEUECKARWb3RlQARBAigHYWNjb3VudCEBFEECKARmcm9tIQEWQQIoAnRvIQEWQQIoBmFtb3VudCEBEUECKBBDb21taXR0ZWVDaGFuZ2VkQAJBAigDb2xkIQEgQQIoA25ldyEBIEABQQIAAEAAKARudWxs vs QAUhAfshACgU9WPqQLwoPU0OBcSOowWz8qBzQO8o005FRjNuZW8tY29yZS12My4wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACFEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQHvz5gNBCCgITmVvVG9rZW5AAEgAQAEoBk5FUC0xN0ECQBNBBSgJYmFsYW5jZU9mQAFBAigHYWNjb3VudCEBFCEBESEAIAFBBSgIZGVjaW1hbHNAACEBESEBByABQQUoD2dldEFjY291bnRTdGF0ZUABQQIoB2FjY291bnQhARQhASAhAQ4gAUEFKBBnZXRBbGxDYW5kaWRhdGVzQAAhATAhARUgAUEFKBBnZXRDYW5kaWRhdGVWb3RlQAFBAigGcHViS2V5IQEWIQERIQEcIAFBBSgNZ2V0Q2FuZGlkYXRlc0AAIQEgIQEjIAFBBSgMZ2V0Q29tbWl0dGVlQAAhASAhASogAUEFKA5nZXRHYXNQZXJCbG9ja0AAIQERIQExIAFBBSgWZ2V0TmV4dEJsb2NrVmFsaWRhdG9yc0AAIQEgIQE4IAFBBSgQZ2V0UmVnaXN0ZXJQcmljZUAAIQERIQE/IAFBBSgRcmVnaXN0ZXJDYW5kaWRhdGVAAUECKAZwdWJrZXkhARYhARAhAUYgAEEFKA5zZXRHYXNQZXJCbG9ja0ABQQIoC2dhc1BlckJsb2NrIQERIQL/ACEBTSAAQQUoEHNldFJlZ2lzdGVyUHJpY2VAAUECKA1yZWdpc3RlclByaWNlIQERIQL/ACEBVCAAQQUoBnN5bWJvbEAAIQETIQFbIAFBBSgLdG90YWxTdXBwbHlAACEBESEBYiABQQUoCHRyYW5zZmVyQARBAigEZnJvbSEBFEECKAJ0byEBFEECKAZhbW91bnQhARFBAigEZGF0YSEAIQEQIQFpIABBBSgMdW5jbGFpbWVkR2FzQAJBAigHYWNjb3VudCEBFEECKANlbmQhAREhAREhAXAgAUEFKBN1bnJlZ2lzdGVyQ2FuZGlkYXRlQAFBAigGcHVia2V5IQEWIQEQIQF3IABBBSgEdm90ZUACQQIoB2FjY291bnQhARRBAigGdm90ZVRvIQEWIQEQIQF+IABABEECKAhUcmFuc2ZlckADQQIoBGZyb20hARRBAigCdG8hARRBAigGYW1vdW50IQERQQIoFUNhbmRpZGF0ZVN0YXRlQ2hhbmdlZEADQQIoBnB1YmtleSEBFkECKApyZWdpc3RlcmVkIQEQQQIoBXZvdGVzIQERQQIoBFZvdGVABEECKAdhY2NvdW50IQEUQQIoBGZyb20hARZBAigCdG8hARZBAigGYW1vdW50IQERQQIoEENvbW1pdHRlZUNoYW5nZWRAAkECKANvbGQhASBBAigDbmV3IQEgQAFBAgAAQAAoBG51bGw=
```

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
Anna Shaleva 2024-04-11 19:25:28 +03:00
parent 8913542f93
commit 97a19df6f0

View file

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"encoding/binary" "encoding/binary"
"encoding/hex"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@ -94,14 +95,18 @@ func compare(a, b string) error {
fail := false fail := false
for j := range blockA.Storage { for j := range blockA.Storage {
if blockA.Storage[j].Key != blockB.Storage[j].Key { if blockA.Storage[j].Key != blockB.Storage[j].Key {
return fmt.Errorf("block %d: key mismatch: %s vs %s", blockA.Block, blockA.Storage[j].Key, blockB.Storage[j].Key) idA, prefixA := parseKey(blockA.Storage[j].Key)
idB, prefixB := parseKey(blockB.Storage[j].Key)
return fmt.Errorf("block %d: key mismatch:\n\tKey: %s\n\tContract ID: %d\n\tItem key (base64): %s\n\tItem key (hex): %s\n\tItem key (bytes): %v\nvs\n\tKey: %s\n\tContract ID: %d\n\tItem key (base64): %s\n\tItem key (hex): %s\n\tItem key (bytes): %v", blockA.Block, blockA.Storage[j].Key, idA, base64.StdEncoding.EncodeToString(prefixA), hex.EncodeToString(prefixA), prefixA, blockB.Storage[j].Key, idB, base64.StdEncoding.EncodeToString(prefixB), hex.EncodeToString(prefixB), prefixB)
} }
if blockA.Storage[j].State != blockB.Storage[j].State { if blockA.Storage[j].State != blockB.Storage[j].State {
return fmt.Errorf("block %d: state mismatch for key %s: %s vs %s", blockA.Block, blockA.Storage[j].Key, blockA.Storage[j].State, blockB.Storage[j].State) id, prefix := parseKey(blockA.Storage[j].Key)
return fmt.Errorf("block %d: state mismatch for key %s:\n\tContract ID: %d\n\tItem key (base64): %s\n\tItem key (hex): %s\n\tItem key (bytes): %v\n\tDiff: %s vs %s", blockA.Block, blockA.Storage[j].Key, id, base64.StdEncoding.EncodeToString(prefix), hex.EncodeToString(prefix), prefix, blockA.Storage[j].State, blockB.Storage[j].State)
} }
if blockA.Storage[j].Value != blockB.Storage[j].Value { if blockA.Storage[j].Value != blockB.Storage[j].Value {
fail = true fail = true
fmt.Printf("block %d: value mismatch for key %s: %s vs %s\n", blockA.Block, blockA.Storage[j].Key, blockA.Storage[j].Value, blockB.Storage[j].Value) id, prefix := parseKey(blockA.Storage[j].Key)
fmt.Printf("block %d: value mismatch for key %s:\n\tContract ID: %d\n\tItem key (base64): %s\n\tItem key (hex): %s\n\tItem key (bytes): %v\n\tDiff: %s vs %s\n", blockA.Block, blockA.Storage[j].Key, id, base64.StdEncoding.EncodeToString(prefix), hex.EncodeToString(prefix), prefix, blockA.Storage[j].Value, blockB.Storage[j].Value)
} }
} }
if fail { if fail {
@ -111,6 +116,14 @@ func compare(a, b string) error {
return nil return nil
} }
// parseKey splits the provided storage item key into contract ID and contract storage item prefix.
func parseKey(key string) (int32, []byte) {
keyBytes, _ := base64.StdEncoding.DecodeString(key) // ignore error, rely on proper storage dump state.
id := int32(binary.LittleEndian.Uint32(keyBytes[:4]))
prefix := keyBytes[4:]
return id, prefix
}
func cliMain(c *cli.Context) error { func cliMain(c *cli.Context) error {
a := c.Args().Get(0) a := c.Args().Get(0)
b := c.Args().Get(1) b := c.Args().Get(1)