rpc: refactor getDecimals

Use existing functions to invoke smartcontract's
method instead of constructing ad-hoc script.
This commit is contained in:
Evgenii Stratonikov 2020-03-11 15:07:14 +03:00
parent 05544a1510
commit d25dddc780

View file

@ -6,7 +6,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"math" "math"
"math/big"
"net/http" "net/http"
"strconv" "strconv"
@ -23,9 +22,9 @@ import (
"github.com/nspcc-dev/neo-go/pkg/rpc/request" "github.com/nspcc-dev/neo-go/pkg/rpc/request"
"github.com/nspcc-dev/neo-go/pkg/rpc/response" "github.com/nspcc-dev/neo-go/pkg/rpc/response"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/pkg/errors" "github.com/pkg/errors"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -515,29 +514,33 @@ func (s *Server) getDecimals(h util.Uint160, cache map[util.Uint160]int64) (int6
if d, ok := cache[h]; ok { if d, ok := cache[h]; ok {
return d, nil return d, nil
} }
w := io.NewBufBinWriter() script, err := request.CreateFunctionInvocationScript(h, request.Params{
emit.Int(w.BinWriter, 0) {
emit.Opcode(w.BinWriter, opcode.NEWARRAY) Type: request.StringT,
emit.String(w.BinWriter, "decimals") Value: "decimals",
emit.AppCall(w.BinWriter, h, true) },
v, _ := s.chain.GetTestVM() {
v.LoadScript(w.Bytes()) Type: request.ArrayT,
if err := v.Run(); err != nil { Value: []request.Param{},
},
})
if err != nil {
return 0, err return 0, err
} }
res := v.PopResult() res := s.runScriptInVM(script)
if res == nil { if res == nil || res.State != "HALT" || len(res.Stack) == 0 {
return 0, errors.New("execution error")
}
var d int64
switch item := res.Stack[len(res.Stack)-1]; item.Type {
case smartcontract.IntegerType:
d = item.Value.(int64)
case smartcontract.ByteArrayType:
d = emit.BytesToInt(item.Value.([]byte)).Int64()
default:
return 0, errors.New("invalid result") return 0, errors.New("invalid result")
} }
bi, ok := res.(*big.Int)
if !ok {
bs, ok := res.([]byte)
if !ok {
return 0, errors.New("invalid result")
}
bi = emit.BytesToInt(bs)
}
d := bi.Int64()
if d < 0 { if d < 0 {
return 0, errors.New("negative decimals") return 0, errors.New("negative decimals")
} }