v2.0.3-p0

This commit is contained in:
Cassandra Heart 2024-11-10 01:15:15 -06:00
parent df0262769b
commit cf89b1c4ee
No known key found for this signature in database
GPG Key ID: 6352152859385958
19 changed files with 899 additions and 275 deletions

View File

@ -202,6 +202,7 @@ func (e *DataClockConsensusEngine) prove(
if err != nil {
return nil, errors.Wrap(err, "prove")
}
e.lastProven = previousFrame.FrameNumber
e.logger.Info(
"returning new proven frame",
@ -233,12 +234,6 @@ func (e *DataClockConsensusEngine) GetMostAheadPeer(
max := frameNumber
var peer []byte = nil
e.peerMapMx.RLock()
beaconInfo, ok := e.peerMap[string(e.beaconPeerId)]
if !ok {
e.peerMapMx.RUnlock()
return nil, 0, p2p.ErrNoPeersAvailable
}
for _, v := range e.peerMap {
e.logger.Debug(
"checking peer info",
@ -248,7 +243,7 @@ func (e *DataClockConsensusEngine) GetMostAheadPeer(
zap.Binary("version", v.version),
)
_, ok := e.uncooperativePeersMap[string(v.peerId)]
if v.maxFrame <= beaconInfo.maxFrame && v.maxFrame > max &&
if v.maxFrame > max &&
v.timestamp > config.GetMinimumVersionCutoff().UnixMilli() &&
bytes.Compare(v.version, config.GetMinimumVersion()) >= 0 && !ok {
peer = v.peerId

View File

@ -1,7 +1,6 @@
package data
import (
"bytes"
"context"
"crypto"
"encoding/binary"
@ -11,8 +10,6 @@ import (
"time"
"github.com/iden3/go-iden3-crypto/poseidon"
pcrypto "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/p2p/discovery/backoff"
"github.com/multiformats/go-multiaddr"
mn "github.com/multiformats/go-multiaddr/net"
@ -101,7 +98,6 @@ type DataClockConsensusEngine struct {
currentReceivingSyncPeersMx sync.Mutex
currentReceivingSyncPeers int
announcedJoin int
beaconPeerId []byte
frameChan chan *protobufs.ClockFrame
executionEngines map[string]execution.ExecutionEngine
@ -201,17 +197,6 @@ func NewDataClockConsensusEngine(
panic(errors.New("peer info manager is nil"))
}
genesis := config.GetGenesis()
beaconPubKey, err := pcrypto.UnmarshalEd448PublicKey(genesis.Beacon)
if err != nil {
panic(err)
}
beaconPeerId, err := peer.IDFromPublicKey(beaconPubKey)
if err != nil {
panic(err)
}
minimumPeersRequired := cfg.Engine.MinimumPeersRequired
if minimumPeersRequired == 0 {
minimumPeersRequired = 3
@ -259,7 +244,6 @@ func NewDataClockConsensusEngine(
infoMessageProcessorCh: make(chan *pb.Message),
config: cfg,
preMidnightMint: map[string]struct{}{},
beaconPeerId: []byte(beaconPeerId),
}
logger.Info("constructing consensus engine")
@ -399,20 +383,6 @@ func (e *DataClockConsensusEngine) Start() <-chan error {
continue
}
e.peerMapMx.RLock()
beaconInfo, ok := e.peerMap[string(e.beaconPeerId)]
if !ok {
e.peerMapMx.RUnlock()
time.Sleep(120 * time.Second)
continue
}
e.peerMapMx.RUnlock()
if nextFrame.FrameNumber < beaconInfo.maxFrame-100 {
time.Sleep(120 * time.Second)
continue
}
frame = nextFrame
list := &protobufs.DataPeerListAnnounce{
@ -1155,29 +1125,3 @@ func (e *DataClockConsensusEngine) createParallelDataClientsFromBaseMultiaddr(
)
return clients, nil
}
func (e *DataClockConsensusEngine) announceProverJoin() {
msg := []byte("join")
head, _ := e.dataTimeReel.Head()
msg = binary.BigEndian.AppendUint64(msg, head.FrameNumber)
msg = append(msg, bytes.Repeat([]byte{0xff}, 32)...)
sig, err := e.pubSub.SignMessage(msg)
if err != nil {
panic(err)
}
e.publishMessage(e.txFilter, &protobufs.TokenRequest{
Request: &protobufs.TokenRequest_Join{
Join: &protobufs.AnnounceProverJoin{
Filter: bytes.Repeat([]byte{0xff}, 32),
FrameNumber: head.FrameNumber,
PublicKeySignatureEd448: &protobufs.Ed448Signature{
Signature: sig,
PublicKey: &protobufs.Ed448PublicKey{
KeyValue: e.pubSub.GetPublicKey(),
},
},
},
},
})
}

View File

@ -83,8 +83,7 @@ func (e *DataClockConsensusEngine) processFrame(
}
}
if latestFrame != nil &&
dataFrame.FrameNumber > latestFrame.FrameNumber {
if latestFrame != nil && dataFrame.FrameNumber > latestFrame.FrameNumber {
latestFrame = dataFrame
}
@ -131,7 +130,11 @@ func (e *DataClockConsensusEngine) processFrame(
if !e.IsInProverTrie(e.pubSub.GetPeerID()) &&
dataFrame.Timestamp > time.Now().UnixMilli()-30000 {
e.logger.Info("announcing prover join")
e.announceProverJoin()
for _, eng := range e.executionEngines {
eng.AnnounceProverMerge()
eng.AnnounceProverJoin()
break
}
}
return latestFrame
}

View File

@ -19,4 +19,6 @@ type ExecutionEngine interface {
GetFrame() *protobufs.ClockFrame
GetSeniority() *big.Int
GetRingPosition() int
AnnounceProverMerge()
AnnounceProverJoin()
}

View File

@ -139,6 +139,41 @@ func (a *TokenApplication) ApplyTransitions(
requests = transitions.Requests
}
parallelismMap := map[int]uint64{}
for i := range a.Tries[1:] {
parallelismMap[i] = 0
}
seen := map[string]struct{}{}
for _, transition := range requests {
switch t := transition.Request.(type) {
case *protobufs.TokenRequest_Mint:
ring, parallelism, err := t.Mint.RingAndParallelism(
func(addr []byte) int {
if _, ok := seen[string(addr)]; ok {
return -1
}
ring := -1
for i, t := range a.Tries[1:] {
if t.Contains(addr) {
ring = i
seen[string(addr)] = struct{}{}
}
}
return ring
},
)
if err != nil {
continue
}
parallelismMap[ring] = parallelismMap[ring] + uint64(parallelism)
}
}
for _, transition := range requests {
req:
switch t := transition.Request.(type) {
@ -319,7 +354,13 @@ func (a *TokenApplication) ApplyTransitions(
transition,
)
case *protobufs.TokenRequest_Mint:
success, err := a.handleMint(currentFrameNumber, lockMap, t.Mint, frame)
success, err := a.handleMint(
currentFrameNumber,
lockMap,
t.Mint,
frame,
parallelismMap,
)
if err != nil {
if !skipFailures {
return nil, nil, nil, errors.Wrap(

View File

@ -18,11 +18,14 @@ import (
"source.quilibrium.com/quilibrium/monorepo/node/tries"
)
const PROOF_FRAME_CUTOFF = 46500
func (a *TokenApplication) handleMint(
currentFrameNumber uint64,
lockMap map[string]struct{},
t *protobufs.MintCoinRequest,
frame *protobufs.ClockFrame,
parallelismMap map[int]uint64,
) ([]*protobufs.TokenOutput, error) {
if t == nil || t.Proofs == nil || t.Signature == nil {
return nil, errors.Wrap(ErrInvalidStateTransition, "handle mint")
@ -119,7 +122,7 @@ func (a *TokenApplication) handleMint(
},
}
return outputs, nil
} else if len(t.Proofs) > 0 && currentFrameNumber > 0 {
} else if len(t.Proofs) > 0 && currentFrameNumber > PROOF_FRAME_CUTOFF {
a.Logger.Debug(
"got mint from peer",
zap.String("peer_id", base58.Encode([]byte(peerId))),
@ -134,7 +137,6 @@ func (a *TokenApplication) handleMint(
return nil, errors.Wrap(ErrInvalidStateTransition, "handle mint")
}
ring := -1
proverSet := int64((len(a.Tries) - 1) * 1024)
for i, t := range a.Tries[1:] {
if t.Contains(altAddr.FillBytes(make([]byte, 32))) {
ring = i
@ -232,8 +234,12 @@ func (a *TokenApplication) handleMint(
)
}
// Current frame - 2 is because the current frame is the newly created frame,
// and the provers are submitting proofs on the frame preceding the one they
// last saw. This enforces liveness and creates a punishment for being
// late.
if (previousFrame != nil && newFrameNumber <= previousFrame.FrameNumber) ||
newFrameNumber < currentFrameNumber-10 {
newFrameNumber < currentFrameNumber-2 {
previousFrameNumber := uint64(0)
if previousFrame != nil {
previousFrameNumber = previousFrame.FrameNumber
@ -349,15 +355,9 @@ func (a *TokenApplication) handleMint(
)
}
if verified && delete != nil && len(t.Proofs) > 3 {
ringFactor := big.NewInt(2)
ringFactor.Exp(ringFactor, big.NewInt(int64(ring)), nil)
// const for testnet
storage := big.NewInt(int64(256 * parallelism))
unitFactor := big.NewInt(8000000000)
storage.Mul(storage, unitFactor)
storage.Quo(storage, big.NewInt(proverSet))
storage.Quo(storage, ringFactor)
storage := PomwBasis(1, ring, currentFrameNumber)
storage.Quo(storage, big.NewInt(int64(parallelismMap[ring])))
storage.Mul(storage, big.NewInt(int64(parallelism)))
a.Logger.Debug(
"issued reward",
@ -458,3 +458,52 @@ func (a *TokenApplication) handleMint(
)
return nil, errors.Wrap(ErrInvalidStateTransition, "handle mint")
}
func PomwBasis(generation uint64, ring int, currentFrameNumber uint64) *big.Int {
prec := uint(53)
one := new(big.Float).SetPrec(prec).SetInt64(1)
divisor := new(big.Float).SetPrec(prec).SetInt64(1048576)
normalized := new(big.Float).SetPrec(prec)
// A simple hack for estimating state growth in terms of frames, based on
// linear relationship of state growth:
normalized.SetInt64(int64((737280 + currentFrameNumber) / 184320))
normalized.Quo(normalized, divisor)
// 1/2^n
exp := new(big.Float).SetPrec(prec).SetInt64(1)
if generation > 0 {
powerOfTwo := new(big.Float).SetPrec(prec).SetInt64(2)
powerOfTwo.SetInt64(1)
for i := uint64(0); i < generation; i++ {
powerOfTwo.Mul(powerOfTwo, big.NewFloat(2))
}
exp.Quo(one, powerOfTwo)
}
// (d/1048576)^(1/2^n)
result := new(big.Float).Copy(normalized)
if generation > 0 {
for i := uint64(0); i < generation; i++ {
result.Sqrt(result)
}
}
// Calculate 1/result
result.Quo(one, result)
// Divide by 2^s
if ring > 0 {
divisor := new(big.Float).SetPrec(prec).SetInt64(1)
for i := 0; i < ring; i++ {
divisor.Mul(divisor, big.NewFloat(2))
}
result.Quo(result, divisor)
}
result.Mul(result, new(big.Float).SetPrec(prec).SetInt64(8000000000))
out, _ := result.Int(new(big.Int))
return out
}

View File

@ -16,7 +16,8 @@ func (a *TokenApplication) handleAnnounce(
var primary *protobufs.Ed448Signature
payload := []byte{}
if t == nil || t.PublicKeySignaturesEd448 == nil {
if t == nil || t.PublicKeySignaturesEd448 == nil ||
len(t.PublicKeySignaturesEd448) == 0 {
return nil, errors.Wrap(ErrInvalidStateTransition, "handle announce")
}
for i, p := range t.PublicKeySignaturesEd448 {
@ -44,11 +45,18 @@ func (a *TokenApplication) handleAnnounce(
return nil, errors.Wrap(ErrInvalidStateTransition, "handle announce")
}
for _, p := range t.PublicKeySignaturesEd448 {
for _, p := range t.PublicKeySignaturesEd448[1:] {
lockMap[string(p.PublicKey.KeyValue)] = struct{}{}
}
outputs := []*protobufs.TokenOutput{}
if currentFrameNumber >= PROOF_FRAME_CUTOFF {
outputs = append(outputs, &protobufs.TokenOutput{
Output: &protobufs.TokenOutput_Announce{
Announce: t,
},
})
}
return outputs, nil
}

View File

@ -46,6 +46,10 @@ func (a *TokenApplication) handleDataAnnounceProverJoin(
[]*protobufs.TokenOutput,
error,
) {
if currentFrameNumber < PROOF_FRAME_CUTOFF {
return nil, errors.Wrap(ErrInvalidStateTransition, "handle join")
}
payload := []byte("join")
if t == nil || t.PublicKeySignatureEd448 == nil {

View File

@ -176,12 +176,13 @@ func TestHandleProverJoin(t *testing.T) {
fmt.Printf("%x\n", individualChallenge)
out2, _ := wprover.CalculateChallengeProof(individualChallenge, 10000)
proofTree, payload, output := tries.PackOutputIntoPayloadAndProof(
proofTree, payload, output, err := tries.PackOutputIntoPayloadAndProof(
[]merkletree.DataBlock{tries.NewProofLeaf(out1), tries.NewProofLeaf(out2)},
2,
frame2,
nil,
)
assert.NoError(t, err)
sig, _ = privKey.Sign(payload)
app, success, _, err = app.ApplyTransitions(2, &protobufs.TokenRequests{
@ -240,12 +241,13 @@ func TestHandleProverJoin(t *testing.T) {
app.ClockStore.CommitDataClockFrame(frame3.Filter, 3, selbi.FillBytes(make([]byte, 32)), app.Tries, txn, false)
txn.Commit()
proofTree, payload, output = tries.PackOutputIntoPayloadAndProof(
proofTree, payload, output, err = tries.PackOutputIntoPayloadAndProof(
[]merkletree.DataBlock{tries.NewProofLeaf(out1), tries.NewProofLeaf(out2)},
2,
frame3,
proofTree,
)
assert.NoError(t, err)
sig, _ = privKey.Sign(payload)
app, success, _, err = app.ApplyTransitions(3, &protobufs.TokenRequests{

View File

@ -15,6 +15,10 @@ func (a *TokenApplication) handleDataAnnounceProverLeave(
[]*protobufs.TokenOutput,
error,
) {
if currentFrameNumber < PROOF_FRAME_CUTOFF {
return nil, errors.Wrap(ErrInvalidStateTransition, "handle leave")
}
payload := []byte("leave")
if t == nil || t.PublicKeySignatureEd448 == nil {

View File

@ -15,6 +15,10 @@ func (a *TokenApplication) handleDataAnnounceProverPause(
[]*protobufs.TokenOutput,
error,
) {
if currentFrameNumber < PROOF_FRAME_CUTOFF {
return nil, errors.Wrap(ErrInvalidStateTransition, "handle pause")
}
payload := []byte("pause")
if t == nil || t.PublicKeySignatureEd448 == nil {

View File

@ -15,6 +15,10 @@ func (a *TokenApplication) handleDataAnnounceProverResume(
[]*protobufs.TokenOutput,
error,
) {
if currentFrameNumber < PROOF_FRAME_CUTOFF {
return nil, errors.Wrap(ErrInvalidStateTransition, "handle resume")
}
payload := []byte("resume")
if t == nil || t.PublicKeySignatureEd448 == nil {

View File

@ -7,6 +7,7 @@ import (
"encoding/hex"
"math/big"
"slices"
"strconv"
"strings"
"sync"
gotime "time"
@ -32,17 +33,24 @@ import (
"source.quilibrium.com/quilibrium/monorepo/node/tries"
)
type peerSeniorityItem struct {
type PeerSeniorityItem struct {
seniority uint64
addr string
}
type peerSeniority map[string]peerSeniorityItem
func NewPeerSeniorityItem(seniority uint64, addr string) PeerSeniorityItem {
return PeerSeniorityItem{
seniority: seniority,
addr: addr,
}
}
func newFromMap(m map[string]uint64) *peerSeniority {
s := &peerSeniority{}
type PeerSeniority map[string]PeerSeniorityItem
func newFromMap(m map[string]uint64) *PeerSeniority {
s := &PeerSeniority{}
for k, v := range m {
(*s)[k] = peerSeniorityItem{
(*s)[k] = PeerSeniorityItem{
seniority: v,
addr: k,
}
@ -50,7 +58,7 @@ func newFromMap(m map[string]uint64) *peerSeniority {
return s
}
func toSerializedMap(m *peerSeniority) map[string]uint64 {
func toSerializedMap(m *PeerSeniority) map[string]uint64 {
s := map[string]uint64{}
for k, v := range *m {
s[k] = v.seniority
@ -58,7 +66,7 @@ func toSerializedMap(m *peerSeniority) map[string]uint64 {
return s
}
func (p peerSeniorityItem) Priority() *big.Int {
func (p PeerSeniorityItem) Priority() *big.Int {
return big.NewInt(int64(p.seniority))
}
@ -82,7 +90,7 @@ type TokenExecutionEngine struct {
alreadyPublishedShare bool
intrinsicFilter []byte
frameProver qcrypto.FrameProver
peerSeniority *peerSeniority
peerSeniority *PeerSeniority
}
func NewTokenExecutionEngine(
@ -116,7 +124,6 @@ func NewTokenExecutionEngine(
var inclusionProof *qcrypto.InclusionAggregateProof
var proverKeys [][]byte
var peerSeniority map[string]uint64
genesisCreated := false
if err != nil && errors.Is(err, store.ErrNotFound) {
origin, inclusionProof, proverKeys, peerSeniority = CreateGenesisState(
@ -133,7 +140,6 @@ func NewTokenExecutionEngine(
); err != nil {
panic(err)
}
genesisCreated = true
} else if err != nil {
panic(err)
} else {
@ -155,7 +161,6 @@ func NewTokenExecutionEngine(
coinStore,
uint(cfg.P2P.Network),
)
genesisCreated = true
}
}
@ -165,8 +170,29 @@ func NewTokenExecutionEngine(
panic(err)
}
if peerSeniority == nil {
RebuildPeerSeniority(clockStore)
peerSeniority, err = RebuildPeerSeniority(uint(cfg.P2P.Network))
if err != nil {
panic(err)
}
txn, err := clockStore.NewTransaction()
if err != nil {
panic(err)
}
err = clockStore.PutPeerSeniorityMap(txn, intrinsicFilter, peerSeniority)
if err != nil {
txn.Abort()
panic(err)
}
if err = txn.Commit(); err != nil {
txn.Abort()
panic(err)
}
}
} else {
LoadAggregatedSeniorityMap()
}
e := &TokenExecutionEngine{
@ -251,126 +277,26 @@ func NewTokenExecutionEngine(
e.proverPublicKey = publicKeyBytes
e.provingKeyAddress = provingKeyAddress
if genesisCreated {
go func() {
keys := [][]byte{}
ksigs := [][]byte{}
if len(e.engineConfig.MultisigProverEnrollmentPaths) != 0 {
for _, conf := range e.engineConfig.MultisigProverEnrollmentPaths {
extraConf, err := config.LoadConfig(conf, "", false)
if err != nil {
panic(err)
}
peerPrivKey, err := hex.DecodeString(extraConf.P2P.PeerPrivKey)
if err != nil {
panic(errors.Wrap(err, "error unmarshaling peerkey"))
}
privKey, err := pcrypto.UnmarshalEd448PrivateKey(peerPrivKey)
if err != nil {
panic(errors.Wrap(err, "error unmarshaling peerkey"))
}
pub := privKey.GetPublic()
pubBytes, err := pub.Raw()
if err != nil {
panic(errors.Wrap(err, "error unmarshaling peerkey"))
}
keys = append(keys, pubBytes)
sig, err := privKey.Sign(e.pubSub.GetPublicKey())
if err != nil {
panic(errors.Wrap(err, "error unmarshaling peerkey"))
}
ksigs = append(ksigs, sig)
}
}
keyjoin := []byte{}
for _, k := range keys {
keyjoin = append(keyjoin, k...)
}
mainsig, err := e.pubSub.SignMessage(keyjoin)
if err != nil {
panic(err)
}
announce := &protobufs.TokenRequest_Announce{
Announce: &protobufs.AnnounceProverRequest{
PublicKeySignaturesEd448: []*protobufs.Ed448Signature{},
},
}
announce.Announce.PublicKeySignaturesEd448 = append(
announce.Announce.PublicKeySignaturesEd448,
&protobufs.Ed448Signature{
PublicKey: &protobufs.Ed448PublicKey{
KeyValue: e.pubSub.GetPublicKey(),
},
Signature: mainsig,
},
)
for i := range keys {
announce.Announce.PublicKeySignaturesEd448 = append(
announce.Announce.PublicKeySignaturesEd448,
&protobufs.Ed448Signature{
PublicKey: &protobufs.Ed448PublicKey{
KeyValue: keys[i],
},
Signature: ksigs[i],
},
)
}
req := &protobufs.TokenRequest{
Request: announce,
}
// need to wait for peering
gotime.Sleep(30 * gotime.Second)
e.publishMessage(append([]byte{0x00}, intrinsicFilter...), req)
}()
} else {
go func() {
f, tries, err := e.clockStore.GetLatestDataClockFrame(e.intrinsicFilter)
fn, err := coinStore.GetLatestFrameProcessed()
if err != nil {
panic(err)
return
}
if f.FrameNumber != fn && fn == 0 {
txn, err := coinStore.NewTransaction()
shouldResume := false
for _, trie := range tries[1:] {
altAddr, err := poseidon.HashBytes(e.pubSub.GetPeerID())
if err != nil {
panic(err)
break
}
err = coinStore.SetLatestFrameProcessed(txn, f.FrameNumber)
if err != nil {
txn.Abort()
panic(err)
}
if err = txn.Commit(); err != nil {
panic(err)
}
} else if f.FrameNumber-fn == 1 && f.FrameNumber > fn {
txn, err := coinStore.NewTransaction()
if err != nil {
panic(err)
}
e.logger.Info(
"replaying last data frame",
zap.Uint64("frame_number", f.FrameNumber),
)
e.ProcessFrame(txn, f, tries)
if err = txn.Commit(); err != nil {
panic(err)
if trie.Contains(altAddr.FillBytes(make([]byte, 32))) {
shouldResume = true
break
}
}
if err == nil {
if shouldResume {
msg := []byte("resume")
msg = binary.BigEndian.AppendUint64(msg, f.FrameNumber)
msg = append(msg, e.intrinsicFilter...)
@ -380,7 +306,17 @@ func NewTokenExecutionEngine(
}
// need to wait for peering
gotime.Sleep(30 * gotime.Second)
for {
gotime.Sleep(30 * gotime.Second)
peerMap := e.pubSub.GetBitmaskPeers()
if peers, ok := peerMap[string(
append([]byte{0x00}, e.intrinsicFilter...),
)]; ok {
if len(peers) >= 3 {
break
}
}
}
e.publishMessage(
append([]byte{0x00}, e.intrinsicFilter...),
&protobufs.TokenRequest{
@ -399,7 +335,7 @@ func NewTokenExecutionEngine(
},
)
}
}
}()
return e
}
@ -591,17 +527,23 @@ func (e *TokenExecutionEngine) ProcessFrame(
txn.Abort()
return nil, errors.Wrap(err, "process frame")
}
// testnet:
if len(o.Proof.Amount) == 32 &&
!bytes.Equal(o.Proof.Amount, make([]byte, 32)) {
!bytes.Equal(o.Proof.Amount, make([]byte, 32)) &&
o.Proof.Commitment != nil {
addr := string(o.Proof.Owner.GetImplicitAccount().Address)
for _, t := range app.Tries {
if t.Contains([]byte(addr)) {
t.Add([]byte(addr), frame.FrameNumber)
break
}
}
if _, ok := (*e.peerSeniority)[addr]; !ok {
(*e.peerSeniority)[addr] = peerSeniorityItem{
(*e.peerSeniority)[addr] = PeerSeniorityItem{
seniority: 10,
addr: addr,
}
} else {
(*e.peerSeniority)[addr] = peerSeniorityItem{
(*e.peerSeniority)[addr] = PeerSeniorityItem{
seniority: (*e.peerSeniority)[addr].seniority + 10,
addr: addr,
}
@ -622,6 +564,96 @@ func (e *TokenExecutionEngine) ProcessFrame(
txn.Abort()
return nil, errors.Wrap(err, "process frame")
}
case *protobufs.TokenOutput_Announce:
peerIds := []string{}
for _, sig := range o.Announce.PublicKeySignaturesEd448 {
peerId, err := e.getPeerIdFromSignature(sig)
if err != nil {
txn.Abort()
return nil, errors.Wrap(err, "process frame")
}
peerIds = append(peerIds, peerId.String())
}
mergeable := true
for i, peerId := range peerIds {
addr, err := e.getAddressFromSignature(
o.Announce.PublicKeySignaturesEd448[i],
)
if err != nil {
txn.Abort()
return nil, errors.Wrap(err, "process frame")
}
sen, ok := (*e.peerSeniority)[string(addr)]
if !ok {
e.logger.Debug(
"peer announced with no seniority",
zap.String("peer_id", peerId),
)
continue
}
peer := new(big.Int).SetUint64(sen.seniority)
if peer.Cmp(e.GetAggregatedSeniority([]string{peerId})) != 0 {
e.logger.Debug(
"peer announced but is already different seniority",
zap.String("peer_id", peerIds[0]),
)
mergeable = false
break
}
}
if mergeable {
addr, err := e.getAddressFromSignature(
o.Announce.PublicKeySignaturesEd448[0],
)
if err != nil {
txn.Abort()
return nil, errors.Wrap(err, "process frame")
}
additional := uint64(0)
_, prfs, err := e.coinStore.GetPreCoinProofsForOwner(addr)
if err != nil && !errors.Is(err, store.ErrNotFound) {
txn.Abort()
return nil, errors.Wrap(err, "process frame")
}
for _, pr := range prfs {
if pr.IndexProof == nil && pr.Difficulty == 0 && pr.Commitment == nil {
// approximate average per interval:
add := new(big.Int).SetBytes(pr.Amount)
add.Quo(add, big.NewInt(58800000))
if add.Cmp(big.NewInt(4000000)) > 0 {
add = big.NewInt(4000000)
}
additional = add.Uint64()
}
}
(*e.peerSeniority)[string(addr)] = PeerSeniorityItem{
seniority: e.GetAggregatedSeniority(peerIds).Uint64() + additional,
addr: string(addr),
}
for _, sig := range o.Announce.PublicKeySignaturesEd448[1:] {
addr, err := e.getAddressFromSignature(
sig,
)
if err != nil {
txn.Abort()
return nil, errors.Wrap(err, "process frame")
}
(*e.peerSeniority)[string(addr)] = PeerSeniorityItem{
seniority: 0,
addr: string(addr),
}
}
}
case *protobufs.TokenOutput_Join:
addr, err := e.getAddressFromSignature(o.Join.PublicKeySignatureEd448)
if err != nil {
@ -629,12 +661,12 @@ func (e *TokenExecutionEngine) ProcessFrame(
return nil, errors.Wrap(err, "process frame")
}
if _, ok := (*e.peerSeniority)[string(addr)]; !ok {
(*e.peerSeniority)[string(addr)] = peerSeniorityItem{
(*e.peerSeniority)[string(addr)] = PeerSeniorityItem{
seniority: 20,
addr: string(addr),
}
} else {
(*e.peerSeniority)[string(addr)] = peerSeniorityItem{
(*e.peerSeniority)[string(addr)] = PeerSeniorityItem{
seniority: (*e.peerSeniority)[string(addr)].seniority + 20,
addr: string(addr),
}
@ -662,19 +694,28 @@ func (e *TokenExecutionEngine) ProcessFrame(
case *protobufs.TokenOutput_Penalty:
addr := string(o.Penalty.Account.GetImplicitAccount().Address)
if _, ok := (*e.peerSeniority)[addr]; !ok {
(*e.peerSeniority)[addr] = peerSeniorityItem{
(*e.peerSeniority)[addr] = PeerSeniorityItem{
seniority: 0,
addr: addr,
}
proverTrieLeaveRequests = append(proverTrieLeaveRequests, []byte(addr))
} else {
if (*e.peerSeniority)[addr].seniority > o.Penalty.Quantity {
(*e.peerSeniority)[addr] = peerSeniorityItem{
for _, t := range app.Tries {
if t.Contains([]byte(addr)) {
_, latest, _ := t.Get([]byte(addr))
if frame.FrameNumber-latest > 100 {
proverTrieLeaveRequests = append(proverTrieLeaveRequests, []byte(addr))
}
break
}
}
(*e.peerSeniority)[addr] = PeerSeniorityItem{
seniority: (*e.peerSeniority)[addr].seniority - o.Penalty.Quantity,
addr: addr,
}
} else {
(*e.peerSeniority)[addr] = peerSeniorityItem{
(*e.peerSeniority)[addr] = PeerSeniorityItem{
seniority: 0,
addr: addr,
}
@ -684,11 +725,11 @@ func (e *TokenExecutionEngine) ProcessFrame(
}
}
joinAddrs := tries.NewMinHeap[peerSeniorityItem]()
leaveAddrs := tries.NewMinHeap[peerSeniorityItem]()
joinAddrs := tries.NewMinHeap[PeerSeniorityItem]()
leaveAddrs := tries.NewMinHeap[PeerSeniorityItem]()
for _, addr := range proverTrieJoinRequests {
if _, ok := (*e.peerSeniority)[string(addr)]; !ok {
joinAddrs.Push(peerSeniorityItem{
joinAddrs.Push(PeerSeniorityItem{
addr: string(addr),
seniority: 0,
})
@ -698,7 +739,7 @@ func (e *TokenExecutionEngine) ProcessFrame(
}
for _, addr := range proverTrieLeaveRequests {
if _, ok := (*e.peerSeniority)[string(addr)]; !ok {
leaveAddrs.Push(peerSeniorityItem{
leaveAddrs.Push(PeerSeniorityItem{
addr: string(addr),
seniority: 0,
})
@ -707,36 +748,14 @@ func (e *TokenExecutionEngine) ProcessFrame(
}
}
joinReqs := make([]peerSeniorityItem, len(joinAddrs.All()))
joinReqs := make([]PeerSeniorityItem, len(joinAddrs.All()))
copy(joinReqs, joinAddrs.All())
slices.Reverse(joinReqs)
leaveReqs := make([]peerSeniorityItem, len(leaveAddrs.All()))
leaveReqs := make([]PeerSeniorityItem, len(leaveAddrs.All()))
copy(leaveReqs, leaveAddrs.All())
slices.Reverse(leaveReqs)
for _, addr := range joinReqs {
rings := len(app.Tries)
last := app.Tries[rings-1]
set := last.FindNearestAndApproximateNeighbors(make([]byte, 32))
if len(set) == 1024 || rings == 1 {
app.Tries = append(
app.Tries,
&tries.RollingFrecencyCritbitTrie{},
)
last = app.Tries[rings]
}
if !last.Contains([]byte(addr.addr)) {
last.Add([]byte(addr.addr), frame.FrameNumber)
}
}
for _, addr := range leaveReqs {
for _, t := range app.Tries {
if t.Contains([]byte(addr.addr)) {
t.Remove([]byte(addr.addr))
break
}
}
}
ProcessJoinsAndLeaves(joinReqs, leaveReqs, app, e.peerSeniority, frame)
err = e.clockStore.PutPeerSeniorityMap(
txn,
@ -757,6 +776,57 @@ func (e *TokenExecutionEngine) ProcessFrame(
return app.Tries, nil
}
func ProcessJoinsAndLeaves(
joinReqs []PeerSeniorityItem,
leaveReqs []PeerSeniorityItem,
app *application.TokenApplication,
seniority *PeerSeniority,
frame *protobufs.ClockFrame,
) {
for _, addr := range joinReqs {
rings := len(app.Tries)
last := app.Tries[rings-1]
set := last.FindNearestAndApproximateNeighbors(make([]byte, 32))
if len(set) == 2048 || rings == 1 {
app.Tries = append(
app.Tries,
&tries.RollingFrecencyCritbitTrie{},
)
last = app.Tries[rings]
}
if !last.Contains([]byte(addr.addr)) {
last.Add([]byte(addr.addr), frame.FrameNumber)
}
}
for _, addr := range leaveReqs {
for _, t := range app.Tries[1:] {
if t.Contains([]byte(addr.addr)) {
t.Remove([]byte(addr.addr))
break
}
}
}
if len(app.Tries) > 2 {
for i, t := range app.Tries[2:] {
setSize := len(app.Tries[1+i].FindNearestAndApproximateNeighbors(make([]byte, 32)))
if setSize < 2048 {
nextSet := t.FindNearestAndApproximateNeighbors(make([]byte, 32))
eligibilityOrder := tries.NewMinHeap[PeerSeniorityItem]()
for _, n := range nextSet {
eligibilityOrder.Push((*seniority)[string(n.External.Key)])
}
process := eligibilityOrder.All()
slices.Reverse(process)
for s := 0; s+setSize < 2048; s++ {
app.Tries[1+i].Add([]byte(process[s].addr), frame.FrameNumber)
app.Tries[2+i].Remove([]byte(process[s].addr))
}
}
}
}
}
func (e *TokenExecutionEngine) publishMessage(
filter []byte,
message proto.Message,
@ -913,6 +983,235 @@ func (e *TokenExecutionEngine) GetSeniority() *big.Int {
return sen.Priority()
}
func (e *TokenExecutionEngine) GetAggregatedSeniority(peerIds []string) *big.Int {
highestFirst := uint64(0)
highestSecond := uint64(0)
highestThird := uint64(0)
highestFourth := uint64(0)
for _, f := range firstRetro {
found := false
for _, p := range peerIds {
if p != f.PeerId {
continue
}
found = true
}
if !found {
continue
}
// these don't have decimals so we can shortcut
max := 157208
actual, err := strconv.Atoi(f.Reward)
if err != nil {
panic(err)
}
s := uint64(10 * 6 * 60 * 24 * 92 / (max / actual))
if s > uint64(highestFirst) {
highestFirst = s
}
}
for _, f := range secondRetro {
found := false
for _, p := range peerIds {
if p != f.PeerId {
continue
}
found = true
}
if !found {
continue
}
amt := uint64(0)
if f.JanPresence {
amt += (10 * 6 * 60 * 24 * 31)
}
if f.FebPresence {
amt += (10 * 6 * 60 * 24 * 29)
}
if f.MarPresence {
amt += (10 * 6 * 60 * 24 * 31)
}
if f.AprPresence {
amt += (10 * 6 * 60 * 24 * 30)
}
if f.MayPresence {
amt += (10 * 6 * 60 * 24 * 31)
}
if amt > uint64(highestSecond) {
highestSecond = amt
}
}
for _, f := range thirdRetro {
found := false
for _, p := range peerIds {
if p != f.PeerId {
continue
}
found = true
}
if !found {
continue
}
s := uint64(10 * 6 * 60 * 24 * 30)
if s > uint64(highestThird) {
highestThird = s
}
}
for _, f := range fourthRetro {
found := false
for _, p := range peerIds {
if p != f.PeerId {
continue
}
found = true
}
if !found {
continue
}
s := uint64(10 * 6 * 60 * 24 * 31)
if s > uint64(highestFourth) {
highestFourth = s
}
}
return new(big.Int).SetUint64(
highestFirst + highestSecond + highestThird + highestFourth,
)
}
func (e *TokenExecutionEngine) AnnounceProverMerge() {
currentHead := e.GetFrame()
if currentHead == nil ||
currentHead.FrameNumber < application.PROOF_FRAME_CUTOFF {
return
}
keys := [][]byte{}
ksigs := [][]byte{}
if len(e.engineConfig.MultisigProverEnrollmentPaths) != 0 &&
e.GetSeniority().Cmp(e.GetAggregatedSeniority(
[]string{peer.ID(e.pubSub.GetPeerID()).String()},
)) == 0 {
for _, conf := range e.engineConfig.MultisigProverEnrollmentPaths {
extraConf, err := config.LoadConfig(conf, "", false)
if err != nil {
panic(err)
}
peerPrivKey, err := hex.DecodeString(extraConf.P2P.PeerPrivKey)
if err != nil {
panic(errors.Wrap(err, "error unmarshaling peerkey"))
}
privKey, err := pcrypto.UnmarshalEd448PrivateKey(peerPrivKey)
if err != nil {
panic(errors.Wrap(err, "error unmarshaling peerkey"))
}
pub := privKey.GetPublic()
pubBytes, err := pub.Raw()
if err != nil {
panic(errors.Wrap(err, "error unmarshaling peerkey"))
}
keys = append(keys, pubBytes)
sig, err := privKey.Sign(e.pubSub.GetPublicKey())
if err != nil {
panic(errors.Wrap(err, "error unmarshaling peerkey"))
}
ksigs = append(ksigs, sig)
}
}
keyjoin := []byte{}
for _, k := range keys {
keyjoin = append(keyjoin, k...)
}
mainsig, err := e.pubSub.SignMessage(keyjoin)
if err != nil {
panic(err)
}
announce := &protobufs.TokenRequest_Announce{
Announce: &protobufs.AnnounceProverRequest{
PublicKeySignaturesEd448: []*protobufs.Ed448Signature{},
},
}
announce.Announce.PublicKeySignaturesEd448 = append(
announce.Announce.PublicKeySignaturesEd448,
&protobufs.Ed448Signature{
PublicKey: &protobufs.Ed448PublicKey{
KeyValue: e.pubSub.GetPublicKey(),
},
Signature: mainsig,
},
)
for i := range keys {
announce.Announce.PublicKeySignaturesEd448 = append(
announce.Announce.PublicKeySignaturesEd448,
&protobufs.Ed448Signature{
PublicKey: &protobufs.Ed448PublicKey{
KeyValue: keys[i],
},
Signature: ksigs[i],
},
)
}
req := &protobufs.TokenRequest{
Request: announce,
}
e.publishMessage(append([]byte{0x00}, e.intrinsicFilter...), req)
}
func (e *TokenExecutionEngine) AnnounceProverJoin() {
msg := []byte("join")
head := e.GetFrame()
if head == nil ||
head.FrameNumber < application.PROOF_FRAME_CUTOFF {
return
}
msg = binary.BigEndian.AppendUint64(msg, head.FrameNumber)
msg = append(msg, bytes.Repeat([]byte{0xff}, 32)...)
sig, err := e.pubSub.SignMessage(msg)
if err != nil {
panic(err)
}
e.publishMessage(
append([]byte{0x00}, e.intrinsicFilter...),
&protobufs.TokenRequest{
Request: &protobufs.TokenRequest_Join{
Join: &protobufs.AnnounceProverJoin{
Filter: bytes.Repeat([]byte{0xff}, 32),
FrameNumber: head.FrameNumber,
PublicKeySignatureEd448: &protobufs.Ed448Signature{
Signature: sig,
PublicKey: &protobufs.Ed448PublicKey{
KeyValue: e.pubSub.GetPublicKey(),
},
},
},
},
},
)
}
func (e *TokenExecutionEngine) GetRingPosition() int {
altAddr, err := poseidon.HashBytes(e.pubSub.GetPeerID())
if err != nil {
@ -933,6 +1232,28 @@ func (e *TokenExecutionEngine) GetRingPosition() int {
return -1
}
func (e *TokenExecutionEngine) getPeerIdFromSignature(
sig *protobufs.Ed448Signature,
) (peer.ID, error) {
if sig.PublicKey == nil || sig.PublicKey.KeyValue == nil {
return "", errors.New("invalid data")
}
pk, err := pcrypto.UnmarshalEd448PublicKey(
sig.PublicKey.KeyValue,
)
if err != nil {
return "", errors.Wrap(err, "get address from signature")
}
peerId, err := peer.IDFromPublicKey(pk)
if err != nil {
return "", errors.Wrap(err, "get address from signature")
}
return peerId, nil
}
func (e *TokenExecutionEngine) getAddressFromSignature(
sig *protobufs.Ed448Signature,
) ([]byte, error) {

View File

@ -0,0 +1,52 @@
package token_test
import (
"crypto/rand"
"testing"
"github.com/stretchr/testify/assert"
"source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/token"
"source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/token/application"
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
"source.quilibrium.com/quilibrium/monorepo/node/tries"
)
func TestProcessJoinsAndLeaves(t *testing.T) {
set := [][]byte{}
for i := 0; i < 6000; i++ {
b := make([]byte, 32)
rand.Read(b)
set = append(set, b)
}
joins := []token.PeerSeniorityItem{}
seniority := &token.PeerSeniority{}
for i, s := range set {
joins = append(joins, token.NewPeerSeniorityItem(uint64(i), string(s)))
(*seniority)[string(s)] = token.NewPeerSeniorityItem(uint64(i), string(s))
}
tr := []*tries.RollingFrecencyCritbitTrie{
&tries.RollingFrecencyCritbitTrie{},
&tries.RollingFrecencyCritbitTrie{},
}
app := &application.TokenApplication{
Tries: tr,
}
token.ProcessJoinsAndLeaves(joins, []token.PeerSeniorityItem{}, app, seniority, &protobufs.ClockFrame{FrameNumber: 20})
assert.Equal(t, len(app.Tries), 4)
assert.Equal(t, len(app.Tries[1].FindNearestAndApproximateNeighbors(make([]byte, 32))), 2048)
assert.Equal(t, len(app.Tries[2].FindNearestAndApproximateNeighbors(make([]byte, 32))), 2048)
assert.Equal(t, len(app.Tries[3].FindNearestAndApproximateNeighbors(make([]byte, 32))), 1904)
leaves := []token.PeerSeniorityItem{}
leaves = append(leaves, joins[30])
leaves = append(leaves, joins[2047])
leaves = append(leaves, joins[4095])
token.ProcessJoinsAndLeaves([]token.PeerSeniorityItem{}, leaves, app, seniority, &protobufs.ClockFrame{FrameNumber: 20})
assert.Equal(t, len(app.Tries), 4)
assert.Equal(t, len(app.Tries[1].FindNearestAndApproximateNeighbors(make([]byte, 32))), 2048)
assert.Equal(t, len(app.Tries[2].FindNearestAndApproximateNeighbors(make([]byte, 32))), 2048)
assert.Equal(t, len(app.Tries[3].FindNearestAndApproximateNeighbors(make([]byte, 32))), 1901)
}

View File

@ -75,25 +75,140 @@ var thirdRetroJsonBinary []byte
//go:embed fourth_retro.json
var fourthRetroJsonBinary []byte
func RebuildPeerSeniority(clockStore store.ClockStore) {
// testnet:
txn, err := clockStore.NewTransaction()
var firstRetro []*FirstRetroJson
var secondRetro []*SecondRetroJson
var thirdRetro []*ThirdRetroJson
var fourthRetro []*FourthRetroJson
func LoadAggregatedSeniorityMap() {
firstRetro = []*FirstRetroJson{}
secondRetro = []*SecondRetroJson{}
thirdRetro = []*ThirdRetroJson{}
fourthRetro = []*FourthRetroJson{}
err := json.Unmarshal(firstRetroJsonBinary, &firstRetro)
if err != nil {
panic(err)
}
err = clockStore.PutPeerSeniorityMap(
txn,
p2p.GetBloomFilter(application.TOKEN_ADDRESS, 256, 3),
map[string]uint64{},
)
err = json.Unmarshal(secondRetroJsonBinary, &secondRetro)
if err != nil {
panic(err)
}
if err = txn.Commit(); err != nil {
err = json.Unmarshal(thirdRetroJsonBinary, &thirdRetro)
if err != nil {
panic(err)
}
err = json.Unmarshal(fourthRetroJsonBinary, &fourthRetro)
if err != nil {
panic(err)
}
}
func RebuildPeerSeniority(network uint) (map[string]uint64, error) {
if network != 0 {
return map[string]uint64{}, nil
}
firstRetro = []*FirstRetroJson{}
secondRetro = []*SecondRetroJson{}
thirdRetro = []*ThirdRetroJson{}
fourthRetro = []*FourthRetroJson{}
err := json.Unmarshal(firstRetroJsonBinary, &firstRetro)
if err != nil {
return nil, err
}
err = json.Unmarshal(secondRetroJsonBinary, &secondRetro)
if err != nil {
return nil, err
}
err = json.Unmarshal(thirdRetroJsonBinary, &thirdRetro)
if err != nil {
return nil, err
}
err = json.Unmarshal(fourthRetroJsonBinary, &fourthRetro)
if err != nil {
return nil, err
}
peerSeniority := map[string]uint64{}
for _, f := range firstRetro {
// these don't have decimals so we can shortcut
max := 157208
actual, err := strconv.Atoi(f.Reward)
if err != nil {
return nil, err
}
p := []byte(f.PeerId)
addr, _ := poseidon.HashBytes(p)
peerSeniority[string(
addr.FillBytes(make([]byte, 32)),
)] = uint64(10 * 6 * 60 * 24 * 92 / (max / actual))
}
for _, f := range secondRetro {
p := []byte(f.PeerId)
addr, _ := poseidon.HashBytes(p)
addrBytes := string(addr.FillBytes(make([]byte, 32)))
if _, ok := peerSeniority[addrBytes]; !ok {
peerSeniority[addrBytes] = 0
}
if f.JanPresence {
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 31)
}
if f.FebPresence {
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 29)
}
if f.MarPresence {
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 31)
}
if f.AprPresence {
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 30)
}
if f.MayPresence {
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 31)
}
}
for _, f := range thirdRetro {
p := []byte(f.PeerId)
addr, _ := poseidon.HashBytes(p)
addrBytes := string(addr.FillBytes(make([]byte, 32)))
if _, ok := peerSeniority[addrBytes]; !ok {
peerSeniority[addrBytes] = 0
}
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 30)
}
for _, f := range fourthRetro {
p := []byte(f.PeerId)
addr, _ := poseidon.HashBytes(p)
addrBytes := string(addr.FillBytes(make([]byte, 32)))
if _, ok := peerSeniority[addrBytes]; !ok {
peerSeniority[addrBytes] = 0
}
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 31)
}
return peerSeniority, nil
}
// Creates a genesis state for the intrinsic
@ -147,10 +262,10 @@ func CreateGenesisState(
if network == 0 {
bridged := []*BridgedPeerJson{}
vouchers := []string{}
firstRetro := []*FirstRetroJson{}
secondRetro := []*SecondRetroJson{}
thirdRetro := []*ThirdRetroJson{}
fourthRetro := []*FourthRetroJson{}
firstRetro = []*FirstRetroJson{}
secondRetro = []*SecondRetroJson{}
thirdRetro = []*ThirdRetroJson{}
fourthRetro = []*FourthRetroJson{}
err = json.Unmarshal(bridgedPeersJsonBinary, &bridged)
if err != nil {
@ -200,6 +315,9 @@ func CreateGenesisState(
peerSeniority := map[string]uint64{}
logger.Info("encoding first retro state")
for _, f := range firstRetro {
p := []byte(f.PeerId)
addr, _ := poseidon.HashBytes(p)
addrBytes := string(addr.FillBytes(make([]byte, 32)))
if _, ok := bridgedAddrs[f.PeerId]; !ok {
peerIdTotals[f.PeerId], err = decimal.NewFromString(f.Reward)
if err != nil {
@ -214,7 +332,7 @@ func CreateGenesisState(
panic(err)
}
peerSeniority[f.PeerId] = uint64(10 * 6 * 60 * 24 * 92 / (max / actual))
peerSeniority[addrBytes] = uint64(10 * 6 * 60 * 24 * 92 / (max / actual))
}
logger.Info("encoding voucher state")
@ -226,6 +344,10 @@ func CreateGenesisState(
logger.Info("encoding second retro state")
for _, f := range secondRetro {
p := []byte(f.PeerId)
addr, _ := poseidon.HashBytes(p)
addrBytes := string(addr.FillBytes(make([]byte, 32)))
if _, ok := bridgedAddrs[f.PeerId]; !ok {
existing, ok := peerIdTotals[f.PeerId]
@ -241,33 +363,37 @@ func CreateGenesisState(
}
}
if _, ok := peerSeniority[f.PeerId]; !ok {
peerSeniority[f.PeerId] = 0
if _, ok := peerSeniority[addrBytes]; !ok {
peerSeniority[addrBytes] = 0
}
if f.JanPresence {
peerSeniority[f.PeerId] = peerSeniority[f.PeerId] + (10 * 6 * 60 * 24 * 31)
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 31)
}
if f.FebPresence {
peerSeniority[f.PeerId] = peerSeniority[f.PeerId] + (10 * 6 * 60 * 24 * 29)
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 29)
}
if f.MarPresence {
peerSeniority[f.PeerId] = peerSeniority[f.PeerId] + (10 * 6 * 60 * 24 * 31)
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 31)
}
if f.AprPresence {
peerSeniority[f.PeerId] = peerSeniority[f.PeerId] + (10 * 6 * 60 * 24 * 30)
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 30)
}
if f.MayPresence {
peerSeniority[f.PeerId] = peerSeniority[f.PeerId] + (10 * 6 * 60 * 24 * 31)
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 31)
}
}
logger.Info("encoding third retro state")
for _, f := range thirdRetro {
p := []byte(f.PeerId)
addr, _ := poseidon.HashBytes(p)
addrBytes := string(addr.FillBytes(make([]byte, 32)))
existing, ok := peerIdTotals[f.PeerId]
amount, err := decimal.NewFromString(f.Reward)
@ -281,15 +407,19 @@ func CreateGenesisState(
peerIdTotals[f.PeerId] = existing.Add(amount)
}
if _, ok := peerSeniority[f.PeerId]; !ok {
peerSeniority[f.PeerId] = 0
if _, ok := peerSeniority[addrBytes]; !ok {
peerSeniority[addrBytes] = 0
}
peerSeniority[f.PeerId] = peerSeniority[f.PeerId] + (10 * 6 * 60 * 24 * 30)
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 30)
}
logger.Info("encoding fourth retro state")
for _, f := range fourthRetro {
p := []byte(f.PeerId)
addr, _ := poseidon.HashBytes(p)
addrBytes := string(addr.FillBytes(make([]byte, 32)))
existing, ok := peerIdTotals[f.PeerId]
amount, err := decimal.NewFromString(f.Reward)
@ -303,11 +433,11 @@ func CreateGenesisState(
peerIdTotals[f.PeerId] = existing.Add(amount)
}
if _, ok := peerSeniority[f.PeerId]; !ok {
peerSeniority[f.PeerId] = 0
if _, ok := peerSeniority[addrBytes]; !ok {
peerSeniority[addrBytes] = 0
}
peerSeniority[f.PeerId] = peerSeniority[f.PeerId] + (10 * 6 * 60 * 24 * 31)
peerSeniority[addrBytes] = peerSeniority[addrBytes] + (10 * 6 * 60 * 24 * 31)
}
genesisState := &protobufs.TokenOutputs{

View File

@ -1,6 +1,14 @@
package protobufs
import "math/big"
import (
"encoding/binary"
"math/big"
"github.com/iden3/go-iden3-crypto/poseidon"
pcrypto "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/pkg/errors"
)
func (t *TokenRequest) Priority() *big.Int {
switch p := t.Request.(type) {
@ -11,3 +19,42 @@ func (t *TokenRequest) Priority() *big.Int {
}
return big.NewInt(0)
}
func (t *MintCoinRequest) RingAndParallelism(
ringCalc func(addr []byte) int,
) (int, uint32, error) {
payload := []byte("mint")
for _, p := range t.Proofs {
payload = append(payload, p...)
}
if err := t.Signature.Verify(payload); err != nil {
return -1, 0, errors.New("invalid")
}
pk, err := pcrypto.UnmarshalEd448PublicKey(
t.Signature.PublicKey.KeyValue,
)
if err != nil {
return -1, 0, errors.New("invalid")
}
peerId, err := peer.IDFromPublicKey(pk)
if err != nil {
return -1, 0, errors.New("invalid")
}
altAddr, err := poseidon.HashBytes([]byte(peerId))
if err != nil {
return -1, 0, errors.New("invalid")
}
ring := ringCalc(altAddr.FillBytes(make([]byte, 32)))
if ring == -1 {
return -1, 0, errors.New("invalid")
}
if t.Proofs != nil && len(t.Proofs) >= 3 && len(t.Proofs[1]) == 4 {
return ring, binary.BigEndian.Uint32(t.Proofs[1]), nil
}
return -1, 0, errors.New("invalid")
}

View File

@ -23,6 +23,7 @@ type CoinStore interface {
)
GetCoinByAddress(txn Transaction, address []byte) (*protobufs.Coin, error)
GetPreCoinProofByAddress(address []byte) (*protobufs.PreCoinProof, error)
RangePreCoinProofs() (Iterator, error)
PutCoin(
txn Transaction,
frameNumber uint64,
@ -251,6 +252,18 @@ func (p *PebbleCoinStore) GetPreCoinProofByAddress(address []byte) (
return proof, nil
}
func (p *PebbleCoinStore) RangePreCoinProofs() (Iterator, error) {
iter, err := p.db.NewIter(
proofKey(bytes.Repeat([]byte{0x00}, 32)),
proofKey(bytes.Repeat([]byte{0xff}, 32)),
)
if err != nil {
return nil, errors.Wrap(err, "range pre coin proofs")
}
return iter, nil
}
func (p *PebbleCoinStore) PutCoin(
txn Transaction,
frameNumber uint64,

View File

@ -89,12 +89,13 @@ func TestPackAndVerifyOutput(t *testing.T) {
require.NoError(t, err)
}
tree, payload, output := tries.PackOutputIntoPayloadAndProof(
tree, payload, output, err := tries.PackOutputIntoPayloadAndProof(
outputs,
tc.modulo,
frame,
previousTree,
)
require.NoError(t, err)
require.NotNil(t, tree)
require.NotEmpty(t, payload)
require.NotEmpty(t, output)

View File

@ -134,7 +134,7 @@ func (t *RollingFrecencyCritbitTrie) FindNearestAndApproximateNeighbors(
var traverse func(p *Node, address []byte) bool
traverse = func(p *Node, address []byte) bool {
if len(ret) > 1024 {
if len(ret) > 2048 {
return true
}