-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test migration of the contracts to notary mode
Signed-off-by: Leonard Lyubich <leonard@morphbits.io>
- Loading branch information
1 parent
237309e
commit 194e1a7
Showing
12 changed files
with
941 additions
and
45 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package alphabet_test | ||
|
||
import ( | ||
"math/rand" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/nspcc-dev/neo-go/pkg/interop" | ||
"github.com/nspcc-dev/neo-go/pkg/util" | ||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" | ||
"github.com/nspcc-dev/neofs-contract/tests/dump" | ||
"github.com/nspcc-dev/neofs-contract/tests/migration" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
const name = "alphabet" | ||
|
||
func TestMigration(t *testing.T) { | ||
err := dump.IterateDumps("../testdata", func(id dump.ID, r *dump.Reader) { | ||
t.Run(id.String()+"/"+name, func(t *testing.T) { | ||
testMigrationFromDump(t, r) | ||
}) | ||
}) | ||
require.NoError(t, err) | ||
} | ||
|
||
func replaceArgI(vs []interface{}, i int, v interface{}) []interface{} { | ||
res := make([]interface{}, len(vs)) | ||
copy(res, vs) | ||
res[i] = v | ||
return res | ||
} | ||
|
||
func randUint160() (u util.Uint160) { | ||
rand.Read(u[:]) | ||
return | ||
} | ||
|
||
var notaryDisabledKey = []byte("notary") | ||
|
||
func testMigrationFromDump(t *testing.T, d *dump.Reader) { | ||
// init test contract shell | ||
c := migration.NewContract(t, d, "alphabet0", migration.ContractOptions{ | ||
SourceCodeDir: filepath.Join("..", name), | ||
}) | ||
|
||
migration.SkipUnsupportedVersions(t, c) | ||
|
||
// gather values which can't be fetched via contract API | ||
v := c.GetStorageItem(notaryDisabledKey) | ||
notaryDisabled := len(v) == 1 && v[0] == 1 | ||
|
||
readPendingVotes := func() bool { | ||
if v := c.GetStorageItem([]byte("ballots")); v != nil { | ||
item, err := stackitem.Deserialize(v) | ||
require.NoError(t, err) | ||
arr, ok := item.Value().([]stackitem.Item) | ||
if ok { | ||
return len(arr) > 0 | ||
} else { | ||
require.Equal(t, stackitem.Null{}, item) | ||
} | ||
} | ||
return false | ||
} | ||
|
||
prevPendingVote := readPendingVotes() | ||
|
||
// read previous values using contract API | ||
readName := func() string { | ||
b, err := c.Call(t, "name").TryBytes() | ||
require.NoError(t, err) | ||
return string(b) | ||
} | ||
|
||
prevName := readName() | ||
|
||
// try to update the contract | ||
proxyContract := randUint160() | ||
updPrm := []interface{}{ | ||
false, // non-notary mode | ||
randUint160(), // unused | ||
[]byte{}, // Proxy contract (custom) | ||
"", // unused | ||
0, // unused | ||
0, // unused | ||
} | ||
|
||
c.CheckUpdateFail(t, "update to non-notary mode is not supported anymore", | ||
replaceArgI(updPrm, 0, true)...) | ||
|
||
if notaryDisabled { | ||
c.CheckUpdateFail(t, "address of the Proxy contract is missing or invalid", | ||
replaceArgI(updPrm, 2, make([]byte, interop.Hash160Len+1))...) | ||
c.CheckUpdateFail(t, "token not found", updPrm...) | ||
|
||
c.RegisterContractInNNS(t, "proxy", proxyContract) | ||
|
||
if prevPendingVote { | ||
c.CheckUpdateFail(t, "pending vote detected", updPrm...) | ||
return | ||
} | ||
} | ||
|
||
c.CheckUpdateSuccess(t, updPrm...) | ||
|
||
// check that contract was updates as expected | ||
newName := readName() | ||
newPendingVote := readPendingVotes() | ||
|
||
require.Nil(t, c.GetStorageItem(notaryDisabledKey), "notary flag should be removed") | ||
require.Nil(t, c.GetStorageItem([]byte("innerring")), "Inner Ring nodes should be removed") | ||
require.Equal(t, prevName, newName, "name should remain") | ||
require.False(t, newPendingVote, "there should be no more pending votes") | ||
|
||
if notaryDisabled { | ||
require.Equal(t, proxyContract[:], c.GetStorageItem([]byte("proxyScriptHash")), "name should remain") | ||
} | ||
} |
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,62 @@ | ||
package audit_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" | ||
"github.com/nspcc-dev/neofs-contract/tests/dump" | ||
"github.com/nspcc-dev/neofs-contract/tests/migration" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
const name = "audit" | ||
|
||
func TestMigration(t *testing.T) { | ||
err := dump.IterateDumps("../testdata", func(id dump.ID, r *dump.Reader) { | ||
t.Run(id.String()+"/"+name, func(t *testing.T) { | ||
testMigrationFromDump(t, r) | ||
}) | ||
}) | ||
require.NoError(t, err) | ||
} | ||
|
||
func testMigrationFromDump(t *testing.T, d *dump.Reader) { | ||
// init test contract shell | ||
c := migration.NewContract(t, d, name, migration.ContractOptions{}) | ||
|
||
migration.SkipUnsupportedVersions(t, c) | ||
|
||
// read previous values using contract API | ||
readAllAuditResults := func() []stackitem.Item { | ||
r := c.Call(t, "list") | ||
items, ok := r.Value().([]stackitem.Item) | ||
if !ok { | ||
require.Equal(t, stackitem.Null{}, r) | ||
} | ||
|
||
var results []stackitem.Item | ||
|
||
for i := range items { | ||
bID, err := items[i].TryBytes() | ||
require.NoError(t, err) | ||
|
||
results = append(results, c.Call(t, "get", bID)) | ||
} | ||
|
||
return results | ||
} | ||
|
||
prevAuditResults := readAllAuditResults() | ||
|
||
// try to update the contract | ||
var notary bool | ||
c.CheckUpdateFail(t, "update to non-notary mode is not supported anymore", !notary) | ||
c.CheckUpdateSuccess(t, notary) | ||
|
||
// check that contract was updates as expected | ||
newAuditResults := readAllAuditResults() | ||
|
||
require.Nil(t, c.GetStorageItem([]byte("notary")), "notary flag should be removed") | ||
require.Nil(t, c.GetStorageItem([]byte("netmapScriptHash")), "Netmap contract address should be removed") | ||
require.ElementsMatch(t, prevAuditResults, newAuditResults, "audit results should remain") | ||
} |
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,81 @@ | ||
package balance_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" | ||
"github.com/nspcc-dev/neofs-contract/tests/dump" | ||
"github.com/nspcc-dev/neofs-contract/tests/migration" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
const name = "balance" | ||
|
||
func TestMigration(t *testing.T) { | ||
err := dump.IterateDumps("../testdata", func(id dump.ID, r *dump.Reader) { | ||
t.Run(id.String()+"/"+name, func(t *testing.T) { | ||
testMigrationFromDump(t, r) | ||
}) | ||
}) | ||
require.NoError(t, err) | ||
} | ||
|
||
var notaryDisabledKey = []byte("notary") | ||
|
||
func testMigrationFromDump(t *testing.T, d *dump.Reader) { | ||
// init test contract shell | ||
c := migration.NewContract(t, d, name, migration.ContractOptions{}) | ||
|
||
migration.SkipUnsupportedVersions(t, c) | ||
|
||
// gather values which can't be fetched via contract API | ||
v := c.GetStorageItem(notaryDisabledKey) | ||
notaryDisabled := len(v) == 1 && v[0] == 1 | ||
|
||
readPendingVotes := func() bool { | ||
if v := c.GetStorageItem([]byte("ballots")); v != nil { | ||
item, err := stackitem.Deserialize(v) | ||
require.NoError(t, err) | ||
arr, ok := item.Value().([]stackitem.Item) | ||
if ok { | ||
return len(arr) > 0 | ||
} else { | ||
require.Equal(t, stackitem.Null{}, item) | ||
} | ||
} | ||
return false | ||
} | ||
|
||
prevPendingVotes := readPendingVotes() | ||
|
||
// read previous values using contract API | ||
readTotalSupply := func() int64 { | ||
n, err := c.Call(t, "totalSupply").TryInteger() | ||
require.NoError(t, err) | ||
return n.Int64() | ||
} | ||
|
||
prevTotalSupply := readTotalSupply() | ||
|
||
// try to update the contract | ||
var notary bool | ||
c.CheckUpdateFail(t, "update to non-notary mode is not supported anymore", !notary) | ||
|
||
if notaryDisabled && prevPendingVotes { | ||
c.CheckUpdateFail(t, "pending vote detected", notary) | ||
return | ||
} | ||
|
||
c.CheckUpdateSuccess(t, notary) | ||
|
||
// check that contract was updates as expected | ||
newTotalSupply := readTotalSupply() | ||
newPendingVotes := readPendingVotes() | ||
|
||
require.False(t, newPendingVotes, "there should be no more pending votes") | ||
require.Nil(t, c.GetStorageItem(notaryDisabledKey), "notary flag should be removed") | ||
require.Nil(t, c.GetStorageItem([]byte("containerScriptHash")), "Container contract address should be removed") | ||
require.Nil(t, c.GetStorageItem([]byte("netmapScriptHash")), "Netmap contract address should be removed") | ||
|
||
require.Equal(t, prevTotalSupply, newTotalSupply) | ||
} |
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,119 @@ | ||
package container_test | ||
|
||
import ( | ||
"bytes" | ||
"testing" | ||
|
||
"github.com/mr-tron/base58" | ||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" | ||
"github.com/nspcc-dev/neofs-contract/tests/dump" | ||
"github.com/nspcc-dev/neofs-contract/tests/migration" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
const name = "container" | ||
|
||
func TestMigration(t *testing.T) { | ||
err := dump.IterateDumps("../testdata", func(id dump.ID, r *dump.Reader) { | ||
t.Run(id.String()+"/"+name, func(t *testing.T) { | ||
testMigrationFromDump(t, r) | ||
}) | ||
}) | ||
require.NoError(t, err) | ||
} | ||
|
||
var notaryDisabledKey = []byte("notary") | ||
|
||
func testMigrationFromDump(t *testing.T, d *dump.Reader) { | ||
// gather values which can't be fetched via contract API | ||
var owners [][]byte | ||
|
||
c := migration.NewContract(t, d, "container", migration.ContractOptions{ | ||
StorageDumpHandler: func(key, value []byte) { | ||
const ownerLen = 25 | ||
if len(key) == ownerLen+32 { // + cid | ||
for i := range owners { | ||
if bytes.Equal(owners[i], key[:ownerLen]) { | ||
return | ||
} | ||
} | ||
owners = append(owners, key[:ownerLen]) | ||
} | ||
}, | ||
}) | ||
|
||
migration.SkipUnsupportedVersions(t, c) | ||
|
||
v := c.GetStorageItem(notaryDisabledKey) | ||
notaryDisabled := len(v) == 1 && v[0] == 1 | ||
|
||
readPendingVotes := func() bool { | ||
if v := c.GetStorageItem([]byte("ballots")); v != nil { | ||
item, err := stackitem.Deserialize(v) | ||
require.NoError(t, err) | ||
arr, ok := item.Value().([]stackitem.Item) | ||
if ok { | ||
return len(arr) > 0 | ||
} else { | ||
require.Equal(t, stackitem.Null{}, item) | ||
} | ||
} | ||
return false | ||
} | ||
|
||
prevPendingVote := readPendingVotes() | ||
|
||
// read previous values using contract API | ||
readAllContainers := func() []stackitem.Item { | ||
containers, ok := c.Call(t, "list", []byte{}).Value().([]stackitem.Item) | ||
require.True(t, ok) | ||
return containers | ||
} | ||
|
||
readContainerCount := func() uint64 { | ||
nContainers, err := c.Call(t, "count").TryInteger() | ||
require.NoError(t, err) | ||
return nContainers.Uint64() | ||
} | ||
|
||
readOwnersToContainers := func() map[string][]stackitem.Item { | ||
m := make(map[string][]stackitem.Item, len(owners)) | ||
for i := range owners { | ||
m[string(owners[i])] = c.Call(t, "list", owners[i]).Value().([]stackitem.Item) | ||
} | ||
return m | ||
} | ||
|
||
prevContainers := readAllContainers() | ||
prevContainerCount := readContainerCount() | ||
prevOwnersToContainers := readOwnersToContainers() | ||
|
||
// try to update the contract | ||
var notary bool | ||
c.CheckUpdateFail(t, "update to non-notary mode is not supported anymore", !notary) | ||
|
||
if notaryDisabled && prevPendingVote { | ||
c.CheckUpdateFail(t, "pending vote detected", notary) | ||
return | ||
} | ||
|
||
c.CheckUpdateSuccess(t, notary) | ||
|
||
// check that contract was updates as expected | ||
newPendingVote := readPendingVotes() | ||
newContainers := readAllContainers() | ||
newContainerCount := readContainerCount() | ||
newOwnersToContainers := readOwnersToContainers() | ||
|
||
require.Nil(t, c.GetStorageItem(notaryDisabledKey), "notary flag should be removed") | ||
require.Equal(t, prevContainerCount, newContainerCount, "number of containers should remain") | ||
require.ElementsMatch(t, prevContainers, newContainers, "container list should remain") | ||
require.False(t, newPendingVote, "there should be no more pending votes") | ||
|
||
require.Equal(t, len(prevOwnersToContainers), len(newOwnersToContainers)) | ||
for k, vPrev := range prevOwnersToContainers { | ||
vNew, ok := newOwnersToContainers[k] | ||
require.True(t, ok) | ||
require.ElementsMatch(t, vPrev, vNew, "containers of '%s' owner should remain", base58.Encode([]byte(k))) | ||
} | ||
} |
Oops, something went wrong.