Duniter Squid crash for out of range integer

INSERT INTO "universal_dividend"("id", "block_number", "timestamp", "amount", "monetary_mass", "members_count", "event_id") VALUES ($1, $2, $3, $4, $5, $6, $7)
      "0003501642-13521-000001",
      3501642,
      "2024-10-17T21:20:54.001Z",
      2163069901,
      "841340712106256",
      2944,
      "0003501642-13521-000001"

Due to universal dividend crazy growth rate in gdev, the monetary mass quickly reached a value too large for 32 bits integer type: 2163069901 > 2^31 (2147483648), causing an indexer crash.
Duniter is currently using 64 bits integers (see Nombre de décimales et durée maximale sans rotation de base).

It would be nice to double check the computation to make sure we do not reach this limit even if Duniter has a lot of users.

And squid must use correct size integers.

Here is current schema.graphql:

type UniversalDividend @entity {
  blockNumber: Int!
  event: Event!
  timestamp: DateTime!
  amount: Int!
  monetaryMass: BigInt!
  membersCount: Int!
}

Using BigInt for monetaryMass but not for amount.

For Ğ1, 64 bits is enough. For ĞDev I don’t know but probably.

But 32 bits is obviously not enough, even for amounts in Ğ1.

1 Like

Parameters of ĞDev network are:

// in /runtime/gdev/src/parameters.rs

// 0.002_381_440 = 0.0488^2
pub const SquareMoneyGrowthRate: Perbill = Perbill::from_parts(2_381_440);

# in /resources/gdev.yaml

# Time between 2 UDs, in milliseconds. 4 hours.
ud_creation_period: 14400000
# Time between 2 UD reevaluations, in milliseconds. 24 hours.
ud_reeval_period: 86400000

ĞDev network 800 was launched on 5th february (ĞDev Runtime 800 -- new network - #13 by cgeek).

This means that in 259 days (~ 9 months), we had 1554 universal dividends. But this UDs were reevaluated every day instead of every 6 month. Even with decreasing member count, this exponential growth lead to a UD value of 2163069901 which is too high for 32 bits integer type.

julia code for simulation
# ud count between reevals
udcountbetweenreevals(udreevalperiod=86_400_000, udcreationperiod=14_400_000) = udreevalperiod/udcreationperiod
# growth factor depending on params
factor(csquare=0.002_381_440, udcountbetweenreevals=udcountbetweenreevals()) = csquare/udcountbetweenreevals
# ud formula
udtplusone(udt, monetarymass, membercount; factor=factor()) = udt + Int(floor(factor * monetarymass / membercount))

monetarymass = [9_173_584_257] # in cents
membercount = [8000]
uds = [1000] # 10 ĞD in cents

# simulation step (each ud reeval)
function step(factor=factor(), udcountbetweenreevals=udcountbetweenreevals())
    udt = uds[end]
    membercountt = membercount[end]
    monetarymasst = monetarymass[end]
    # do not change member count
    # push!(membercount, membercountt)
    # update monetary mass
    push!(monetarymass, monetarymasst + udt * membercountt * udcountbetweenreevals)
    push!(uds, udtplusone(udt, monetarymasst, membercountt, factor=factor))
end

for i in 1:280
    step()
end

plot(uds, legend=false)
plot!([0,300],[2^31, 2^31])

image

I confirm that with these values and 8000 fixed member count, its normal to reach this size within ~270 days (270 reevals).

The problem is that with this growth rate, ĞDev would reach 64 bit limit within ~ 730 days.

Conclusion

  • i’ll use BigInt in squid for ud amount too
  • but for next test network, we should increase the reeval period a lot

Or reduce the growth rate, if we still want to test reevaluations easily (that could be useful to wallet developers).

1 Like