diff --git a/rpc/nns/hashes.go b/rpc/nns/hashes.go new file mode 100644 index 00000000..177b7095 --- /dev/null +++ b/rpc/nns/hashes.go @@ -0,0 +1,29 @@ +package nns + +import ( + "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/util" +) + +// ID is the default NNS contract ID in all NeoFS networks. NeoFS networks +// always deploy NNS first and can't work without it, therefore it always gets +// and ID of 1. +const ID = 1 + +// ContractStateGetter is the interface required for contract state resolution +// using a known contract ID. +type ContractStateGetter interface { + GetContractStateByID(int32) (*state.Contract, error) +} + +// InferHash simplifies resolving NNS contract hash in existing NeoFS networks. +// It assumes that NNS follows [ID] assignment assumptions which likely won't +// be the case for any non-NeoFS network. +func InferHash(sg ContractStateGetter) (util.Uint160, error) { + c, err := sg.GetContractStateByID(ID) + if err != nil { + return util.Uint160{}, err + } + + return c.Hash, nil +} diff --git a/rpc/nns/hashes_test.go b/rpc/nns/hashes_test.go new file mode 100644 index 00000000..a7d87017 --- /dev/null +++ b/rpc/nns/hashes_test.go @@ -0,0 +1,37 @@ +package nns + +import ( + "errors" + "testing" + + "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/stretchr/testify/require" +) + +type stateGetter struct { + f func(int32) (*state.Contract, error) +} + +func (s stateGetter) GetContractStateByID(id int32) (*state.Contract, error) { + return s.f(id) +} + +func TestInferHash(t *testing.T) { + var sg stateGetter + sg.f = func(int32) (*state.Contract, error) { + return nil, errors.New("bad") + } + _, err := InferHash(sg) + require.Error(t, err) + sg.f = func(int32) (*state.Contract, error) { + return &state.Contract{ + ContractBase: state.ContractBase{ + Hash: util.Uint160{0x01, 0x02, 0x03}, + }, + }, nil + } + h, err := InferHash(sg) + require.NoError(t, err) + require.Equal(t, util.Uint160{0x01, 0x02, 0x03}, h) +}