Skip to content

Commit 21e9f7e

Browse files
authored
Merge pull request #134 from sigrlami/sb/features/pip-0016-developer-rewards
PIP 16 - Developer Rewards Mechanism
2 parents 9d453a0 + b30100a commit 21e9f7e

File tree

3 files changed

+164
-0
lines changed

3 files changed

+164
-0
lines changed

node/devs.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package node
2+
3+
// Special structure for the Developer rewards
4+
type DevReward struct {
5+
DevGroup string // group or information about reward
6+
DevAddress string // FCT address where to send developer reward
7+
DevRewardPct float64 // % from total development rewards
8+
}
9+
10+
// Hardcode developers who work active on PegNet to avoid manipulations from config files
11+
//
12+
// contains the percentage distribution of the total 2000
13+
// defined in `pegnet` repo `modules/conversions/conversionlimit.go` as PerBlockDevelopers
14+
//
15+
// TODO: in v2.5 move into special Developer Rewards Chain (DRC)
16+
var (
17+
DeveloperRewardAddreses = []DevReward{
18+
{"Listing Tech Support", "FA2i9WZqJnaKbJxDY2AZdVgewE28uCcSwoFt8LJCMtGCC7tpCa2n", 10.00},
19+
{"Architecture Dev for PegNet 2.5", "FA37cGXKWMtf2MmHy3n1rMCYeLVuR5MpDaP4VXVeFavjJCJLYYez", 9.0},
20+
{"Trading Bots Work", "FA2wDRieaBrWeZHVuXXWUHY6t9nKCVCCKAMS5xknLUExuVAq3ziS", 9.0},
21+
{"Mining Pool Support / Dev/ Infra Hosting/ Gateway Operation", "FA3LDEA5fcskV6ZoFpKE84qPcjd7GYjEnswGHMZXL1V9d14wmgh3", 9.0},
22+
{"Media Tech Support", "FA381EygeEXjZzB6hNvxbE4oSUzHZMfvGByMZoW5UrG1gHEKJcNK", 8.0},
23+
{"Social Coverage User Support", "FA2DxkaTx1k2oGfbTqvwVMScSHHac7JFRiBjRngjRnqQpeBxsLhA", 8.0},
24+
{"pTrader + PIPs", "FA2Ersb227gn7eWJ2HPsHZ5QqxfMBZhSjwixQ44dAS17CtRXSDRU", 8.0},
25+
{"Desktop Wallet + PIPs", " FA2eFEVUzTQZxNp3LYYgjPaaHUfGmuvShhtBdGB2BBWMeByPCmJy", 8.0},
26+
{"DeFi Integrations + PIPs Work", "FA2z6Nnaj8a5nXmwZD8tYhDENAx8ciVE3xeNeixKiFj22vZEZEdT", 8.0},
27+
{"Explorer + Mobile", " FA2T72oxBxXvnujNdsVUshqFM2qV1W4nJy33nkrpxbYQV8rFbUPP", 5.0},
28+
{"Prosper / Staking GUI Upgrades", "FA2cEaq1GdGfFjhymiTEzW24DocZFZHNBqe9qkT18YPaL5ZzsgRi", 5.0},
29+
{"Payment Intergrations Work", "FA2YhZBZbc4V858ao7dJuAqRC4iwA3MrbZs7BHUPK7Mq19yYdMwZ", 3.0},
30+
{"General Development Tasks", "FA3PYuvrsDvkhnekokVNrgLn7JiL5pChSBTtR9gZB1mVGFVB7JRD", 3.0},
31+
{"Gateway Ethereum Upgrade", "FA2Wy7AzeoBuaXYnGu67xa5zdNkmqTbPryUgpy7qVPvj46GRZkep", 2.0},
32+
{"Statistics & Visualizations of PegNet", "FA3dsCiKGzwrTALfX4T2CKv8wCmNMxwJx3jS4jz1ST9fwge9Wrnm", 2.0},
33+
{"Trading Tech Support", "FA2a2nXgkBg7pL5wrgm99rLZDGFs2T8jfTgMuia6ep8ZMkVtPe8E", 3.00},
34+
}
35+
)

node/pegnet/txhistory.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,65 @@ func (p *Pegnet) InsertStakingCoinbase(tx *sql.Tx, txid string, height uint32, h
451451
return nil
452452
}
453453

454+
func (p *Pegnet) InsertDeveloperRewardCoinbase(tx *sql.Tx, txid string, addTxid string, height uint32, heightTimestamp time.Time, payout uint64, faAdd factom.FAAddress) error {
455+
txidBytes, err := hex.DecodeString(txid)
456+
if err != nil {
457+
return err
458+
}
459+
460+
// First we need to record the batch. The batch is the entire set of transactions, where
461+
// each tx is a deverloper reward.
462+
stmt, err := tx.Prepare(`INSERT INTO "pn_history_txbatch"
463+
(entry_hash, height, blockorder, timestamp, executed) VALUES
464+
(?, ?, ?, ?, ?)`)
465+
if err != nil {
466+
return err
467+
}
468+
469+
// The Entryhash is the custom txid, it is not an actual entry on chain
470+
// The executed height is the same height as the recorded.
471+
_, err = stmt.Exec(txidBytes, height, 0, heightTimestamp.Unix(), height)
472+
if err != nil {
473+
return err
474+
}
475+
476+
// Now we record each developer reward.
477+
478+
// All addresses are stored as bytes in the sqlitedb
479+
add := faAdd[:]
480+
// index for the address
481+
index, _, err := SplitTxID(addTxid)
482+
if err != nil {
483+
return err
484+
}
485+
486+
// Insert each payout as a coinbase.
487+
// Insert the TX
488+
coinbaseStatement, err := tx.Prepare(`INSERT INTO "pn_history_transaction"
489+
(entry_hash, tx_index, action_type, from_address, from_asset, from_amount, to_asset, to_amount, outputs) VALUES
490+
(?, ?, ?, ?, ?, ?, ?, ?, ?)`)
491+
if err != nil {
492+
return err
493+
}
494+
495+
_, err = coinbaseStatement.Exec(txidBytes, index, Coinbase, add, "", 0, "PEG", payout, "")
496+
if err != nil {
497+
return err
498+
}
499+
500+
// Insert into lookup table
501+
lookup, err := tx.Prepare(insertLookupQuery)
502+
if err != nil {
503+
return err
504+
}
505+
506+
if _, err = lookup.Exec(txidBytes, index, add); err != nil {
507+
return err
508+
}
509+
510+
return nil
511+
}
512+
454513
// Special construction to nullify burn address
455514
func (p *Pegnet) InsertZeroingCoinbase(tx *sql.Tx, txid string, addTxid string, height uint32, heightTimestamp time.Time, payout uint64, asset string, faAdd factom.FAAddress) error {
456515
txidBytes, err := hex.DecodeString(txid)

node/sync.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,15 @@ func (d *Pegnetd) SyncBlock(ctx context.Context, tx *sql.Tx, height uint32) erro
362362
}
363363
}
364364

365+
// 5) Apply Developers Rewards
366+
if height >= V20HeightActivation && height%pegnet.SnapshotRate == 0 {
367+
err := d.DevelopersPayouts(tx, fLog, height, dblock.Timestamp, DeveloperRewardAddreses)
368+
if err != nil {
369+
// something wrong happend during payout execution
370+
return err
371+
}
372+
}
373+
365374
return nil
366375
}
367376

@@ -484,6 +493,67 @@ func (d *Pegnetd) SnapshotPayouts(tx *sql.Tx, fLog *log.Entry, rates map[fat2.PT
484493
return nil
485494
}
486495

496+
// Developers Reward Payouts
497+
// implementation of PIP16 - distributed rewards collected for developers every 24h
498+
func (d *Pegnetd) DevelopersPayouts(tx *sql.Tx, fLog *log.Entry, height uint32, heightTimestamp time.Time, developers []DevReward) error {
499+
500+
totalPayout := uint64(conversions.PerBlockDevelopers) * pegnet.SnapshotRate // once a day
501+
payoutStart := time.Now()
502+
503+
// We need to mock a TXID to record dev rewards
504+
txid := fmt.Sprintf("%064d", height)
505+
506+
// we use hardcoded list of dev payouts
507+
i := 0
508+
for _, dev := range developers {
509+
510+
// we calculate developers reward from % pre-defined
511+
rewardPayout := uint64((conversions.PerBlockDevelopers / 100) * dev.DevRewardPct)
512+
addr, err := factom.NewFAAddress(dev.DevAddress)
513+
514+
_, err = d.Pegnet.AddToBalance(tx, &addr, fat2.PTickerPEG, rewardPayout)
515+
if err != nil {
516+
return err
517+
}
518+
519+
// Mock entry hash value
520+
addTxid := fmt.Sprintf("%d-%s", i, txid)
521+
i++
522+
523+
// Get dev address as FAAdress
524+
FADevAddress, err := factom.NewFAAddress(dev.DevAddress)
525+
if err != nil {
526+
log.WithFields(log.Fields{
527+
"error": err,
528+
"addr": dev.DevAddress,
529+
}).Info("error getting developer address")
530+
return err
531+
}
532+
533+
// ---- Database Payouts ----
534+
// Inserts tx into the db
535+
err = d.Pegnet.InsertDeveloperRewardCoinbase(tx, txid, addTxid, height, heightTimestamp, rewardPayout, FADevAddress)
536+
if err != nil {
537+
return err
538+
}
539+
540+
fLog.WithFields(log.Fields{
541+
"total": float64(totalPayout) / 1e8,
542+
"developer": len(dev.DevAddress),
543+
"PEG": float64(rewardPayout) / 1e8, // Float is good enough here
544+
}).Info("developer reward | paid out to")
545+
546+
}
547+
548+
fLog.WithFields(log.Fields{
549+
"total": float64(totalPayout) / 1e8,
550+
"elapsed": time.Since(payoutStart),
551+
"txid": txid,
552+
}).Info("developer rewards | paid out")
553+
554+
return nil
555+
}
556+
487557
func multiFetch(eblock *factom.EBlock, c *factom.Client) error {
488558
err := eblock.Get(nil, c)
489559
if err != nil {

0 commit comments

Comments
 (0)