diff --git a/internal/fakechain/fakechain.go b/internal/fakechain/fakechain.go index 97d690a6c..0489a46fd 100644 --- a/internal/fakechain/fakechain.go +++ b/internal/fakechain/fakechain.go @@ -85,6 +85,11 @@ func (*FakeChain) IsExtensibleAllowed(uint160 util.Uint160) bool { return true } +// GetNatives implements blockchainer.Blockchainer interface. +func (*FakeChain) GetNatives() []state.NativeContract { + panic("TODO") +} + // GetNotaryDepositExpiration implements Blockchainer interface. func (chain *FakeChain) GetNotaryDepositExpiration(acc util.Uint160) uint32 { if chain.NotaryDepositExpiration != 0 { diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 4fd1a5857..56c8c8666 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1243,6 +1243,19 @@ func (bc *Blockchain) GetNativeContractScriptHash(name string) (util.Uint160, er return util.Uint160{}, errors.New("Unknown native contract") } +// GetNatives returns list of native contracts. +func (bc *Blockchain) GetNatives() []state.NativeContract { + res := make([]state.NativeContract, len(bc.contracts.Contracts)) + for i, c := range bc.contracts.Contracts { + md := c.Metadata() + res[i].ID = md.ContractID + res[i].Hash = md.Hash + res[i].Manifest = md.Manifest + res[i].NEF = md.NEF + } + return res +} + // GetConfig returns the config stored in the blockchain. func (bc *Blockchain) GetConfig() config.ProtocolConfiguration { return bc.config diff --git a/pkg/core/blockchainer/blockchainer.go b/pkg/core/blockchainer/blockchainer.go index 9dad9966c..24ed60289 100644 --- a/pkg/core/blockchainer/blockchainer.go +++ b/pkg/core/blockchainer/blockchainer.go @@ -45,6 +45,7 @@ type Blockchainer interface { GetAppExecResults(util.Uint256, trigger.Type) ([]state.AppExecResult, error) GetNotaryDepositExpiration(acc util.Uint160) uint32 GetNativeContractScriptHash(string) (util.Uint160, error) + GetNatives() []state.NativeContract GetNextBlockValidators() ([]*keys.PublicKey, error) GetNEP17Balances(util.Uint160) *state.NEP17Balances GetNotaryContractScriptHash() util.Uint160 diff --git a/pkg/core/state/contract.go b/pkg/core/state/contract.go index a9b94612d..7e0dd435c 100644 --- a/pkg/core/state/contract.go +++ b/pkg/core/state/contract.go @@ -30,6 +30,12 @@ type ContractBase struct { Manifest manifest.Manifest `json:"manifest"` } +// NativeContract holds information about native contract. +type NativeContract struct { + ContractBase + ActiveBlockIndex uint32 `json:"activeblockindex"` +} + // DecodeBinary implements Serializable interface. func (c *Contract) DecodeBinary(r *io.BinReader) { si := stackitem.DecodeBinaryStackItem(r) diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index f7d7349c9..2adaae5dd 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -103,6 +103,7 @@ var rpcHandlers = map[string]func(*Server, request.Params) (interface{}, *respon "getcommittee": (*Server).getCommittee, "getconnectioncount": (*Server).getConnectionCount, "getcontractstate": (*Server).getContractState, + "getnativecontracts": (*Server).getNativeContracts, "getnep17balances": (*Server).getNEP17Balances, "getnep17transfers": (*Server).getNEP17Transfers, "getpeers": (*Server).getPeers, @@ -986,6 +987,10 @@ func (s *Server) getContractState(reqParams request.Params) (interface{}, *respo return cs, nil } +func (s *Server) getNativeContracts(_ request.Params) (interface{}, *response.Error) { + return s.chain.GetNatives(), nil +} + // getBlockSysFee returns the system fees of the block, based on the specified index. func (s *Server) getBlockSysFee(reqParams request.Params) (interface{}, *response.Error) { param := reqParams.ValueWithType(0, request.NumberT) diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index fe5a102d0..fc68ae6e3 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -552,6 +552,22 @@ var rpcTestCases = map[string][]rpcTestCase{ }, }, }, + "getnativecontracts": { + { + params: "[]", + result: func(e *executor) interface{} { + return new([]state.NativeContract) + }, + check: func(t *testing.T, e *executor, res interface{}) { + lst := res.(*[]state.NativeContract) + for i := range *lst { + cs := e.chain.GetContractState((*lst)[i].Hash) + require.NotNil(t, cs) + require.True(t, cs.ID <= 0) + } + }, + }, + }, "getpeers": { { params: "[]",