Skip to content

Commit

Permalink
types: Update encode/decode for Mortal Era
Browse files Browse the repository at this point in the history
  • Loading branch information
cdamian committed Aug 16, 2022
1 parent 77783c7 commit daa0719
Showing 1 changed file with 115 additions and 13 deletions.
128 changes: 115 additions & 13 deletions types/extrinsic_era.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
package types

import (
"errors"
"math"
"strconv"

"github.com/centrifuge/go-substrate-rpc-client/v4/scale"
)

Expand All @@ -39,38 +43,136 @@ func (e *ExtrinsicEra) Decode(decoder scale.Decoder) error {
return nil
}

e.IsMortalEra = true

second, err := decoder.ReadOneByte()
if err != nil {
return err
}

e.AsMortalEra = MortalEra{first, second}
encoded := uint64(first) + (uint64(second) << 8)
period := 2 << (encoded % (1 << 4))
quantizeFactor := period >> 12

if quantizeFactor <= 1 {
quantizeFactor = 1
}

phase := (encoded >> 4) * uint64(quantizeFactor)

if period >= 4 && phase < uint64(period) {
e.IsMortalEra = true
e.AsMortalEra = MortalEra{
First: U64(period),
Second: U64(phase),
}
return nil
}

return nil
return errors.New("invalid era")
}

func (e ExtrinsicEra) Encode(encoder scale.Encoder) error {
if e.IsImmortalEra {
return encoder.PushByte(0)
}

err := encoder.PushByte(e.AsMortalEra.First)
if err != nil {
return err
// let quantize_factor = (*period as u64 >> 12).max(1);
quantizeFactor := e.AsMortalEra.First >> 12

if quantizeFactor <= 1 {
quantizeFactor = 1
}

err = encoder.PushByte(e.AsMortalEra.Second)
if err != nil {
return err
// let encoded = (period.trailing_zeros() - 1).max(1).min(15) as u16 |
// ((phase / quantize_factor) << 4) as u16;
trailingZeroes := getTrailingZeroes(e.AsMortalEra.First) - 1

if trailingZeroes <= 1 {
trailingZeroes = 1
}

if trailingZeroes >= 15 {
trailingZeroes = 15
}

return nil
r := U16((e.AsMortalEra.Second / quantizeFactor) << 4)

encoded := trailingZeroes | r

// encoded.encode_to(output);
return encoder.Encode(encoded)
}

// MortalEra for an extrinsic, indicating period and phase
type MortalEra struct {
First byte
Second byte
First U64
Second U64
}

func NewMortalEra(currentBlock BlockNumber, blockHashCount U64) MortalEra {
// BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64;
np := getNextPowerOfTwo(blockHashCount, 2)

var npb U64

if np > 2 {
npb = np / 2
}

// let period = period.checked_next_power_of_two().unwrap_or(1 << 16).max(4).min(1 << 16);
period := getNextPowerOfTwo(npb, 1<<16)

if period <= 4 {
period = 4
}

if period >= 1<<16 {
period = 1 << 16
}

// let phase = current % period;
phase := U64(currentBlock) % period

// let quantize_factor = (period >> 12).max(1);
quantizeFactor := period >> 12

if quantizeFactor <= 1 {
quantizeFactor = 1
}

// let quantized_phase = phase / quantize_factor * quantize_factor;
quantizedPhase := phase / quantizeFactor * quantizeFactor

return MortalEra{period, quantizedPhase}
}

func getNextPowerOfTwo(n U64, def U64) U64 {
bn := strconv.FormatInt(int64(n), 2)
numBits := len(bn)

if (1 << (numBits - 1)) == n {
return n
}

res := uint(1 << numBits)

if res > math.MaxUint64 {
return def
}

return U64(res)
}

func getTrailingZeroes(n U64) U16 {
var count U16

for n > 0 {
if n%2 == 1 {
break
}

n = n / 2
count++
}

return count
}

0 comments on commit daa0719

Please sign in to comment.