diff options
author | Wei-Ning Huang <w@dexon.org> | 2019-01-13 16:21:17 +0800 |
---|---|---|
committer | Wei-Ning Huang <w@byzantine-lab.io> | 2019-06-12 17:27:21 +0800 |
commit | 56680e215e7e27ab8896d782876ee64881cae6ff (patch) | |
tree | 40daa411b7f1ee239b702ccc7987b6130892d7e6 /consensus/dexcon/dexcon.go | |
parent | f82a81c6fa36c8ee6ba6a55e0662930c8f0d2658 (diff) | |
download | go-tangerine-56680e215e7e27ab8896d782876ee64881cae6ff.tar go-tangerine-56680e215e7e27ab8896d782876ee64881cae6ff.tar.gz go-tangerine-56680e215e7e27ab8896d782876ee64881cae6ff.tar.bz2 go-tangerine-56680e215e7e27ab8896d782876ee64881cae6ff.tar.lz go-tangerine-56680e215e7e27ab8896d782876ee64881cae6ff.tar.xz go-tangerine-56680e215e7e27ab8896d782876ee64881cae6ff.tar.zst go-tangerine-56680e215e7e27ab8896d782876ee64881cae6ff.zip |
consensus: implement DEXON cryptoeconomics v4.0 (#145)
Diffstat (limited to 'consensus/dexcon/dexcon.go')
-rw-r--r-- | consensus/dexcon/dexcon.go | 67 |
1 files changed, 52 insertions, 15 deletions
diff --git a/consensus/dexcon/dexcon.go b/consensus/dexcon/dexcon.go index f0a133ccf..4480f64cb 100644 --- a/consensus/dexcon/dexcon.go +++ b/consensus/dexcon/dexcon.go @@ -23,17 +23,17 @@ import ( "github.com/dexon-foundation/dexon/consensus" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - "github.com/dexon-foundation/dexon/params" + "github.com/dexon-foundation/dexon/core/vm" "github.com/dexon-foundation/dexon/rpc" ) -type ConfigurationFetcher interface { - DexconConfiguration(round uint64) *params.DexconConfig +type GovernanceStateFetcher interface { + GetGovStateHelperAtRound(round uint64) *vm.GovernanceStateHelper } // Dexcon is a delegated proof-of-stake consensus engine. type Dexcon struct { - configFetcher ConfigurationFetcher + govStateFetcer GovernanceStateFetcher } // New creates a Clique proof-of-authority consensus engine with the initial @@ -42,11 +42,11 @@ func New() *Dexcon { return &Dexcon{} } -// SetConfigFetcher sets the config fetcher for Dexcon. The reason this is not +// SetGovStateFetcher sets the config fetcher for Dexcon. The reason this is not // passed in the New() method is to bypass cycle dependencies when initializing // dex backend. -func (d *Dexcon) SetConfigFetcher(fetcher ConfigurationFetcher) { - d.configFetcher = fetcher +func (d *Dexcon) SetGovStateFetcher(fetcher GovernanceStateFetcher) { + d.govStateFetcer = fetcher } // Author implements consensus.Engine, returning the Ethereum address recovered @@ -107,13 +107,55 @@ func (d *Dexcon) Prepare(chain consensus.ChainReader, header *types.Header) erro return nil } +func (d *Dexcon) calculateBlockReward(round int64, state *state.StateDB) *big.Int { + gs := d.govStateFetcer.GetGovStateHelperAtRound(uint64(round)) + config := gs.Configuration() + + gsCurrent := vm.GovernanceStateHelper{state} + configCurrent := gsCurrent.Configuration() + heightCurrent := gsCurrent.RoundHeight(big.NewInt(round)).Uint64() + + blocksPerRound := uint64(0) + + // The initial round, calculate an approximate number of round base on config. + if round == 0 || heightCurrent == 0 { + blocksPerRound = uint64(config.NumChains) * config.RoundInterval / config.MinBlockInterval + } else { + heightPrev := gsCurrent.RoundHeight(big.NewInt(round - 1)).Uint64() + blocksPerRound = heightCurrent - heightPrev + } + + // blockReard = miningVelocity * totalStaked * roundInterval / aYear / numBlocksInPrevRound + numerator, _ := new(big.Float).Mul( + new(big.Float).Mul( + big.NewFloat(float64(configCurrent.MiningVelocity)), + new(big.Float).SetInt(gs.TotalStaked())), + new(big.Float).SetInt(gs.RoundInterval())).Int(nil) + + reward := new(big.Int).Div(numerator, + new(big.Int).Mul( + big.NewInt(86400*1000*365), + big.NewInt(int64(blocksPerRound)))) + + return reward +} + // Finalize implements consensus.Engine, ensuring no uncles are set, nor block // rewards given, and returns the final block. func (d *Dexcon) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { - config := d.configFetcher.DexconConfiguration(header.Round) - reward := new(big.Int).Div(config.BlockReward, big.NewInt(int64(config.NumChains))) + reward := d.calculateBlockReward(int64(header.Round), state) state.AddBalance(header.Coinbase, reward) + gs := vm.GovernanceStateHelper{state} + gs.IncTotalSupply(reward) + + config := gs.Configuration() + + // Check if halving checkpoint reached. + if gs.TotalSupply().Cmp(config.NextHalvingSupply) >= 0 { + gs.MiningHalved() + } + header.Reward = reward header.Root = state.IntermediateRoot(true) return types.NewBlock(header, txs, uncles, receipts), nil @@ -145,10 +187,5 @@ func (d *Dexcon) Close() error { // APIs implements consensus.Engine, returning the user facing RPC API to allow // controlling the signer voting. func (d *Dexcon) APIs(chain consensus.ChainReader) []rpc.API { - return []rpc.API{{ - Namespace: "dexcon", - Version: "1.0", - Service: &API{dexcon: d}, - Public: false, - }} + return []rpc.API{} } |