-
Notifications
You must be signed in to change notification settings - Fork 12
/
sortition.go
72 lines (58 loc) · 1.76 KB
/
sortition.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package executors
import (
"errors"
"github.com/gallactic/gallactic/core/blockchain"
"github.com/gallactic/gallactic/core/state"
e "github.com/gallactic/gallactic/errors"
"github.com/gallactic/gallactic/txs"
"github.com/gallactic/gallactic/txs/tx"
tmRPC "github.com/tendermint/tendermint/rpc/core"
)
type SortitionContext struct {
Committing bool
BC *blockchain.Blockchain
Cache *state.Cache
}
func (ctx *SortitionContext) Execute(txEnv *txs.Envelope, txRec *txs.Receipt) error {
tx, ok := txEnv.Tx.(*tx.SortitionTx)
if !ok {
return e.Error(e.ErrInvalidTxType)
}
sortitionThreshold := uint64(ctx.BC.MaximumPower())
/// Check if sortition tx belongs to next height, otherwise discard it
curBlockHeight := ctx.BC.LastBlockHeight() + 1
if tx.Height() < curBlockHeight-sortitionThreshold {
return errors.New("Invalid block height")
}
val, err := getInputValidator(ctx.Cache, tx.Validator())
if err != nil {
return err
}
/// validators should not submit sortition before the threshold
if tx.Height() < val.BondingHeight()+sortitionThreshold {
return errors.New("Invalid block height")
}
isInSet := ctx.BC.ValidatorSet().Contains(tx.Validator().Address)
if isInSet {
return errors.New("This validator is already in set")
}
/// Verify the sortition
var blockHeight = int64(tx.Height())
result, err := tmRPC.Block(&blockHeight)
if err != nil {
return err
}
blockHash := result.Block.Hash()
isValid := ctx.BC.VerifySortition(blockHash, txEnv.Signatories[0].PublicKey, tx.Index(), tx.Proof())
if !isValid {
return errors.New("Sortition transaction is invalid")
}
// Good! Adjust validator
err = adjustInputValidator(val, tx.Validator())
if err != nil {
return err
}
/// Update state cache
ctx.Cache.AddToSet(val)
return nil
}