diff --git a/pkg/compiler/native_test.go b/pkg/compiler/native_test.go index ba0add4e4..c7a78c606 100644 --- a/pkg/compiler/native_test.go +++ b/pkg/compiler/native_test.go @@ -163,6 +163,7 @@ func TestNativeHelpersCompile(t *testing.T) { {"getAllCandidates", nil}, {"getCandidateVote", []string{pub}}, {"getCommittee", nil}, + {"getCommitteeAddress", nil}, {"getGasPerBlock", nil}, {"getNextBlockValidators", nil}, {"getRegisterPrice", nil}, diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 4e0e426a1..2822716d9 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -232,6 +232,10 @@ func newNEO(cfg config.ProtocolConfiguration) *NEO { md = newMethodAndPrice(n.getCommittee, 1<<16, callflag.ReadStates) n.AddMethod(md, desc) + desc = newDescriptor("getCommitteeAddress", smartcontract.Hash160Type) + md = newMethodAndPrice(n.getCommitteeAddress, 1<<16, callflag.ReadStates) + n.AddMethod(md, desc) + desc = newDescriptor("getNextBlockValidators", smartcontract.ArrayType) md = newMethodAndPrice(n.getNextBlockValidators, 1<<16, callflag.ReadStates) n.AddMethod(md, desc) @@ -1071,6 +1075,10 @@ func (n *NEO) getCandidatesCall(ic *interop.Context, _ []stackitem.Item) stackit return stackitem.NewArray(arr) } +func (n *NEO) getCommitteeAddress(ic *interop.Context, _ []stackitem.Item) stackitem.Item { + return stackitem.NewByteArray(n.GetCommitteeAddress(ic.DAO).BytesBE()) +} + func (n *NEO) getAllCandidatesCall(ic *interop.Context, _ []stackitem.Item) stackitem.Item { ctx, cancel := context.WithCancel(context.Background()) prefix := []byte{prefixCandidate} diff --git a/pkg/core/native/native_test/neo_test.go b/pkg/core/native/native_test/neo_test.go index ac2ece158..c3ea676f7 100644 --- a/pkg/core/native/native_test/neo_test.go +++ b/pkg/core/native/native_test/neo_test.go @@ -18,10 +18,12 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/neotest" "github.com/nspcc-dev/neo-go/pkg/neotest/chain" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" @@ -396,6 +398,19 @@ func TestNEO_RecursiveGASMint(t *testing.T) { neoValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), c.Hash, int64(1), nil) } +func TestNEO_GetCommitteeAddress(t *testing.T) { + neoValidatorInvoker := newNeoValidatorsClient(t) + e := neoValidatorInvoker.Executor + standByCommitteePublicKeys, err := keys.NewPublicKeysFromStrings(e.Chain.GetConfig().StandbyCommittee) + require.NoError(t, err) + sort.Sort(standByCommitteePublicKeys) + expectedCommitteeAddress, err := smartcontract.CreateMajorityMultiSigRedeemScript(standByCommitteePublicKeys) + require.NoError(t, err) + stack, err := neoValidatorInvoker.TestInvoke(t, "getCommitteeAddress") + require.NoError(t, err) + require.Equal(t, hash.Hash160(expectedCommitteeAddress).BytesBE(), stack.Pop().Item().Value().([]byte)) +} + func TestNEO_GetAccountState(t *testing.T) { neoValidatorInvoker := newNeoValidatorsClient(t) e := neoValidatorInvoker.Executor diff --git a/pkg/interop/native/neo/neo.go b/pkg/interop/native/neo/neo.go index 4fde83829..e0031a2db 100644 --- a/pkg/interop/native/neo/neo.go +++ b/pkg/interop/native/neo/neo.go @@ -126,3 +126,9 @@ func UnclaimedGAS(addr interop.Hash160, end int) int { func GetAccountState(addr interop.Hash160) *AccountState { return neogointernal.CallWithToken(Hash, "getAccountState", int(contract.ReadStates), addr).(*AccountState) } + +// GetCommitteeAddress represents `getCommitteeAddress` method of NEO native contract. +func GetCommitteeAddress() interop.Hash160 { + return neogointernal.CallWithToken(Hash, "getCommitteeAddress", int(contract.ReadStates)).(interop.Hash160) + +} diff --git a/pkg/rpcclient/neo/neo.go b/pkg/rpcclient/neo/neo.go index 8817e3658..ccb209001 100644 --- a/pkg/rpcclient/neo/neo.go +++ b/pkg/rpcclient/neo/neo.go @@ -233,6 +233,11 @@ func (c *ContractReader) GetCommittee() (keys.PublicKeys, error) { return unwrap.ArrayOfPublicKeys(c.invoker.Call(Hash, "getCommittee")) } +// GetCommitteeAddress returns the committee address. +func (c *ContractReader) GetCommitteeAddress() (util.Uint160, error) { + return unwrap.Uint160(c.invoker.Call(Hash, "getCommitteeAddress")) +} + // GetNextBlockValidators returns the list of validator keys that will sign the // next block. This method is mostly useful for historic invocations because the // RPC protocol provides direct getnextblockvalidators call that provides more