Skip to content

Commit

Permalink
Add "events" to block response #100
Browse files Browse the repository at this point in the history
  • Loading branch information
danil-lashin committed Sep 11, 2018
1 parent 26a2f05 commit deeec7a
Show file tree
Hide file tree
Showing 10 changed files with 265 additions and 14 deletions.
6 changes: 2 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
# Changelog

## TBD

- [api] Add validators rewards to block api

## 0.3.3
*Sept 8th, 2018*

IMPROVEMENT

- [api] Add block size in bytes
- [api] #100 Add "events" to block response. To get events add ?withEvents=true to request URL.
WARNING! You should sync blockchain from scratch to get this feature working

## 0.3.2
*Sept 8th, 2018*
Expand Down
2 changes: 2 additions & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"github.com/MinterTeam/minter-go-node/config"
"github.com/MinterTeam/minter-go-node/eventsdb"
"log"
"net/http"

Expand All @@ -26,6 +27,7 @@ var (

func init() {
cryptoAmino.RegisterAmino(cdc)
eventsdb.RegisterAminoEvents(cdc)
}

func RunApi(b *minter.Blockchain, node *node.Node) {
Expand Down
28 changes: 25 additions & 3 deletions api/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/MinterTeam/minter-go-node/core/rewards"
"github.com/MinterTeam/minter-go-node/core/transaction"
"github.com/MinterTeam/minter-go-node/core/types"
"github.com/MinterTeam/minter-go-node/eventsdb"
"github.com/gorilla/mux"
"github.com/tendermint/tendermint/libs/common"
"math/big"
Expand All @@ -21,6 +22,7 @@ type BlockResponse struct {
NumTxs int64 `json:"num_txs"`
TotalTxs int64 `json:"total_txs"`
Transactions []BlockTransactionResponse `json:"transactions"`
Events json.RawMessage `json:"events,omitempty"`
Precommits json.RawMessage `json:"precommits"`
BlockReward string `json:"block_reward"`
Size int `json:"size"`
Expand All @@ -45,6 +47,7 @@ func Block(w http.ResponseWriter, r *http.Request) {

vars := mux.Vars(r)
height, _ := strconv.ParseInt(vars["height"], 10, 64)
includeEvents, _ := strconv.ParseBool(r.URL.Query().Get("withEvents"))

block, err := client.Block(&height)
blockResults, err := client.BlockResults(&height)
Expand All @@ -60,8 +63,6 @@ func Block(w http.ResponseWriter, r *http.Request) {
return
}

w.WriteHeader(http.StatusOK)

txs := make([]BlockTransactionResponse, len(block.Block.Data.Txs))

for i, rawTx := range block.Block.Data.Txs {
Expand Down Expand Up @@ -98,18 +99,39 @@ func Block(w http.ResponseWriter, r *http.Request) {

size := len(encodedBlock)

var eventsRaw []byte

if includeEvents {
events := eventsdb.GetCurrent().GetEvents(height)

if len(events) > 0 {
eventsRaw, err = cdc.MarshalJSON(events)

if err != nil {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(Response{
Code: 0,
Log: err.Error(),
})
return
}
}
}

response := BlockResponse{
Hash: block.Block.Hash(),
Height: block.Block.Height,
Time: block.Block.Time,
NumTxs: block.Block.NumTxs,
TotalTxs: block.Block.TotalTxs,
Transactions: txs,
Precommits: json.RawMessage(precommits),
Precommits: precommits,
BlockReward: rewards.GetRewardForBlock(uint64(height)).String(),
Size: size,
Events: eventsRaw,
}

w.WriteHeader(http.StatusOK)
err = json.NewEncoder(w).Encode(Response{
Code: 0,
Result: response,
Expand Down
4 changes: 2 additions & 2 deletions core/minter/minter.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res
app.stateDeliver.SetValidatorPresent(address)
app.validatorsStatuses[address] = ValidatorPresent
} else {
app.stateDeliver.SetValidatorAbsent(address)
app.stateDeliver.SetValidatorAbsent(req.Header.Height, address)
app.validatorsStatuses[address] = ValidatorAbsent
}
}
Expand Down Expand Up @@ -193,7 +193,7 @@ func (app *Blockchain) EndBlock(req abciTypes.RequestEndBlock) abciTypes.Respons

// pay rewards
if app.height%12 == 0 {
app.stateDeliver.PayRewards()
app.stateDeliver.PayRewards(req.Height)
}

hasDroppedValidators := false
Expand Down
14 changes: 14 additions & 0 deletions core/state/state_frozen_fund.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package state

import (
"github.com/MinterTeam/minter-go-node/eventsdb"
"io"

"fmt"
Expand Down Expand Up @@ -119,6 +120,9 @@ func (c *stateFrozenFund) PunishFund(candidateAddress [20]byte) {
}

func (c *stateFrozenFund) punishFund(candidateAddress [20]byte) {

edb := eventsdb.GetCurrent()

var NewList []FrozenFund

for _, item := range c.data.List {
Expand All @@ -134,6 +138,16 @@ func (c *stateFrozenFund) punishFund(candidateAddress [20]byte) {
newValue.Mul(newValue, big.NewInt(95))
newValue.Div(newValue, big.NewInt(100))

slashed := big.NewInt(0).Set(item.Value)
slashed.Sub(slashed, newValue)

edb.SaveEvent(int64(c.blockHeight), eventsdb.SlashEvent{
Address: item.Address,
Amount: slashed.String(),
Coin: item.Coin,
ValidatorPubKey: item.CandidateKey,
})

item.Value = newValue
}

Expand Down
60 changes: 58 additions & 2 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package state

import (
"fmt"
"github.com/MinterTeam/minter-go-node/eventsdb"
"math/big"
"sync"

Expand Down Expand Up @@ -812,7 +813,9 @@ func (s *StateDB) AddAccumReward(pubkey types.Pubkey, reward *big.Int) {
}
}

func (s *StateDB) PayRewards() {
func (s *StateDB) PayRewards(height int64) {
edb := eventsdb.GetCurrent()

validators := s.getStateValidators()

for i := range validators.data {
Expand All @@ -827,12 +830,24 @@ func (s *StateDB) PayRewards() {
DAOReward.Mul(DAOReward, big.NewInt(int64(dao.Commission)))
DAOReward.Div(DAOReward, big.NewInt(100))
s.AddBalance(dao.Address, types.GetBaseCoin(), DAOReward)
edb.SaveEvent(height, eventsdb.RewardEvent{
Role: eventsdb.RoleDAO,
Address: dao.Address,
Amount: DAOReward.String(),
ValidatorPubKey: validator.PubKey,
})

// pay commission to Developers
DevelopersReward := big.NewInt(0).Set(totalReward)
DevelopersReward.Mul(DevelopersReward, big.NewInt(int64(developers.Commission)))
DevelopersReward.Div(DevelopersReward, big.NewInt(100))
s.AddBalance(developers.Address, types.GetBaseCoin(), DevelopersReward)
edb.SaveEvent(height, eventsdb.RewardEvent{
Role: eventsdb.RoleDevelopers,
Address: developers.Address,
Amount: DevelopersReward.String(),
ValidatorPubKey: validator.PubKey,
})

totalReward.Sub(totalReward, DevelopersReward)
totalReward.Sub(totalReward, DAOReward)
Expand All @@ -843,6 +858,12 @@ func (s *StateDB) PayRewards() {
validatorReward.Div(validatorReward, big.NewInt(100))
totalReward.Sub(totalReward, validatorReward)
s.AddBalance(validator.CandidateAddress, types.GetBaseCoin(), validatorReward)
edb.SaveEvent(height, eventsdb.RewardEvent{
Role: eventsdb.RoleValidator,
Address: validator.CandidateAddress,
Amount: validatorReward.String(),
ValidatorPubKey: validator.PubKey,
})

candidate := s.GetStateCandidate(validator.PubKey)

Expand All @@ -858,7 +879,18 @@ func (s *StateDB) PayRewards() {
reward.Mul(reward, stake.BipValue)
reward.Div(reward, validator.TotalBipStake)

if reward.Cmp(types.Big0) < 1 {
continue
}

s.AddBalance(stake.Owner, types.GetBaseCoin(), reward)

edb.SaveEvent(height, eventsdb.RewardEvent{
Role: eventsdb.RoleDelegator,
Address: stake.Owner,
Amount: reward.String(),
ValidatorPubKey: candidate.PubKey,
})
}

validator.AccumReward.SetInt64(0)
Expand Down Expand Up @@ -990,7 +1022,9 @@ func (s *StateDB) SetCandidateOffline(pubkey []byte) {
s.MarkStateCandidateDirty()
}

func (s *StateDB) SetValidatorAbsent(address [20]byte) {
func (s *StateDB) SetValidatorAbsent(height int64, address [20]byte) {
edb := eventsdb.GetCurrent()

validators := s.getStateValidators()

for i := range validators.data {
Expand Down Expand Up @@ -1026,6 +1060,16 @@ func (s *StateDB) SetValidatorAbsent(address [20]byte) {
newValue.Mul(newValue, big.NewInt(99))
newValue.Div(newValue, big.NewInt(100))

slashed := big.NewInt(0).Set(stake.Value)
slashed.Sub(slashed, newValue)

edb.SaveEvent(height, eventsdb.SlashEvent{
Address: stake.Owner,
Amount: slashed.String(),
Coin: stake.Coin,
ValidatorPubKey: candidate.PubKey,
})

candidate.Stakes[j] = Stake{
Owner: stake.Owner,
Coin: stake.Coin,
Expand All @@ -1049,6 +1093,8 @@ func (s *StateDB) SetValidatorAbsent(address [20]byte) {

func (s *StateDB) PunishByzantineValidator(currentBlock uint64, address [20]byte) {

edb := eventsdb.GetCurrent()

validators := s.getStateValidators()

for i := range validators.data {
Expand All @@ -1072,6 +1118,16 @@ func (s *StateDB) PunishByzantineValidator(currentBlock uint64, address [20]byte
newValue.Mul(newValue, big.NewInt(95))
newValue.Div(newValue, big.NewInt(100))

slashed := big.NewInt(0).Set(stake.Value)
slashed.Sub(slashed, newValue)

edb.SaveEvent(int64(currentBlock), eventsdb.SlashEvent{
Address: stake.Owner,
Amount: slashed.String(),
Coin: stake.Coin,
ValidatorPubKey: candidate.PubKey,
})

s.GetOrNewStateFrozenFunds(currentBlock+UnbondPeriod).AddFund(stake.Owner, candidate.PubKey, stake.Coin, newValue)
}

Expand Down
5 changes: 2 additions & 3 deletions core/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@
package types

import (
"bytes"
"encoding/hex"
"fmt"
"github.com/MinterTeam/minter-go-node/hexutil"
"math/big"
"math/rand"
"reflect"

"bytes"
"github.com/MinterTeam/minter-go-node/hexutil"
)

const (
Expand Down
11 changes: 11 additions & 0 deletions eventsdb/amino.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package eventsdb

import "github.com/tendermint/go-amino"

func RegisterAminoEvents(codec *amino.Codec) {
codec.RegisterInterface((*Event)(nil), nil)
codec.RegisterConcrete(RewardEvent{},
"minter/RewardEvent", nil)
codec.RegisterConcrete(SlashEvent{},
"minter/SlashEvent", nil)
}
61 changes: 61 additions & 0 deletions eventsdb/events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package eventsdb

import (
"encoding/json"
"fmt"
"github.com/MinterTeam/minter-go-node/core/types"
)

type Role string

var (
RoleValidator Role = "Validator"
RoleDelegator Role = "Delegator"
RoleDAO Role = "DAO"
RoleDevelopers Role = "Developers"
)

type Event interface{}
type Events []Event

type RewardEvent struct {
Role Role
Address types.Address
Amount string
ValidatorPubKey types.Pubkey
}

func (e RewardEvent) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Role string `json:"role"`
Address string `json:"address"`
Amount string `json:"amount"`
ValidatorPubKey string `json:"validator_pub_key"`
}{
Role: string(e.Role),
Address: e.Address.String(),
Amount: e.Amount,
ValidatorPubKey: fmt.Sprintf("Mp%x", e.ValidatorPubKey),
})
}

type SlashEvent struct {
Address types.Address
Amount string
Coin types.CoinSymbol
ValidatorPubKey types.Pubkey
}

func (e SlashEvent) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Address string `json:"address"`
Amount string `json:"amount"`
Coin string `json:"coin"`
ValidatorPubKey string `json:"validator_pub_key"`
}{
Address: e.Address.String(),
Amount: e.Amount,
Coin: e.Coin.String(),
ValidatorPubKey: fmt.Sprintf("Mp%x", e.ValidatorPubKey),
})
}
Loading

0 comments on commit deeec7a

Please sign in to comment.