diff --git a/netmap/network_info.go b/netmap/network_info.go index bc73fd42..035fc37c 100644 --- a/netmap/network_info.go +++ b/netmap/network_info.go @@ -7,6 +7,7 @@ import ( "fmt" "math" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neofs-api-go/v2/netmap" ) @@ -74,6 +75,8 @@ func (x *NetworkInfo) readFromV2(m netmap.NetworkInfo, checkFieldPresence bool) configMaxObjSize, configWithdrawalFee: _, err = decodeConfigValueUint64(prm.GetValue()) + case configHomomorphicHashingDisabled: + _, err = decodeConfigValueBool(prm.GetValue()) } if err != nil { @@ -243,7 +246,8 @@ func (x *NetworkInfo) IterateRawNetworkParameters(f func(name string, value []by configEpochDuration, configIRCandidateFee, configMaxObjSize, - configWithdrawalFee: + configWithdrawalFee, + configHomomorphicHashingDisabled: } return false @@ -257,6 +261,11 @@ func (x *NetworkInfo) setConfigUint64(name string, num uint64) { x.setConfig(name, val) } +func (x *NetworkInfo) setConfigBool(name string, val bool) { + v := stackitem.NewBool(val) + x.setConfig(name, v.Bytes()) +} + // decodeConfigValueUint64 parses val as little-endian uint64. // val must be less than 8 bytes in size. func decodeConfigValueUint64(val []byte) (uint64, error) { @@ -272,6 +281,18 @@ func decodeConfigValueUint64(val []byte) (uint64, error) { return res, nil } +// decodeConfigValueBool parses val as boolean contract storage value. +func decodeConfigValueBool(val []byte) (bool, error) { + arr := stackitem.NewByteArray(val) + + res, err := arr.TryBool() + if err != nil { + return false, fmt.Errorf("invalid bool parameter contract format %s", err) + } + + return res, nil +} + func (x NetworkInfo) configUint64(name string) uint64 { val := x.configValue(name) if val == nil { @@ -288,6 +309,22 @@ func (x NetworkInfo) configUint64(name string) uint64 { return res } +func (x NetworkInfo) configBool(name string) bool { + val := x.configValue(name) + if val == nil { + return false + } + + res, err := decodeConfigValueBool(val) + if err != nil { + // potential panic is OK since value MUST be correct since it is + // verified in ReadFromV2 or set by provided method. + panic(err) + } + + return res +} + const configAuditFee = "AuditFee" // SetAuditFee sets the configuration value of the audit fee for the Inner Ring. @@ -467,3 +504,21 @@ func (x *NetworkInfo) SetWithdrawalFee(sz uint64) { func (x NetworkInfo) WithdrawalFee() uint64 { return x.configUint64(configWithdrawalFee) } + +const configHomomorphicHashingDisabled = "HomomorphicHashingDisabled" + +// DisableHomomorphicHashing sets flag requiring to disable homomorphic +// hashing of the containers in the network. +// +// See also HomomorphicHashingDisabled. +func (x *NetworkInfo) DisableHomomorphicHashing() { + x.setConfigBool(configHomomorphicHashingDisabled, true) +} + +// HomomorphicHashingDisabled returns the state of the homomorphic +// hashing network setting. +// +// Zero NetworkInfo has enabled homomorphic hashing. +func (x NetworkInfo) HomomorphicHashingDisabled() bool { + return x.configBool(configHomomorphicHashingDisabled) +} diff --git a/netmap/network_info_decode_test.go b/netmap/network_info_decode_test.go index 59296679..c347ac90 100644 --- a/netmap/network_info_decode_test.go +++ b/netmap/network_info_decode_test.go @@ -26,3 +26,38 @@ func TestDecodeUint64(t *testing.T) { require.Equal(t, expected, actual) } } + +func TestDecodeBool(t *testing.T) { + testCases := []struct { + expected bool + raw []byte + }{ + { + false, + []byte{0}, + }, + { + false, + []byte{0, 0, 0, 0}, + }, + { + true, + []byte{1}, + }, + { + true, + []byte{1, 1, 1, 1, 1}, + }, + { + true, + []byte{0, 0, 0, 0, 1}, // neo-go casts any value that does not consist of zeroes as `true` + }, + } + + for _, test := range testCases { + actual, err := decodeConfigValueBool(test.raw) + require.NoError(t, err) + + require.Equal(t, test.expected, actual) + } +} diff --git a/netmap/network_info_test.go b/netmap/network_info_test.go index d24fb5d9..fc3bbc9b 100644 --- a/netmap/network_info_test.go +++ b/netmap/network_info_test.go @@ -212,3 +212,24 @@ func TestNetworkInfo_WithdrawalFee(t *testing.T) { }, ) } + +func TestNetworkInfo_HomomorphicHashingDisabled(t *testing.T) { + testConfigValue(t, + func(x NetworkInfo) interface{} { return x.HomomorphicHashingDisabled() }, + func(info *NetworkInfo, val interface{}) { + if val.(bool) { + info.DisableHomomorphicHashing() + } + }, + true, true, // it is impossible to enable hashing + "HomomorphicHashingDisabled", func(val interface{}) []byte { + data := make([]byte, 1) + + if val.(bool) { + data[0] = 1 + } + + return data + }, + ) +}