Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/slashing #42

Draft
wants to merge 73 commits into
base: feat/scheduled-sc-execution
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
bb968c3
FEAT: Add slash.proto
mariusmihaic Oct 19, 2021
2d0ef67
FEAT: Add multipleHeaderSigningProof.proto
mariusmihaic Oct 19, 2021
211fb93
FEAT: Add multipleHeaderProposalProof.proto
mariusmihaic Oct 19, 2021
8ba35ca
FIX: Add empty line
mariusmihaic Oct 19, 2021
dd931a3
FIX: Import order
mariusmihaic Oct 19, 2021
1e3790b
FIX: Generate proto file
mariusmihaic Oct 19, 2021
aebaffe
FEAT: Remove pointer to slice
mariusmihaic Oct 20, 2021
9e288dd
FEAT: Add SetHeaders
mariusmihaic Oct 21, 2021
7b1e68d
Merge pull request #25 from ElrondNetwork/EN-10929-Create_slash_proto…
mariusmihaic Oct 21, 2021
dc2c279
FEAT: Add proof proto struct
mariusmihaic Nov 1, 2021
64178e2
FEAT: Add generated proof struct
mariusmihaic Nov 1, 2021
710e890
FEAT: Add header info proto struct
mariusmihaic Nov 1, 2021
8dd1f3e
FEAT: Add multiple sign and propose proof interfaces
mariusmihaic Nov 1, 2021
2efc821
FIX: Move proof interfaces in types package
mariusmihaic Nov 1, 2021
2a0e212
FEAT: Add header info generated proto files
mariusmihaic Nov 1, 2021
c547b25
FEAT: Add set headers, slash result, proof constructors
mariusmihaic Nov 2, 2021
af27452
FEAT: Add proof tests
mariusmihaic Nov 2, 2021
6fd6c79
FEAT: Add new header info constructor
mariusmihaic Nov 2, 2021
5241ebc
FIX: Refactor proofs to only use data heandler, remove header info
mariusmihaic Nov 3, 2021
30bedcc
FEAT: Add IsIndexSetInBitmap + tests
mariusmihaic Nov 5, 2021
400edd5
FIX: Delete proto proof files
mariusmihaic Nov 8, 2021
526cc84
FIX: Review findings
mariusmihaic Nov 12, 2021
ceda651
FEAT: Add headers in proof always in the same order
mariusmihaic Nov 15, 2021
b76390d
FEAT: Add zero threat level + fix review findings
mariusmihaic Nov 15, 2021
8b37351
FEAT: Add GetProofTxData in slashing proof
mariusmihaic Nov 16, 2021
0a7b474
FEAT: Add tests for GetProofTxData in multipleHeaderProposalProof_tes…
mariusmihaic Nov 16, 2021
127dd95
FEAT: Add tests for GetProofTxData in multipleHeaderSigningProof_test.go
mariusmihaic Nov 16, 2021
05c9a89
FEAT: Remove slashing type enum, add ProofID byte
mariusmihaic Nov 18, 2021
02150a7
FEAT: Add first ugly version
mariusmihaic Nov 18, 2021
c7fc737
FEAT: Make existing tests pass
mariusmihaic Nov 18, 2021
96c87c4
FEAT: Extend tests
mariusmihaic Nov 18, 2021
7670733
FIX: Replace magic number
mariusmihaic Nov 18, 2021
0ea4835
FIX: General refactor
mariusmihaic Nov 19, 2021
df5e313
FIX: General refactor
mariusmihaic Nov 22, 2021
774f975
Merge branch 'EN-10945-Create_proto_proof_interfaces' into EN-11141-S…
mariusmihaic Nov 22, 2021
cd321ae
FIX: General refactor pt. 2
mariusmihaic Nov 22, 2021
cfff50f
FIX: Return fmt.Errorf instead of simple error
mariusmihaic Nov 22, 2021
d8124e4
FEAT: Add initial benchmark
mariusmihaic Nov 22, 2021
1ab3131
FIX: Error sprintf
mariusmihaic Nov 22, 2021
ce1f215
Merge branch 'EN-11141-Shrink_proof_size' into EN-11151-Proof_constru…
mariusmihaic Nov 22, 2021
2923ca0
FIX: Add generator file in testscommon
mariusmihaic Nov 23, 2021
3af6d5c
FIX: Add threat level in generator
mariusmihaic Nov 23, 2021
519b307
FEAT: Add benchmark for NewMultipleProposalProof
mariusmihaic Dec 2, 2021
ec61d74
CLN: Remove ProofID
mariusmihaic Dec 2, 2021
f36ca9e
FEAT: Add GetAllHeaders()
mariusmihaic Dec 2, 2021
6eaba3d
FEAT: Add GetBitmap()
mariusmihaic Dec 3, 2021
5c6bed1
FEAT: Remove GetBitmap()
mariusmihaic Dec 6, 2021
553f9a5
FIX: Review findings
mariusmihaic Dec 6, 2021
daf2552
FIX: Merge conflicts
mariusmihaic Dec 6, 2021
85cf15a
FIX: Review findings
mariusmihaic Dec 6, 2021
bbfb7e2
FIX: Minor fix
mariusmihaic Dec 7, 2021
2afd87b
Merge branch 'EN-11141-Shrink_proof_size' into EN-11151-Proof_constru…
mariusmihaic Dec 7, 2021
d913d29
Merge branch 'EN-11151-Proof_construct_benchmark' into EN-11166-Exten…
mariusmihaic Dec 7, 2021
c43273b
FEAT: Add CalcBitmapSize
mariusmihaic Dec 7, 2021
51714ad
FIX: Interface description
mariusmihaic Dec 8, 2021
6ae6b83
FIX: Minor description
mariusmihaic Dec 8, 2021
bda6989
Merge branch 'feat/scheduled-sc-execution' into merge-scheduled-sc-in…
mariusmihaic Dec 9, 2021
8cf8ab4
Merge pull request #43 from ElrondNetwork/merge-scheduled-sc-into-sla…
mariusmihaic Dec 9, 2021
e96f550
Merge branch 'feat/slashing' into EN-10945-Create_proto_proof_interfaces
mariusmihaic Dec 9, 2021
c5f8dc6
Merge branch 'EN-10945-Create_proto_proof_interfaces' into EN-11141-S…
mariusmihaic Dec 9, 2021
7820f4b
Merge branch 'EN-11141-Shrink_proof_size' into EN-11151-Proof_constru…
mariusmihaic Dec 9, 2021
e88b9ca
Merge branch 'EN-11151-Proof_construct_benchmark' into EN-11166-Exten…
mariusmihaic Dec 9, 2021
013f63e
FIX: Review findings
mariusmihaic Dec 23, 2021
e38ac2a
Merge pull request #26 from ElrondNetwork/EN-10945-Create_proto_proof…
mariusmihaic Dec 23, 2021
14e9900
Merge branch 'EN-11141-Shrink_proof_size' into EN-11151-Proof_constru…
mariusmihaic Dec 23, 2021
2f07f8d
Merge branch 'EN-11151-Proof_construct_benchmark' into EN-11166-Exten…
mariusmihaic Dec 23, 2021
346bfb4
FIX: Review findings
mariusmihaic Jan 20, 2022
adbd4ab
Merge pull request #33 from ElrondNetwork/EN-11141-Shrink_proof_size
mariusmihaic Jan 20, 2022
e21a951
Merge pull request #34 from ElrondNetwork/EN-11151-Proof_construct_be…
AdoAdoAdo Jan 20, 2022
6f67cc2
FIX: Review findings
mariusmihaic Jan 20, 2022
84c4c06
FEAT: Add byteSize const
mariusmihaic Jan 20, 2022
79c52b5
Merge branch 'feat/slashing' into EN-11166-Extend_multiple_sign_proof…
mariusmihaic Jan 20, 2022
99ddc6e
Merge pull request #39 from ElrondNetwork/EN-11166-Extend_multiple_si…
AdoAdoAdo Jan 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions core/sliceUtil/sliceUtil.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,39 @@ func TrimSliceSliceByte(in [][]byte) [][]byte {
copy(ret, in)
return ret
}

// IsIndexSetInBitmap - checks if a bit is set(1) in the given bitmap
func IsIndexSetInBitmap(index uint32, bitmap []byte) bool {
if isIndexOutOfBounds(index, bitmap) {
return false
}

byteInMap := getByteAtIndex(index, bitmap)
mask := calcByteMask(index)
return (*byteInMap & mask) != 0
}

func SetIndexInBitmap(index uint32, bitmap []byte) {
if isIndexOutOfBounds(index, bitmap) {
return
}

byteInMap := getByteAtIndex(index, bitmap)
mask := calcByteMask(index)
*byteInMap |= mask
}

// Could panic. Do not call this unless you check before if isIndexOutOfBounds == false
func getByteAtIndex(index uint32, bitmap []byte) *byte {
bytePos := index / 8
return &bitmap[bytePos]
}

func calcByteMask(index uint32) byte {
bitPos := index % 8
return 1 << bitPos
}

func isIndexOutOfBounds(index uint32, bitmap []byte) bool {
return index >= uint32(len(bitmap))*8
}
48 changes: 48 additions & 0 deletions core/sliceUtil/sliceUtil_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package sliceUtil_test

import (
"strconv"
"testing"

"github.com/ElrondNetwork/elrond-go-core/core/sliceUtil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestTrimSliceSliceByte_EmptyInputShouldDoNothing(t *testing.T) {
Expand Down Expand Up @@ -49,3 +51,49 @@ func TestTrimSliceSliceByte_SliceAlreadyOkShouldDoNothing(t *testing.T) {
assert.Equal(t, 2, len(input))
assert.Equal(t, 2, cap(input))
}

func TestIsIndexSetInBitmap(t *testing.T) {
byte1Map, _ := strconv.ParseInt("11001101", 2, 9)
byte2Map, _ := strconv.ParseInt("00000101", 2, 9)
bitmap := []byte{byte(byte1Map), byte(byte2Map)}

//Byte 1
require.True(t, sliceUtil.IsIndexSetInBitmap(0, bitmap))
require.False(t, sliceUtil.IsIndexSetInBitmap(1, bitmap))
require.True(t, sliceUtil.IsIndexSetInBitmap(2, bitmap))
require.True(t, sliceUtil.IsIndexSetInBitmap(3, bitmap))
require.False(t, sliceUtil.IsIndexSetInBitmap(4, bitmap))
require.False(t, sliceUtil.IsIndexSetInBitmap(5, bitmap))
require.True(t, sliceUtil.IsIndexSetInBitmap(6, bitmap))
require.True(t, sliceUtil.IsIndexSetInBitmap(7, bitmap))
// Byte 2
require.True(t, sliceUtil.IsIndexSetInBitmap(8, bitmap))
require.False(t, sliceUtil.IsIndexSetInBitmap(9, bitmap))
require.True(t, sliceUtil.IsIndexSetInBitmap(10, bitmap))

for i := uint32(11); i <= 100; i++ {
require.False(t, sliceUtil.IsIndexSetInBitmap(i, bitmap))
}
}

func TestSetIndexInBitmap(t *testing.T) {
byte1Map, _ := strconv.ParseInt("11001101", 2, 9)
byte2Map, _ := strconv.ParseInt("00000101", 2, 9)
expectedBitMap := []byte{byte(byte1Map), byte(byte2Map)}

bitMap := make([]byte, 2)

sliceUtil.SetIndexInBitmap(0, bitMap)
sliceUtil.SetIndexInBitmap(2, bitMap)
sliceUtil.SetIndexInBitmap(3, bitMap)
sliceUtil.SetIndexInBitmap(6, bitMap)
sliceUtil.SetIndexInBitmap(7, bitMap)
sliceUtil.SetIndexInBitmap(8, bitMap)
sliceUtil.SetIndexInBitmap(10, bitMap)

for i := uint32(16); i <= 100; i++ {
sliceUtil.SetIndexInBitmap(i, bitMap)
}

require.Equal(t, expectedBitMap, bitMap)
}
24 changes: 24 additions & 0 deletions data/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,27 @@ var ErrScheduledRootHashNotSupported = errors.New("scheduled root hash is not su

// ErrWrongTransactionsTypeSize signals that size of transactions type buffer from mini block reserved field is wrong
var ErrWrongTransactionsTypeSize = errors.New("wrong transactions type size")

// ErrNilSlashResult signals that a nil slash result has been provided
var ErrNilSlashResult = errors.New("slash result is nil")

// ErrNilHeaderHandler signals that a nil header handler has been provided
var ErrNilHeaderHandler = errors.New("nil header handler")

// ErrEmptyHeaderInfoList signals that an empty header info list has been provided
var ErrEmptyHeaderInfoList = errors.New("empty header info list")

// ErrNilHeaderInfo signals that a nil header info has been provided
var ErrNilHeaderInfo = errors.New("nil header info")

// ErrNilHash signals that a nil hash has been provided
var ErrNilHash = errors.New("nil hash provided")

// ErrHeadersSameHash signals that headers have the same hash in a multiple header proof
var ErrHeadersSameHash = errors.New("headers have the same hash in a multiple header proof")

// ErrNotEnoughHeadersProvided signals that not enough headers have been provided for a multiple header proof
var ErrNotEnoughHeadersProvided = errors.New("not enough headers have been provided for a multiple header proof")

// ErrNotEnoughPublicKeysProvided signals that not enough public keys have been provided for a multiple header proof
var ErrNotEnoughPublicKeysProvided = errors.New("not enough public keys have been provided for a multiple header proof")
8 changes: 7 additions & 1 deletion data/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ type HeaderHandler interface {
IsInterfaceNil() bool
}

// HeaderInfoHandler defines a HeaderHandler and its corresponding hash
type HeaderInfoHandler interface {
GetHeaderHandler() HeaderHandler
GetHash() []byte
}

// ShardHeaderHandler defines getters and setters for the shard block header
type ShardHeaderHandler interface {
HeaderHandler
Expand Down Expand Up @@ -193,7 +199,7 @@ type EpochStartShardDataHandler interface {
SetPendingMiniBlockHeaders([]MiniBlockHeaderHandler) error
}

// EconomicHandler defines setters and getters for Economics
// EconomicsHandler defines setters and getters for Economics
type EconomicsHandler interface {
GetTotalSupply() *big.Int
GetTotalToDistribute() *big.Int
Expand Down
19 changes: 19 additions & 0 deletions data/mock/headerInfoStub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package mock

import "github.com/ElrondNetwork/elrond-go-core/data"

// HeaderInfoStub -
type HeaderInfoStub struct {
Header data.HeaderHandler
Hash []byte
}

// GetHeaderHandler -
func (his *HeaderInfoStub) GetHeaderHandler() data.HeaderHandler {
return his.Header
}

// GetHash -
func (his *HeaderInfoStub) GetHash() []byte {
return his.Hash
}
125 changes: 125 additions & 0 deletions data/slash/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package slash

import (
"encoding/hex"
"fmt"
"sort"

"github.com/ElrondNetwork/elrond-go-core/core/check"
"github.com/ElrondNetwork/elrond-go-core/data"
)

// MinSlashableNoOfHeaders represents the min number of headers required for a
// multiple proposal/signing proof to be considered slashable
const MinSlashableNoOfHeaders = 2

// SlashingResult contains the slashable data as well as the severity(slashing level)
// for a possible malicious validator
type SlashingResult struct {
SlashingLevel ThreatLevel
Headers []data.HeaderInfoHandler
}

// ProofTxData represents necessary data to be used in a slashing commitment proof tx by a slashing notifier.
// Each field is required to be added in a transaction.data field
type ProofTxData struct {
Round uint64
ShardID uint32
ProofID byte
}

// Used by slashing notifier to create a slashing transaction
// from a proof. Each transaction identifies a different
// slashing event based on this ID
const (
// MultipleProposalProofID = MultipleProposal's ID
MultipleProposalProofID byte = 0x1
// MultipleSigningProofID = MultipleSigning's ID
MultipleSigningProofID byte = 0x2
)

const byteSize = 8

// CalcBitmapSize returns the min required bitmap size, which
// can hold a noOfBits
func CalcBitmapSize(noOfBits int) uint32 {
bitmapSize := noOfBits / byteSize
if noOfBits%byteSize != 0 {
bitmapSize++
}
return uint32(bitmapSize)
}

func getSortedHeadersV2(headersInfo []data.HeaderInfoHandler) (*HeadersV2, error) {
sortedHeaders, err := sortHeaders(headersInfo)
if err != nil {
return nil, err
}

headersV2 := &HeadersV2{}
err = headersV2.SetHeaders(sortedHeaders)
if err != nil {
return nil, err
}

return headersV2, nil
}

func getHeaderHashIfUnique(headerInfo data.HeaderInfoHandler, hashes map[string]struct{}) (string, error) {
if headerInfo == nil {
return "", data.ErrNilHeaderInfo
}

hash := headerInfo.GetHash()
if hash == nil {
return "", data.ErrNilHash
}

headerHandler := headerInfo.GetHeaderHandler()
if check.IfNil(headerHandler) {
return "", fmt.Errorf("%w in header info for hash: %s", data.ErrNilHeaderHandler, hex.EncodeToString(hash))
}

hashStr := string(hash)
_, exists := hashes[hashStr]
if exists {
return "", fmt.Errorf("%w, duplicated hash: %s", data.ErrHeadersSameHash, hex.EncodeToString(hash))
}

return hashStr, nil
}

func sortHeaders(headersInfo []data.HeaderInfoHandler) ([]data.HeaderHandler, error) {
if len(headersInfo) == 0 {
return nil, data.ErrEmptyHeaderInfoList
}

sortHeadersByHash(headersInfo)
headers := make([]data.HeaderHandler, 0, len(headersInfo))
hashes := make(map[string]struct{})
for idx, headerInfo := range headersInfo {
hash, err := getHeaderHashIfUnique(headerInfo, hashes)
if err != nil {
return nil, fmt.Errorf("%w in sorted header list at index: %d", err, idx)
}

headers = append(headers, headerInfo.GetHeaderHandler())
hashes[hash] = struct{}{}
}

return headers, nil
}

func sortHeadersByHash(headersInfo []data.HeaderInfoHandler) {
sortFunc := func(i, j int) bool {
if headersInfo[i] == nil || headersInfo[j] == nil {
return false
}
hash1 := string(headersInfo[i].GetHash())
hash2 := string(headersInfo[j].GetHash())

return hash1 < hash2
}

sort.Slice(headersInfo, sortFunc)
}
Loading