Skip to content

Commit cb1b4e1

Browse files
committed
Merge branch 'staging' into sb/features/pip-0016-developer-rewards
2 parents eec4438 + 4054a7d commit cb1b4e1

4 files changed

Lines changed: 163 additions & 10 deletions

File tree

node/burns.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
package node
22

3-
import "encoding/hex"
3+
import (
4+
"encoding/hex"
5+
6+
"github.com/Factom-Asset-Tokens/factom"
7+
)
48

59
var (
610
// BurnAddress is the mainnet burn address
711
BurnAddress = "EC2BURNFCT2PEGNETooo1oooo1oooo1oooo1oooo1oooo19wthin"
12+
13+
// BurnAddress that can be used for all assets
14+
GlobalBurnAddress = "FA2BURNBABYBURNoooooooooooooooooooooooooooooooDGvNXy"
15+
16+
// Global Burn Address as proper FAAddress
17+
FAGlobalBurnAddress factom.FAAddress
18+
819
// BurnRCD is the rcd representation of the burn address
920
BurnRCD = [32]byte{}
1021
)

node/node.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,18 @@ func NewPegnetd(ctx context.Context, conf *viper.Viper) (*Pegnetd, error) {
110110
}
111111
}
112112

113+
// init burn address
114+
FAGlobalBurnAddress, err := factom.NewFAAddress(GlobalBurnAddress)
115+
if err != nil {
116+
log.WithFields(log.Fields{
117+
"error": err,
118+
}).Info("error getting burn address")
119+
}
120+
121+
log.WithFields(log.Fields{
122+
"addr": FAGlobalBurnAddress,
123+
}).Info("burn address loaded")
124+
113125
grader.InitLX()
114126
return n, nil
115127
}

node/pegnet/txhistory.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,3 +509,63 @@ func (p *Pegnet) InsertDeveloperRewardCoinbase(tx *sql.Tx, txid string, addTxid
509509

510510
return nil
511511
}
512+
513+
// Special construction to nullify burn address
514+
func (p *Pegnet) InsertZeroingCoinbase(tx *sql.Tx, txid string, addTxid string, height uint32, heightTimestamp time.Time, payout uint64, asset string, faAdd factom.FAAddress) error {
515+
txidBytes, err := hex.DecodeString(txid)
516+
if err != nil {
517+
return err
518+
}
519+
520+
// First we need to record the batch. The batch is the entire set of transactions, where
521+
// each tx is a stake payout.
522+
stmt, err := tx.Prepare(`INSERT INTO "pn_history_txbatch"
523+
(entry_hash, height, blockorder, timestamp, executed) VALUES
524+
(?, ?, ?, ?, ?)`)
525+
if err != nil {
526+
return err
527+
}
528+
529+
// The Entryhash is the custom txid, it is not an actual entry on chain
530+
// The executed height is the same height as the recorded.
531+
_, err = stmt.Exec(txidBytes, height, 0, heightTimestamp.Unix(), height)
532+
if err != nil {
533+
return err
534+
}
535+
536+
// Now we record balance zeroing .
537+
538+
// All addresses are stored as bytes in the sqlitedb
539+
add := faAdd[:]
540+
// index for the address
541+
index, _, err := SplitTxID(txid)
542+
if err != nil {
543+
return err
544+
}
545+
546+
// Decrease each balance as a coinbase.
547+
// Insert the TX
548+
coinbaseStatement, err := tx.Prepare(`INSERT INTO "pn_history_transaction"
549+
(entry_hash, tx_index, action_type, from_address, from_asset, from_amount, to_asset, to_amount, outputs) VALUES
550+
(?, ?, ?, ?, ?, ?, ?, ?, ?)`)
551+
if err != nil {
552+
return err
553+
}
554+
555+
_, err = coinbaseStatement.Exec(txidBytes, index, Coinbase, add, "", 0, asset, -payout, "") // -payout means we substract value
556+
if err != nil {
557+
return err
558+
}
559+
560+
// Insert into lookup table
561+
lookup, err := tx.Prepare(insertLookupQuery)
562+
if err != nil {
563+
return err
564+
}
565+
566+
if _, err = lookup.Exec(txidBytes, index, add); err != nil {
567+
return err
568+
}
569+
570+
return nil
571+
}

node/sync.go

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func (d *Pegnetd) GetCurrentSync() uint32 {
2727
func (d *Pegnetd) DBlockSync(ctx context.Context) {
2828
retryPeriod := d.Config.GetDuration(config.DBlockSyncRetryPeriod)
2929
isFirstSync := true
30+
3031
OuterSyncLoop:
3132
for {
3233
if isDone(ctx) {
@@ -85,6 +86,16 @@ OuterSyncLoop:
8586
hLog.WithError(err).Errorf("failed to start transaction")
8687
continue
8788
}
89+
90+
////////////////////////
91+
// Zeroing funds at Global Burn Address
92+
93+
// One time operation, Inserts negative balance for the burn address that used during the attack
94+
// We need to do this before main logic because sqlite db will be locked
95+
if d.Sync.Synced+1 == V20HeightActivation {
96+
d.NullifyBurnAddress(ctx, tx, d.Sync.Synced+1)
97+
}
98+
8899
// We are not synced, so we need to iterate through the dblocks and sync them
89100
// one by one. We can only sync our current synced height +1
90101
// TODO: This skips the genesis block. I'm sure that is fine
@@ -157,6 +168,57 @@ OuterSyncLoop:
157168

158169
}
159170

171+
func (d *Pegnetd) NullifyBurnAddress(ctx context.Context, tx *sql.Tx, height uint32) error {
172+
fLog := log.WithFields(log.Fields{"height": height})
173+
174+
dblock := new(factom.DBlock)
175+
dblock.Height = height
176+
if err := dblock.Get(nil, d.FactomClient); err != nil {
177+
return err
178+
}
179+
heightTimestamp := dblock.Timestamp
180+
// We need to mock a TXID to record zeroing
181+
txid := fmt.Sprintf("%064d", height)
182+
183+
// 1. check current balance
184+
// 2. substract amounts for every ticker
185+
186+
// Get all balances for the address
187+
balances, err := d.Pegnet.SelectBalances(&FAGlobalBurnAddress)
188+
189+
if err != nil {
190+
fLog.WithFields(log.Fields{
191+
"err": err,
192+
}).Info("zeroing burn | balances retrieval failed")
193+
}
194+
195+
for ticker := fat2.PTickerInvalid + 1; ticker < fat2.PTickerMax; ticker++ {
196+
// Substract from every issuance
197+
value, _ := balances[ticker]
198+
_, _, err := d.Pegnet.SubFromBalance(tx, &FAGlobalBurnAddress, ticker, value) // lastInd, txErr, err
199+
if err != nil {
200+
fLog.WithFields(log.Fields{
201+
"ticker": ticker,
202+
"balance": value,
203+
}).Info("zeroing burn | substract from balance failed")
204+
}
205+
206+
// Mock entry hash value
207+
addTxid := fmt.Sprintf("%d-%s", ticker, txid)
208+
209+
err = d.Pegnet.InsertZeroingCoinbase(tx, txid, addTxid, height, heightTimestamp, value, ticker.String(), FAGlobalBurnAddress)
210+
if err != nil {
211+
fLog.WithFields(log.Fields{
212+
"error": err,
213+
}).Info("zeroing burn | coinbase tx failed")
214+
return err
215+
}
216+
217+
}
218+
219+
return nil
220+
}
221+
160222
// If SyncBlock returns no error, than that height was synced and saved. If any part of the sync fails,
161223
// the whole sync should be rolled back and not applied. An error should then be returned.
162224
// The context should be respected if it is cancelled
@@ -811,7 +873,8 @@ func (d *Pegnetd) recordBatch(sqlTx *sql.Tx, txBatch *fat2.TransactionBatch, rat
811873
}
812874

813875
// Outputs
814-
if tx.IsConversion() { // Conv Output
876+
if tx.IsConversion() {
877+
// Conversions Output
815878
outputAmount, err := conversions.Convert(int64(tx.Input.Amount), rates[tx.Input.Type], rates[tx.Conversion])
816879
if err != nil {
817880
return err
@@ -820,19 +883,26 @@ func (d *Pegnetd) recordBatch(sqlTx *sql.Tx, txBatch *fat2.TransactionBatch, rat
820883
if err = d.Pegnet.SetTransactionHistoryConvertedAmount(sqlTx, txBatch, txIndex, outputAmount); err != nil {
821884
return err
822885
}
886+
823887
_, err = d.Pegnet.AddToBalance(sqlTx, &tx.Input.Address, tx.Conversion, uint64(outputAmount))
824888
if err != nil {
825889
return err
826890
}
827-
} else { // Transfer Outputs
891+
892+
} else {
893+
// Transfer Outputs
894+
828895
for _, transfer := range tx.Transfers {
829-
_, err = d.Pegnet.AddToBalance(sqlTx, &transfer.Address, tx.Input.Type, transfer.Amount)
830-
if err != nil {
831-
return err
832-
}
833-
_, err = d.Pegnet.InsertTransactionRelation(sqlTx, transfer.Address, txBatch.Entry.Hash, uint64(txIndex), true, false)
834-
if err != nil {
835-
return err
896+
// if transfer to Burn address do nothing, otherwise add balances
897+
if transfer.Address != FAGlobalBurnAddress {
898+
_, err = d.Pegnet.AddToBalance(sqlTx, &transfer.Address, tx.Input.Type, transfer.Amount)
899+
if err != nil {
900+
return err
901+
}
902+
_, err = d.Pegnet.InsertTransactionRelation(sqlTx, transfer.Address, txBatch.Entry.Hash, uint64(txIndex), true, false)
903+
if err != nil {
904+
return err
905+
}
836906
}
837907
}
838908
}

0 commit comments

Comments
 (0)