Skip to content

Commit

Permalink
fix decimal precision
Browse files Browse the repository at this point in the history
  • Loading branch information
Ji Qiren committed Jun 28, 2022
1 parent ee63584 commit ed76e54
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 57 deletions.
4 changes: 4 additions & 0 deletions common/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ func RescalePair(a *Decimal, b *Decimal) (*Decimal, *Decimal, error) {
return a, bChanged, nil
}

func NewDecimalZero() *Decimal {
return &Decimal{Value: 0, Scale: 0}
}

func NewDecimalFromInt(v int) *Decimal {
return &Decimal{Value: int64(v), Scale: 0}
}
Expand Down
19 changes: 9 additions & 10 deletions rpc/api_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,7 @@ func (as *APIService) GetAccount(ctx context.Context, req *rpcpb.GetAccountReque
ret := toPbAccount(acc)

// pack balance and ram information
balance := dbVisitor.TokenBalanceFixed("iost", req.GetName()).Float64()
ret.Balance = balance
balance := dbVisitor.TokenBalanceDecimal("iost", req.GetName())
ramInfo := dbVisitor.RAMHandler.GetAccountRAMInfo(req.GetName())
ret.RamInfo = &rpcpb.Account_RAMInfo{
Available: ramInfo.Available,
Expand Down Expand Up @@ -344,10 +343,10 @@ func (as *APIService) GetAccount(ctx context.Context, req *rpcpb.GetAccountReque
}

// pack frozen balance information
frozen := dbVisitor.AllFreezedTokenBalanceFixed("iost", req.GetName())
frozen := dbVisitor.AllFreezedTokenBalanceDecimal("iost", req.GetName())
unfrozen, stillFrozen := as.getUnfrozenToken(frozen, req.ByLongestChain)
ret.FrozenBalances = stillFrozen
ret.Balance += unfrozen
ret.Balance = unfrozen.Add(balance).Float64()

voteInfo := dbVisitor.GetAccountVoteInfo(req.GetName())
for _, v := range voteInfo {
Expand Down Expand Up @@ -376,12 +375,12 @@ func (as *APIService) GetTokenBalance(ctx context.Context, req *rpcpb.GetTokenBa
//if acc == nil {
// return nil, errors.New("account not found")
//}
balance := dbVisitor.TokenBalanceFixed(req.GetToken(), req.GetAccount()).Float64()
balance := dbVisitor.TokenBalanceDecimal(req.GetToken(), req.GetAccount())
// pack frozen balance information
frozen := dbVisitor.AllFreezedTokenBalanceFixed(req.GetToken(), req.GetAccount())
frozen := dbVisitor.AllFreezedTokenBalanceDecimal(req.GetToken(), req.GetAccount())
unfrozen, stillFrozen := as.getUnfrozenToken(frozen, req.ByLongestChain)
return &rpcpb.GetTokenBalanceResponse{
Balance: balance + unfrozen,
Balance: balance.Add(unfrozen).Float64(),
FrozenBalances: stillFrozen,
}, nil
}
Expand Down Expand Up @@ -1026,18 +1025,18 @@ func (as *APIService) getStateDBVisitor(longestChain bool) (*database.Visitor, *
return nil, nil, err
}

func (as *APIService) getUnfrozenToken(frozens []database.FreezeItemFixed, longestChain bool) (float64, []*rpcpb.FrozenBalance) {
func (as *APIService) getUnfrozenToken(frozens []database.FreezeItemDecimal, longestChain bool) (*common.Decimal, []*rpcpb.FrozenBalance) {
var blockTime int64
if longestChain {
blockTime = as.bc.Head().Head.Time
} else {
blockTime = as.bc.LinkedRoot().Head.Time
}
var unfrozen float64
var unfrozen *common.Decimal = common.NewDecimalZero()
var stillFrozen []*rpcpb.FrozenBalance
for _, f := range frozens {
if f.Ftime <= blockTime {
unfrozen += f.Amount.Float64()
unfrozen = unfrozen.Add(&f.Amount)
} else {
stillFrozen = append(stillFrozen, &rpcpb.FrozenBalance{
Amount: f.Amount.Float64(),
Expand Down
2 changes: 1 addition & 1 deletion test/integration/gas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ func TestGas_PledgeunpledgeForOther(t *testing.T) {
signerList := make(map[string]bool)
signerList[otherAcc+"@active"] = true
h.Context().Set("signer_list", signerList)
h.DB().SetTokenBalanceFixed("iost", otherAcc, "20")
h.DB().SetTokenBalanceDecimal("iost", otherAcc, "20")
_, _, err = e.LoadAndCall(h, code, "pledge", otherAcc, otherAcc, "20")
So(err, ShouldBeNil)
_, _, err = e.LoadAndCall(h, code, "unpledge", otherAcc, otherAcc, "20")
Expand Down
30 changes: 15 additions & 15 deletions test/integration/verifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ func TestTransfer(t *testing.T) {
createToken(t, s, acc)

Reset(func() {
s.Visitor.SetTokenBalanceFixed("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceFixed("iost", acc1.ID, "0")
s.Visitor.SetTokenBalanceDecimal("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", acc1.ID, "0")
s.SetGas(acc.ID, 100000)
s.SetRAM(acc.ID, 10000)
})
Expand Down Expand Up @@ -186,8 +186,8 @@ func TestAmountLimit(t *testing.T) {
s.SetRAM(acc0.ID, 10000)

Reset(func() {
s.Visitor.SetTokenBalanceFixed("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceFixed("iost", acc1.ID, "0")
s.Visitor.SetTokenBalanceDecimal("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", acc1.ID, "0")
s.SetGas(acc0.ID, 100000)
s.SetRAM(acc0.ID, 10000)
})
Expand Down Expand Up @@ -329,7 +329,7 @@ func TestAmountLimit(t *testing.T) {

Convey("test amount limit transfer from multi signers", func() {
s.SetAccount(acc2.ToAccount())
s.Visitor.SetTokenBalanceFixed("iost", acc2.ID, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", acc2.ID, "1000")

trx := tx.NewTx([]*tx.Action{{
Contract: "Contracttransfer",
Expand Down Expand Up @@ -397,8 +397,8 @@ func TestTxAmountLimit(t *testing.T) {
s.SetRAM(acc0.ID, 10000)

Reset(func() {
s.Visitor.SetTokenBalanceFixed("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceFixed("iost", acc1.ID, "0")
s.Visitor.SetTokenBalanceDecimal("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", acc1.ID, "0")
s.SetGas(acc0.ID, 100000)
s.SetRAM(acc0.ID, 10000)
})
Expand Down Expand Up @@ -528,8 +528,8 @@ func TestTokenMemo(t *testing.T) {
s.SetRAM(acc0.ID, 10000)

Reset(func() {
s.Visitor.SetTokenBalanceFixed("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceFixed("iost", acc1.ID, "0")
s.Visitor.SetTokenBalanceDecimal("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", acc1.ID, "0")
s.SetGas(acc0.ID, 100000)
s.SetRAM(acc0.ID, 10000)
})
Expand Down Expand Up @@ -591,7 +591,7 @@ func TestNativeVM_GasPledgeShortCut(t *testing.T) {
So(r.Status.Message, ShouldEqual, "")
txGasUsage := r.GasUsage / 100
So(s.GetGas(acc0.ID), ShouldEqual, expectedGasAfterPlegde-txGasUsage)
So(s.Visitor.TokenBalanceFixed("iost", acc0.ID).String(), ShouldEqual, strconv.Itoa(int(initialBalance-pledgeAmount)))
So(s.Visitor.TokenBalanceDecimal("iost", acc0.ID).String(), ShouldEqual, strconv.Itoa(int(initialBalance-pledgeAmount)))
})
SkipConvey("vm can kill tx if gas limit is not enough(TODO it is not possible in current code)", func() {
s.SetGas(acc0.ID, 0)
Expand All @@ -609,7 +609,7 @@ func TestNativeVM_GasPledgeShortCut(t *testing.T) {
So(r.Status.Message, ShouldContainSubstring, "out of gas")
So(r.Status.Code, ShouldEqual, tx.ErrorRuntime)
So(s.GetGas(acc0.ID), ShouldEqual, expectedGasAfterPlegde-txGasLimit)
So(s.Visitor.TokenBalanceFixed("iost", acc0.ID).String(), ShouldEqual, strconv.Itoa(int(initialBalance-pledgeAmount)))
So(s.Visitor.TokenBalanceDecimal("iost", acc0.ID).String(), ShouldEqual, strconv.Itoa(int(initialBalance-pledgeAmount)))
})
})
}
Expand Down Expand Up @@ -709,8 +709,8 @@ func TestGasLimit2(t *testing.T) {
assert.NotNil(t, ca)
s.SetContract(ca)

s.Visitor.SetTokenBalanceFixed("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceFixed("iost", acc1.ID, "0")
s.Visitor.SetTokenBalanceDecimal("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", acc1.ID, "0")
s.SetGas(acc0.ID, 2000000)
s.SetRAM(acc0.ID, 10000)

Expand All @@ -733,8 +733,8 @@ func TestGasLimit2(t *testing.T) {
assert.Equal(t, "20", balance2.String())

// out of gas
s.Visitor.SetTokenBalanceFixed("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceFixed("iost", acc1.ID, "0")
s.Visitor.SetTokenBalanceDecimal("iost", acc0.ID, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", acc1.ID, "0")
s.SetGas(acc0.ID, 2000000)
s.SetRAM(acc0.ID, 10000)
acts = []*tx.Action{}
Expand Down
14 changes: 7 additions & 7 deletions test/integration/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ func Test_callWithAuth(t *testing.T) {
So(r.Status.Code, ShouldEqual, tx.Success)

Convey("test of callWithoutAuth", func() {
s.Visitor.SetTokenBalanceFixed("iost", cname, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", cname, "1000")
r, err := s.Call(cname, "withdrawWithoutAuth", fmt.Sprintf(`["%v", "%v"]`, acc0.ID, "10"), acc0.ID, acc0.KeyPair)
So(err, ShouldBeNil)
So(r.Status.Message, ShouldContainSubstring, "transaction has no permission")
s.Visitor.Commit()
})

Convey("test of callWithAuth", func() {
s.Visitor.SetTokenBalanceFixed("iost", cname, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", cname, "1000")
r, err = s.Call(cname, "withdraw", fmt.Sprintf(`["%v", "%v"]`, acc0.ID, "10"), acc0.ID, acc0.KeyPair)
s.Visitor.Commit()

Expand All @@ -56,7 +56,7 @@ func Test_callWithAuth(t *testing.T) {
})

Convey("test of callWithoutAuth after callWithAuth", func() {
s.Visitor.SetTokenBalanceFixed("iost", cname, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", cname, "1000")
r, err = s.Call(cname, "withdrawWithoutAuthAfterWithAuth", fmt.Sprintf(`["%v", "%v"]`, acc0.ID, "10"), acc0.ID, acc0.KeyPair)
s.Visitor.Commit()
So(err, ShouldBeNil)
Expand Down Expand Up @@ -267,7 +267,7 @@ func Test_RamPayer(t *testing.T) {
ram0 = s.GetRAM(acc0.ID)
ram4 := s.GetRAM(acc2.ID)
ram6 := s.GetRAM(acc3.ID)
s.Visitor.SetTokenBalanceFixed("iost", acc2.ID, "100")
s.Visitor.SetTokenBalanceDecimal("iost", acc2.ID, "100")
r, err = s.Call(cname0, "call", fmt.Sprintf(`["%v", "test", "%v"]`, cname1,
fmt.Sprintf(`[\"%v\", \"%v\"]`, acc2.ID, acc3.ID)), acc2.ID, acc2.KeyPair)
So(err, ShouldBeNil)
Expand Down Expand Up @@ -425,8 +425,8 @@ func Test_SpecialChar(t *testing.T) {
s.Visitor.Commit()
So(err, ShouldBeNil)

s.Visitor.SetTokenBalanceFixed("iost", acc.ID, "1000")
s.Visitor.SetTokenBalanceFixed("iost", acc1.ID, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", acc.ID, "1000")
s.Visitor.SetTokenBalanceDecimal("iost", acc1.ID, "1000")
params := []any{
acc.ID,
acc1.ID,
Expand All @@ -440,7 +440,7 @@ func Test_SpecialChar(t *testing.T) {
r, err := s.Call(cname, "transfer", string(paramsByte), acc.ID, acc.KeyPair)
So(err, ShouldBeNil)
So(r.Status.Message, ShouldEqual, "")
So(s.Visitor.TokenBalanceFixed("iost", acc1.ID).String(), ShouldEqual, "2000")
So(s.Visitor.TokenBalanceDecimal("iost", acc1.ID).String(), ShouldEqual, "2000")
})
}

Expand Down
10 changes: 5 additions & 5 deletions test/native/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ func TestToken_TransferFreeze(t *testing.T) {
So(err, ShouldBeNil)
So(true, ShouldEqual, len(rs) > 0 && rs[0] == "0")

freezedBalance := host.DB().FreezedTokenBalanceFixed("iost", "user0")
freezedBalance := host.DB().FreezedTokenBalanceDecimal("iost", "user0")
So(freezedBalance.String(), ShouldEqual, "22.3")

rs, cost, err = e.LoadAndCall(host, code, "balanceOf", "iost", "issuer0")
Expand All @@ -591,7 +591,7 @@ func TestToken_TransferFreeze(t *testing.T) {
So(err, ShouldBeNil)
So(true, ShouldEqual, len(rs) > 0 && rs[0] == "22.3")

freezedBalance = host.DB().FreezedTokenBalanceFixed("iost", "user0")
freezedBalance = host.DB().FreezedTokenBalanceDecimal("iost", "user0")
So(freezedBalance.String(), ShouldEqual, "0")

// transferFreeze to self
Expand All @@ -612,23 +612,23 @@ func TestToken_TransferFreeze(t *testing.T) {
So(err, ShouldBeNil)
So(true, ShouldEqual, len(rs) > 0 && rs[0] == "11.3")

freezedBalance = host.DB().FreezedTokenBalanceFixed("iost", "user0")
freezedBalance = host.DB().FreezedTokenBalanceDecimal("iost", "user0")
So(freezedBalance.String(), ShouldEqual, "11")

host.Context().Set("time", now+11)
rs, cost, err = e.LoadAndCall(host, code, "balanceOf", "iost", "user0")
So(err, ShouldBeNil)
So(true, ShouldEqual, len(rs) > 0 && rs[0] == "21.3")

freezedBalance = host.DB().FreezedTokenBalanceFixed("iost", "user0")
freezedBalance = host.DB().FreezedTokenBalanceDecimal("iost", "user0")
So(freezedBalance.String(), ShouldEqual, "1")

host.Context().Set("time", now+21)
rs, cost, err = e.LoadAndCall(host, code, "balanceOf", "iost", "user0")
So(err, ShouldBeNil)
So(true, ShouldEqual, len(rs) > 0 && rs[0] == "22.3")

freezedBalance = host.DB().FreezedTokenBalanceFixed("iost", "user0")
freezedBalance = host.DB().FreezedTokenBalanceDecimal("iost", "user0")
So(freezedBalance.String(), ShouldEqual, "0")
})

Expand Down
10 changes: 5 additions & 5 deletions test/native/token_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ func TestTokenV2_TransferFreeze(t *testing.T) {
So(err, ShouldBeNil)
So(true, ShouldEqual, len(rs) > 0 && rs[0] == "0")

freezedBalance := host.DB().FreezedTokenBalanceFixed("iost", "user0")
freezedBalance := host.DB().FreezedTokenBalanceDecimal("iost", "user0")
So(freezedBalance.String(), ShouldEqual, "22.3")

rs, cost, err = e.LoadAndCall(host, code, "balanceOf", "iost", "issuer0")
Expand All @@ -619,7 +619,7 @@ func TestTokenV2_TransferFreeze(t *testing.T) {
So(err, ShouldBeNil)
So(true, ShouldEqual, len(rs) > 0 && rs[0] == "22.3")

freezedBalance = host.DB().FreezedTokenBalanceFixed("iost", "user0")
freezedBalance = host.DB().FreezedTokenBalanceDecimal("iost", "user0")
So(freezedBalance.String(), ShouldEqual, "0")

// transferFreeze to self
Expand All @@ -640,23 +640,23 @@ func TestTokenV2_TransferFreeze(t *testing.T) {
So(err, ShouldBeNil)
So(true, ShouldEqual, len(rs) > 0 && rs[0] == "11.3")

freezedBalance = host.DB().FreezedTokenBalanceFixed("iost", "user0")
freezedBalance = host.DB().FreezedTokenBalanceDecimal("iost", "user0")
So(freezedBalance.String(), ShouldEqual, "11")

host.Context().Set("time", now+11)
rs, cost, err = e.LoadAndCall(host, code, "balanceOf", "iost", "user0")
So(err, ShouldBeNil)
So(true, ShouldEqual, len(rs) > 0 && rs[0] == "21.3")

freezedBalance = host.DB().FreezedTokenBalanceFixed("iost", "user0")
freezedBalance = host.DB().FreezedTokenBalanceDecimal("iost", "user0")
So(freezedBalance.String(), ShouldEqual, "1")

host.Context().Set("time", now+21)
rs, cost, err = e.LoadAndCall(host, code, "balanceOf", "iost", "user0")
So(err, ShouldBeNil)
So(true, ShouldEqual, len(rs) > 0 && rs[0] == "22.3")

freezedBalance = host.DB().FreezedTokenBalanceFixed("iost", "user0")
freezedBalance = host.DB().FreezedTokenBalanceDecimal("iost", "user0")
So(freezedBalance.String(), ShouldEqual, "0")
})

Expand Down
26 changes: 13 additions & 13 deletions vm/database/token_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ type FreezeItem struct {
Ftime int64
}

// FreezeItemFixed ...
type FreezeItemFixed struct {
// FreezeItemDecimal ...
type FreezeItemDecimal struct {
Amount common.Decimal
Ftime int64
}
Expand Down Expand Up @@ -53,8 +53,8 @@ func (m *TokenHandler) TokenBalance(tokenName, acc string) int64 {
return ib
}

// TokenBalanceFixed get token balance of acc
func (m *TokenHandler) TokenBalanceFixed(tokenName, acc string) *common.Decimal {
// TokenBalanceDecimal get token balance of acc
func (m *TokenHandler) TokenBalanceDecimal(tokenName, acc string) *common.Decimal {
ib := m.TokenBalance(tokenName, acc)
return &common.Decimal{Value: ib, Scale: m.Decimal(tokenName)}
}
Expand Down Expand Up @@ -97,18 +97,18 @@ func (m *TokenHandler) AllFreezedTokenBalance(tokenName, acc string) []FreezeIte
return freezeList
}

// AllFreezedTokenBalanceFixed get freezed token balance of acc
func (m *TokenHandler) AllFreezedTokenBalanceFixed(tokenName, acc string) []FreezeItemFixed {
// AllFreezedTokenBalanceDecimal get freezed token balance of acc
func (m *TokenHandler) AllFreezedTokenBalanceDecimal(tokenName, acc string) []FreezeItemDecimal {
freezeList := m.AllFreezedTokenBalance(tokenName, acc)
result := make([]FreezeItemFixed, 0)
result := make([]FreezeItemDecimal, 0)
for _, item := range freezeList {
result = append(result, FreezeItemFixed{Amount: common.Decimal{Value: item.Amount, Scale: m.Decimal(tokenName)}, Ftime: item.Ftime})
result = append(result, FreezeItemDecimal{Amount: common.Decimal{Value: item.Amount, Scale: m.Decimal(tokenName)}, Ftime: item.Ftime})
}
return result
}

// FreezedTokenBalanceFixed get token balance of acc
func (m *TokenHandler) FreezedTokenBalanceFixed(tokenName, acc string) *common.Decimal {
// FreezedTokenBalanceDecimal get token balance of acc
func (m *TokenHandler) FreezedTokenBalanceDecimal(tokenName, acc string) *common.Decimal {
ib := m.FreezedTokenBalance(tokenName, acc)
return &common.Decimal{Value: ib, Scale: m.Decimal(tokenName)}
}
Expand All @@ -118,11 +118,11 @@ func (m *TokenHandler) SetTokenBalance(tokenName, acc string, amount int64) {
m.db.Put(m.balanceKey(tokenName, acc), MustMarshal(amount))
}

// SetTokenBalanceFixed set token balance of acc, used for test
func (m *TokenHandler) SetTokenBalanceFixed(tokenName, acc string, amountStr string) {
// SetTokenBalanceDecimal set token balance of acc, used for test
func (m *TokenHandler) SetTokenBalanceDecimal(tokenName, acc string, amountStr string) {
amountNumber, err := common.NewDecimalFromString(amountStr, m.Decimal(tokenName))
if err != nil {
panic(errors.New("construct Fixed number failed. str = " + amountStr + ", decimal = " + fmt.Sprintf("%d", m.Decimal(tokenName))))
panic(errors.New("construct decimal number failed. str = " + amountStr + ", decimal = " + fmt.Sprintf("%d", m.Decimal(tokenName))))
}
m.db.Put(m.balanceKey(tokenName, acc), MustMarshal(amountNumber.Value))
}
Expand Down
2 changes: 1 addition & 1 deletion vm/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func CheckTxGasLimitValid(t *tx.Tx, currentGas *common.Decimal, dbVisitor *datab
if !(args[0] == t.Publisher && args[1] == t.Publisher) {
return defaultErr
}
balance := dbVisitor.TokenBalanceFixed("iost", t.Publisher)
balance := dbVisitor.TokenBalanceDecimal("iost", t.Publisher)
pledgeAmount, err := common.NewDecimalFromString(args[2].(string), 8)
if err != nil {
return fmt.Errorf("invalid gas pledge amount %v %v", err, args[2].(string))
Expand Down

0 comments on commit ed76e54

Please sign in to comment.