From 3e6b4b6e364482a8197415e22e3c792835653864 Mon Sep 17 00:00:00 2001 From: Jordi Pinyana Date: Wed, 21 Jun 2023 18:45:09 +0200 Subject: [PATCH] api: /chain/dateToBlock fix overflow for big timestamps --- api/chain.go | 2 +- api/wallet.go | 8 ++++---- vochain/vochaininfo/vochaininfo.go | 19 ++++++++++++------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/api/chain.go b/api/chain.go index 774a97a65..d0ecfd581 100644 --- a/api/chain.go +++ b/api/chain.go @@ -333,7 +333,7 @@ func (a *API) chainEstimateHeightHandler(msg *apirest.APIdata, ctx *httprouter.H return err } data, err := json.Marshal(struct { - Height uint32 `json:"height"` + Height uint64 `json:"height"` }{Height: height}, ) if err != nil { diff --git a/api/wallet.go b/api/wallet.go index e7f5fc9f9..4d397bc2a 100644 --- a/api/wallet.go +++ b/api/wallet.go @@ -309,7 +309,7 @@ func (a *API) walletElectionHandler(msg *apirest.APIdata, ctx *httprouter.HTTPCo } // Set startBlock and endBlock - var startBlock uint32 + var startBlock uint64 // if start date is empty, do not attempt to parse it. Set startBlock to 0, starting the // election immediately. Otherwise, ensure the startBlock is in the future if !description.StartDate.IsZero() { @@ -336,7 +336,7 @@ func (a *API) walletElectionHandler(msg *apirest.APIdata, ctx *httprouter.HTTPCo if startBlock == 0 { // If startBlock is set to 0 (process starts asap), set the blockcount to the desired // end block, minus the expected start block of the process - blockCount = blockCount - uint32(a.vocinfo.Height()) + 3 + blockCount = blockCount - uint64(a.vocinfo.Height()) + 3 } // Set the envelope and process models @@ -421,8 +421,8 @@ func (a *API) walletElectionHandler(msg *apirest.APIdata, ctx *httprouter.HTTPCo // Build the process transaction process := &models.Process{ EntityId: wallet.Address().Bytes(), - StartBlock: startBlock, - BlockCount: blockCount, + StartBlock: uint32(startBlock), + BlockCount: uint32(blockCount), CensusRoot: root, CensusURI: &description.Census.URL, Status: models.ProcessStatus_READY, diff --git a/vochain/vochaininfo/vochaininfo.go b/vochain/vochaininfo/vochaininfo.go index 6061f8b84..a65b38d98 100644 --- a/vochain/vochaininfo/vochaininfo.go +++ b/vochain/vochaininfo/vochaininfo.go @@ -3,6 +3,7 @@ package vochaininfo import ( "context" "fmt" + "math" "sync" "time" @@ -58,27 +59,31 @@ func (vi *VochainInfo) BlockTimes() *[5]int32 { } // EstimateBlockHeight provides an estimation time for a future blockchain height number. -func (vi *VochainInfo) EstimateBlockHeight(target time.Time) (uint32, error) { +func (vi *VochainInfo) EstimateBlockHeight(target time.Time) (uint64, error) { currentTime := time.Now() // diff time in seconds diffTime := target.Unix() - currentTime.Unix() // block time in ms times := vi.BlockTimes() - getMaxTimeFrom := func(i int) uint32 { + getMaxTimeFrom := func(i int) uint64 { for ; i >= 0; i-- { if times[i] != 0 { - return uint32(times[i]) + return uint64(times[i]) } } return 10000 // fallback } inPast := diffTime < 0 absDiff := diffTime + // check diff is not too big + if absDiff > math.MaxUint64/1000 { + return 0, fmt.Errorf("target time %v is too far in the future", target) + } if inPast { absDiff = -absDiff } - t := uint32(0) + t := uint64(0) switch { // if less than around 15 minutes missing case absDiff < 900: @@ -86,14 +91,14 @@ func (vi *VochainInfo) EstimateBlockHeight(target time.Time) (uint32, error) { // if less than around 6 hours missing case absDiff < 21600: t = getMaxTimeFrom(3) - // if less than around 6 hours missing + // if more than around 6 hours missing default: t = getMaxTimeFrom(4) } // Multiply by 1000 because t is represented in seconds, not ms. // Dividing t first can floor the integer, leading to divide-by-zero - currentHeight := uint32(vi.Height()) - blockDiff := (uint32(absDiff*1000) / t) + currentHeight := uint64(vi.Height()) + blockDiff := (uint64(absDiff*1000) / t) if inPast { if blockDiff > currentHeight { return 0, fmt.Errorf("target time %v is before origin", target)