Skip to content

Commit

Permalink
Merge pull request #93 from ElrondNetwork/dev-to-master-1oct
Browse files Browse the repository at this point in the history
Dev to master
  • Loading branch information
iulianpascalau authored Oct 1, 2020
2 parents 16a305f + 486803a commit 8fbf423
Show file tree
Hide file tree
Showing 26 changed files with 346 additions and 58 deletions.
1 change: 1 addition & 0 deletions api/address/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ import (
type FacadeHandler interface {
GetAccount(address string) (*data.Account, error)
GetTransactions(address string) ([]data.DatabaseTransaction, error)
GetShardIDForAddress(address string) (uint32, error)
GetValueForKey(address string, key string) (string, error)
}
36 changes: 36 additions & 0 deletions api/address/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func Routes(router *gin.RouterGroup) {
router.GET("/:address/balance", GetBalance)
router.GET("/:address/username", GetUsername)
router.GET("/:address/nonce", GetNonce)
router.GET("/:address/shard", GetShard)
router.GET("/:address/transactions", GetTransactions)
router.GET("/:address/key/:key", GetValueForKey)
}
Expand Down Expand Up @@ -152,3 +153,38 @@ func GetValueForKey(c *gin.Context) {

shared.RespondWith(c, http.StatusOK, gin.H{"value": value}, "", data.ReturnCodeSuccess)
}

// GetShard returns the shard for the given address based on the current proxy's configuration
func GetShard(c *gin.Context) {
ef, ok := c.MustGet("elrondProxyFacade").(FacadeHandler)
if !ok {
shared.RespondWithInvalidAppContext(c)
return
}

addr := c.Param("address")
if addr == "" {
shared.RespondWith(
c,
http.StatusBadRequest,
nil,
fmt.Sprintf("%v: %v", errors.ErrComputeShardForAddress, errors.ErrEmptyAddress),
data.ReturnCodeRequestError,
)
return
}

shardID, err := ef.GetShardIDForAddress(addr)
if err != nil {
shared.RespondWith(
c,
http.StatusInternalServerError,
nil,
fmt.Sprintf("%s: %s", errors.ErrComputeShardForAddress.Error(), err.Error()),
data.ReturnCodeInternalError,
)
return
}

shared.RespondWith(c, http.StatusOK, gin.H{"shardID": shardID}, "", data.ReturnCodeSuccess)
}
73 changes: 73 additions & 0 deletions api/address/routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"math/big"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/ElrondNetwork/elrond-proxy-go/api"
Expand Down Expand Up @@ -61,6 +62,15 @@ type usernameResponse struct {
Data usernameResponseData
}

type getShardResponseData struct {
ShardID uint32 `json:"shardID"`
}

type getShardResponse struct {
GeneralResponse
Data getShardResponseData
}

type nonceResponseData struct {
Nonce uint64 `json:"nonce"`
}
Expand Down Expand Up @@ -323,3 +333,66 @@ func TestGetNonce_ReturnsSuccessfully(t *testing.T) {
assert.Equal(t, uint64(1), nonceResponse.Data.Nonce)
assert.Empty(t, nonceResponse.Error)
}

// ---- GetShard
func TestGetShard_FailsWithWrongFacadeTypeConversion(t *testing.T) {
t.Parallel()

ws := startNodeServerWrongFacade()
req, _ := http.NewRequest("GET", "/address/address/shard", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

statusRsp := getShardResponse{}
loadResponse(resp.Body, &statusRsp)

assert.Equal(t, resp.Code, http.StatusInternalServerError)
assert.Equal(t, statusRsp.Error, apiErrors.ErrInvalidAppContext.Error())
}

func TestGetShard_FailWhenFacadeErrors(t *testing.T) {
t.Parallel()

expectedErr := errors.New("cannot compute shard ID")
facade := mock.Facade{
GetShardIDForAddressHandler: func(_ string) (uint32, error) {
return 0, expectedErr
},
}
ws := startNodeServer(&facade)

reqAddress := "test"
req, _ := http.NewRequest("GET", fmt.Sprintf("/address/%s/shard", reqAddress), nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

shardResponse := getShardResponse{}
loadResponse(resp.Body, &shardResponse)

assert.Equal(t, http.StatusInternalServerError, resp.Code)
assert.True(t, strings.Contains(shardResponse.Error, expectedErr.Error()))
}

func TestGetShard_ReturnsSuccessfully(t *testing.T) {
t.Parallel()

expectedShardID := uint32(37)
facade := mock.Facade{
GetShardIDForAddressHandler: func(_ string) (uint32, error) {
return expectedShardID, nil
},
}
ws := startNodeServer(&facade)

reqAddress := "test"
req, _ := http.NewRequest("GET", fmt.Sprintf("/address/%s/shard", reqAddress), nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

shardResponse := getShardResponse{}
loadResponse(resp.Body, &shardResponse)

assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, shardResponse.Data.ShardID, expectedShardID)
assert.Empty(t, shardResponse.Error)
}
3 changes: 3 additions & 0 deletions api/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ var ErrInvalidAppContext = errors.New("invalid app context")
// ErrGetValueForKey signals an error in getting the value of a key for an account
var ErrGetValueForKey = errors.New("get value for key error")

// ErrComputeShardForAddress signals an error in computing the shard ID for a given address
var ErrComputeShardForAddress = errors.New("compute shard ID for address error")

// ErrEmptyAddress signals that an empty address was provided
var ErrEmptyAddress = errors.New("address is empty")

Expand Down
3 changes: 2 additions & 1 deletion api/hyperblock/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import (
"github.com/ElrondNetwork/elrond-proxy-go/data"
)

type facadeHandler interface {
// FacadeHandler defines the actions needed for fetching the hyperblocks from the nodes
type FacadeHandler interface {
GetHyperBlockByNonce(nonce uint64) (*data.HyperblockApiResponse, error)
GetHyperBlockByHash(hash string) (*data.HyperblockApiResponse, error)
}
4 changes: 2 additions & 2 deletions api/hyperblock/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func Routes(router *gin.RouterGroup) {

// ByHashHandler handles "by-hash" requests
func ByHashHandler(c *gin.Context) {
epf, ok := c.MustGet("elrondProxyFacade").(facadeHandler)
epf, ok := c.MustGet("elrondProxyFacade").(FacadeHandler)
if !ok {
shared.RespondWithInvalidAppContext(c)
return
Expand All @@ -42,7 +42,7 @@ func ByHashHandler(c *gin.Context) {

// ByNonceHandler handles "by-nonce" requests
func ByNonceHandler(c *gin.Context) {
epf, ok := c.MustGet("elrondProxyFacade").(facadeHandler)
epf, ok := c.MustGet("elrondProxyFacade").(FacadeHandler)
if !ok {
shared.RespondWithInvalidAppContext(c)
return
Expand Down
12 changes: 9 additions & 3 deletions api/mock/facade.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@ package mock
import (
"math/big"

"github.com/ElrondNetwork/elrond-go/data/vm"
"github.com/ElrondNetwork/elrond-proxy-go/data"
vmcommon "github.com/ElrondNetwork/elrond-vm-common"
)

// Facade is the mock implementation of a node's router handler
type Facade struct {
IsFaucetEnabledHandler func() bool
GetAccountHandler func(address string) (*data.Account, error)
GetShardIDForAddressHandler func(address string) (uint32, error)
GetValueForKeyHandler func(address string, key string) (string, error)
GetTransactionsHandler func(address string) ([]data.DatabaseTransaction, error)
GetTransactionHandler func(txHash string) (*data.FullTransaction, error)
SendTransactionHandler func(tx *data.Transaction) (int, string, error)
SendMultipleTransactionsHandler func(txs []*data.Transaction) (data.MultipleTransactionsResponseData, error)
SimulateTransactionHandler func(tx *data.Transaction) (*data.ResponseTransactionSimulation, error)
SendUserFundsCalled func(receiver string, value *big.Int) error
ExecuteSCQueryHandler func(query *data.SCQuery) (*vmcommon.VMOutput, error)
ExecuteSCQueryHandler func(query *data.SCQuery) (*vm.VMOutputApi, error)
GetHeartbeatDataHandler func() (*data.HeartbeatResponse, error)
ValidatorStatisticsHandler func() (map[string]*data.ValidatorApiResponse, error)
TransactionCostRequestHandler func(tx *data.Transaction) (string, error)
Expand Down Expand Up @@ -75,6 +76,11 @@ func (f *Facade) GetValueForKey(address string, key string) (string, error) {
return f.GetValueForKeyHandler(address, key)
}

// GetShardIDForAddress -
func (f *Facade) GetShardIDForAddress(address string) (uint32, error) {
return f.GetShardIDForAddressHandler(address)
}

// GetTransactions -
func (f *Facade) GetTransactions(address string) ([]data.DatabaseTransaction, error) {
return f.GetTransactionsHandler(address)
Expand Down Expand Up @@ -121,7 +127,7 @@ func (f *Facade) SendUserFunds(receiver string, value *big.Int) error {
}

// ExecuteSCQuery -
func (f *Facade) ExecuteSCQuery(query *data.SCQuery) (*vmcommon.VMOutput, error) {
func (f *Facade) ExecuteSCQuery(query *data.SCQuery) (*vm.VMOutputApi, error) {
return f.ExecuteSCQueryHandler(query)
}

Expand Down
4 changes: 2 additions & 2 deletions api/vmValues/interface.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package vmValues

import (
"github.com/ElrondNetwork/elrond-go/data/vm"
"github.com/ElrondNetwork/elrond-proxy-go/data"
vmcommon "github.com/ElrondNetwork/elrond-vm-common"
)

// FacadeHandler interface defines methods that can be used from `elrondFacade` context variable
type FacadeHandler interface {
ExecuteSCQuery(*data.SCQuery) (*vmcommon.VMOutput, error)
ExecuteSCQuery(*data.SCQuery) (*vm.VMOutputApi, error)
}
3 changes: 2 additions & 1 deletion api/vmValues/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"net/http"

"github.com/ElrondNetwork/elrond-go/data/vm"
apiErrors "github.com/ElrondNetwork/elrond-proxy-go/api/errors"
"github.com/ElrondNetwork/elrond-proxy-go/api/shared"
"github.com/ElrondNetwork/elrond-proxy-go/data"
Expand Down Expand Up @@ -72,7 +73,7 @@ func executeQuery(context *gin.Context) {
returnOkResponse(context, vmOutput)
}

func doExecuteQuery(context *gin.Context) (*vmcommon.VMOutput, error) {
func doExecuteQuery(context *gin.Context) (*vm.VMOutputApi, error) {
facade, ok := context.MustGet("elrondProxyFacade").(FacadeHandler)
if !ok {
return nil, apiErrors.ErrInvalidAppContext
Expand Down
34 changes: 17 additions & 17 deletions api/vmValues/routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import (
"net/http/httptest"
"testing"

"github.com/ElrondNetwork/elrond-go/data/vm"
apiErrors "github.com/ElrondNetwork/elrond-proxy-go/api/errors"
"github.com/ElrondNetwork/elrond-proxy-go/api/mock"
"github.com/ElrondNetwork/elrond-proxy-go/data"
vmcommon "github.com/ElrondNetwork/elrond-vm-common"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"
Expand All @@ -31,7 +31,7 @@ type simpleResponse struct {
}

type vmOutputResponse struct {
Data *vmcommon.VMOutput `json:"data"`
Data *vm.VMOutputApi `json:"data"`
}

type vmOutputGenericResponse struct {
Expand All @@ -51,8 +51,8 @@ func TestGetHex_ShouldWork(t *testing.T) {
valueBuff, _ := hex.DecodeString("DEADBEEF")

facade := mock.Facade{
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vmcommon.VMOutput, e error) {
return &vmcommon.VMOutput{
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vm.VMOutputApi, e error) {
return &vm.VMOutputApi{
ReturnData: [][]byte{valueBuff},
}, nil
},
Expand All @@ -78,8 +78,8 @@ func TestGetString_ShouldWork(t *testing.T) {
valueBuff := "DEADBEEF"

facade := mock.Facade{
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vmcommon.VMOutput, e error) {
return &vmcommon.VMOutput{
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vm.VMOutputApi, e error) {
return &vm.VMOutputApi{
ReturnData: [][]byte{[]byte(valueBuff)},
}, nil
},
Expand All @@ -105,10 +105,10 @@ func TestGetInt_ShouldWork(t *testing.T) {
value := "1234567"

facade := mock.Facade{
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vmcommon.VMOutput, e error) {
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vm.VMOutputApi, e error) {
returnData := big.NewInt(0)
returnData.SetString(value, 10)
return &vmcommon.VMOutput{
return &vm.VMOutputApi{
ReturnData: [][]byte{returnData.Bytes()},
}, nil
},
Expand All @@ -132,9 +132,9 @@ func TestQuery_ShouldWork(t *testing.T) {
t.Parallel()

facade := mock.Facade{
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vmcommon.VMOutput, e error) {
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vm.VMOutputApi, e error) {

return &vmcommon.VMOutput{
return &vm.VMOutputApi{
ReturnData: [][]byte{big.NewInt(42).Bytes()},
}, nil
},
Expand Down Expand Up @@ -171,7 +171,7 @@ func TestAllRoutes_FacadeErrorsShouldErr(t *testing.T) {

errExpected := errors.New("some random error")
facade := mock.Facade{
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vmcommon.VMOutput, e error) {
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vm.VMOutputApi, e error) {
return nil, errExpected
},
}
Expand All @@ -190,8 +190,8 @@ func TestAllRoutes_WhenBadArgumentsShouldErr(t *testing.T) {

errExpected := errors.New("not a valid hex string")
facade := mock.Facade{
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vmcommon.VMOutput, e error) {
return &vmcommon.VMOutput{}, nil
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vm.VMOutputApi, e error) {
return &vm.VMOutputApi{}, nil
},
}

Expand All @@ -209,8 +209,8 @@ func TestAllRoutes_WhenNoVMReturnDataShouldErr(t *testing.T) {

errExpected := errors.New("no return data")
facade := mock.Facade{
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vmcommon.VMOutput, e error) {
return &vmcommon.VMOutput{}, nil
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vm.VMOutputApi, e error) {
return &vm.VMOutputApi{}, nil
},
}

Expand All @@ -227,8 +227,8 @@ func TestAllRoutes_WhenBadJsonShouldErr(t *testing.T) {
t.Parallel()

facade := mock.Facade{
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vmcommon.VMOutput, e error) {
return &vmcommon.VMOutput{}, nil
ExecuteSCQueryHandler: func(query *data.SCQuery) (vmOutput *vm.VMOutputApi, e error) {
return &vm.VMOutputApi{}, nil
},
}

Expand Down
2 changes: 2 additions & 0 deletions data/nodeStatus.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ type PubKeyHeartbeat struct {
ComputedShardID uint32 `json:"computedShardID"`
PeerType string `json:"peerType"`
IsActive bool `json:"isActive"`
Nonce uint64 `json:"nonce"`
NumInstances uint64 `json:"numInstances"`
}

// StatusResponse represents the status received when trying to find an online node
Expand Down
4 changes: 2 additions & 2 deletions data/vmValues.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package data

import (
vmcommon "github.com/ElrondNetwork/elrond-vm-common"
"github.com/ElrondNetwork/elrond-go/data/vm"
)

// VmValuesResponseData follows the format of the data field in an API response for a VM values query
type VmValuesResponseData struct {
Data *vmcommon.VMOutput `json:"data"`
Data *vm.VMOutputApi `json:"data"`
}

// ResponseVmValue defines a wrapper over string containing returned data in hex format
Expand Down
Loading

0 comments on commit 8fbf423

Please sign in to comment.