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

Refactor Core/Types Package to Align With Spec #1021

Closed
wants to merge 51 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
904a7cc
begin major refactor starting with attestations
rauljordan Nov 24, 2018
450f986
db package full refactor
rauljordan Nov 24, 2018
98712bc
simulator full refactor done
rauljordan Nov 24, 2018
255d8a9
initial sync passes
rauljordan Nov 24, 2018
10ef557
all rpc tests passing
rauljordan Nov 24, 2018
853e891
almost done with blockchain refactor
rauljordan Nov 24, 2018
72e0bb9
need to add block validity conditions, then make blockchain tests pas…
rauljordan Nov 25, 2018
762b9a1
cleaned up validity conditions file in core
rauljordan Nov 25, 2018
65834d4
update proto
rauljordan Nov 25, 2018
f061029
yay it buildssssss
rauljordan Nov 25, 2018
ce63cfa
fix test
rauljordan Nov 25, 2018
304b715
tests pass
rauljordan Nov 25, 2018
8d17827
shuffle stream fixed
rauljordan Nov 25, 2018
0329de8
merge master
rauljordan Nov 25, 2018
0112f42
fix lint
rauljordan Nov 25, 2018
bccd4b1
readd most blockchain tests
rauljordan Nov 26, 2018
868bfec
added rest of the blockchain tests
rauljordan Nov 26, 2018
a70d822
Merge branch 'master' into single-state-refactor
rauljordan Nov 26, 2018
8dba7e5
readd pubkey
rauljordan Nov 26, 2018
7881e30
Merge branch 'single-state-refactor' of github.com:rauljordan/prysm i…
rauljordan Nov 26, 2018
55d03aa
validity conditions tests
rauljordan Nov 26, 2018
feaa34b
Merge branch 'master' into single-state-refactor
rauljordan Nov 26, 2018
1d283c0
added block tests
rauljordan Nov 26, 2018
5e8e6ca
block test
rauljordan Nov 26, 2018
e1ce8bf
Merge branch 'single-state-refactor' of github.com:rauljordan/prysm i…
rauljordan Nov 26, 2018
326f151
Merge branch 'master' into single-state-refactor
rauljordan Nov 28, 2018
1293d55
Merge branch 'master' into single-state-refactor
rauljordan Nov 28, 2018
d3d790e
gazelle add
rauljordan Nov 28, 2018
4356e62
Merge branch 'single-state-refactor' of github.com:rauljordan/prysm i…
rauljordan Nov 28, 2018
4d99331
Merge branch 'master' into single-state-refactor
rauljordan Nov 28, 2018
981a1ca
Merge branch 'master' into single-state-refactor
rauljordan Nov 28, 2018
d668940
define proto types according to spec
rauljordan Nov 28, 2018
0b1d113
fix dependency in dbcleanup
rauljordan Nov 28, 2018
275ffdb
Merge branch 'single-state-refactor' into type-fixes
rauljordan Nov 28, 2018
04bf3f0
Merge branch 'master' into single-state-refactor
rauljordan Nov 28, 2018
218f738
Merge branch 'single-state-refactor' into type-fixes
rauljordan Nov 28, 2018
643a740
types tests passing
rauljordan Nov 28, 2018
27e3e27
added more setters
rauljordan Nov 28, 2018
7d3dade
added getters for justification
rauljordan Nov 28, 2018
5884249
defined attestation record type instead with the ability to create pr…
rauljordan Nov 29, 2018
44f87e6
fix types tests and building
rauljordan Nov 29, 2018
948bd7d
add processed att proto
rauljordan Nov 29, 2018
b091e08
fix att types
rauljordan Nov 29, 2018
e99fb3f
fixes done
rauljordan Nov 29, 2018
7ed8f84
fix some review comments
rauljordan Nov 29, 2018
c4d9185
merge confs fixed
rauljordan Dec 1, 2018
f096df3
gazelle
rauljordan Dec 1, 2018
aaed96e
fixed errors
rauljordan Dec 1, 2018
27fce5d
fix att
rauljordan Dec 1, 2018
6cdf372
fix test
rauljordan Dec 1, 2018
d5aa222
core/types passing
rauljordan Dec 1, 2018
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
2 changes: 0 additions & 2 deletions beacon-chain/core/types/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ go_library(
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_golang_protobuf//proto:go_default_library",
"@com_github_golang_protobuf//ptypes:go_default_library_gen",
],
Expand All @@ -33,7 +32,6 @@ go_test(
deps = [
"//proto/beacon/p2p/v1:go_default_library",
"//shared/params:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_golang_protobuf//ptypes:go_default_library_gen",
],
)
169 changes: 98 additions & 71 deletions beacon-chain/core/types/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,73 @@ import (
"github.com/prysmaticlabs/prysm/shared/params"
)

// Attestation is the primary source of load on the beacon chain, it's used to
// AggregatedAttestation is the primary source of load on the beacon chain, it's used to
// attest to some parent block in the chain and block hash in a shard.
type Attestation struct {
type AggregatedAttestation struct {
data *pb.AggregatedAttestation
}

// NewAttestation explicitly sets the data field of a attestation.
// Return attestation with default fields if data is nil.
func NewAttestation(data *pb.AggregatedAttestation) *Attestation {
// ProcessedAttestation simply tracks slot inclusion and does not contain an aggregate
// signature value from validators.
type ProcessedAttestation struct {
data *pb.ProcessedAttestation
}

// NewAggregatedAttestation explicitly sets the data field of an
// attestation record including an aggregate BLS signature.
// This returns an attestation with default fields if data is nil.
func NewAggregatedAttestation(data *pb.AggregatedAttestation) *AggregatedAttestation {
if data == nil {
return &Attestation{
return &AggregatedAttestation{
data: &pb.AggregatedAttestation{
Slot: 0,
Shard: 0,
JustifiedSlot: 0,
JustifiedBlockHash: []byte{},
ShardBlockHash: []byte{},
AttesterBitfield: []byte{},
ObliqueParentHashes: [][]byte{{}},
AggregateSig: []uint64{},
AttesterBitfield: []byte{},
AggregateSig: []uint64{},
PocBitfield: []byte{},
SignedData: &pb.AttestationSignedData{
Slot: 0,
Shard: 0,
BlockHash: []byte{},
CycleBoundaryHash: []byte{},
LastCrosslinkHash: []byte{},
JustifiedSlot: 0,
JustifiedBlockHash: []byte{},
ShardBlockHash: []byte{},
},
},
}
}
return &AggregatedAttestation{data: data}
}

// NewProcessedAttestation creates an attestation record instance that
// does not care about aggregate signatures and just tracks the
// slot it was included.
func NewProcessedAttestation(data *pb.ProcessedAttestation) *ProcessedAttestation {
if data == nil {
return &ProcessedAttestation{
data: &pb.ProcessedAttestation{
AttesterBitfield: []byte{},
PocBitfield: []byte{},
SlotIncluded: 0,
SignedData: &pb.AttestationSignedData{
Slot: 0,
Shard: 0,
BlockHash: []byte{},
CycleBoundaryHash: []byte{},
LastCrosslinkHash: []byte{},
JustifiedSlot: 0,
JustifiedBlockHash: []byte{},
ShardBlockHash: []byte{},
},
},
}
}
return &Attestation{data: data}
return &ProcessedAttestation{data: data}
}

// AttestationMsg hashes parentHashes + shardID + slotNumber + shardBlockHash + justifiedSlot
// AttestationMsg hashes shardID + slotNumber + shardBlockHash + justifiedSlot
// into a message to use for verifying with aggregated public key and signature.
func AttestationMsg(
parentHashes [][32]byte,
blockHash []byte,
slot uint64,
shardID uint64,
Expand All @@ -49,105 +86,96 @@ func AttestationMsg(
msg := make([]byte, binary.MaxVarintLen64)
binary.BigEndian.PutUint64(msg, forkVersion)
binary.PutUvarint(msg, slot%params.BeaconConfig().CycleLength)
for _, parentHash := range parentHashes {
msg = append(msg, parentHash[:]...)
}
binary.PutUvarint(msg, shardID)
msg = append(msg, blockHash...)
binary.PutUvarint(msg, justifiedSlot)
return hashutil.Hash(msg)
}

// Proto returns the underlying protobuf data.
func (a *Attestation) Proto() *pb.AggregatedAttestation {
func (a *AggregatedAttestation) Proto() *pb.AggregatedAttestation {
return a.data
}

// Marshal encodes block object into the wire format.
func (a *Attestation) Marshal() ([]byte, error) {
func (a *AggregatedAttestation) Marshal() ([]byte, error) {
return proto.Marshal(a.data)
}

// Hash generates the blake2b hash of the attestation.
func (a *Attestation) Hash() ([32]byte, error) {
func (a *AggregatedAttestation) Hash() ([32]byte, error) {
data, err := proto.Marshal(a.data)
if err != nil {
return [32]byte{}, fmt.Errorf("could not marshal attestation proto data: %v", err)
}
return hashutil.Hash(data), nil
}

// Key generates the blake2b hash of the following attestation fields:
// slotNumber + shardID + blockHash + obliqueParentHash
// This is used for attestation table look up in localDB.
func (a *Attestation) Key() [32]byte {
key := make([]byte, binary.MaxVarintLen64)
binary.PutUvarint(key, a.SlotNumber())
binary.PutUvarint(key, a.ShardID())
key = append(key, a.ShardBlockHash()...)
for _, pHash := range a.ObliqueParentHashes() {
key = append(key, pHash[:]...)
}
return hashutil.Hash(key)
// SignedData returns the innter attestation signed data object.
func (a *AggregatedAttestation) SignedData() *pb.AttestationSignedData {
return a.data.SignedData
}

// SlotNumber of the block, which this attestation is attesting to.
func (a *Attestation) SlotNumber() uint64 {
return a.data.Slot
// Proto returns the underlying protobuf data.
func (a *ProcessedAttestation) Proto() *pb.ProcessedAttestation {
return a.data
}

// ShardID of the block, which this attestation is attesting to.
func (a *Attestation) ShardID() uint64 {
return a.data.Shard
// Marshal encodes block object into the wire format.
func (a *ProcessedAttestation) Marshal() ([]byte, error) {
return proto.Marshal(a.data)
}

// ShardBlockHash of the block, which this attestation is attesting to.
func (a *Attestation) ShardBlockHash() []byte {
return a.data.ShardBlockHash
// Hash generates the blake2b hash of the attestation.
func (a *ProcessedAttestation) Hash() ([32]byte, error) {
data, err := proto.Marshal(a.data)
if err != nil {
return [32]byte{}, fmt.Errorf("could not marshal attestation proto data: %v", err)
}
return hashutil.Hash(data), nil
}

// JustifiedSlotNumber of the attestation should be earlier than the last justified slot in crystallized state.
func (a *Attestation) JustifiedSlotNumber() uint64 {
return a.data.JustifiedSlot
// SignedData returns the inner attestation signed data object.
func (a *ProcessedAttestation) SignedData() *pb.AttestationSignedData {
return a.data.SignedData
}

// JustifiedBlockHash should be in the chain of the block being processed.
func (a *Attestation) JustifiedBlockHash() []byte {
return a.data.JustifiedBlockHash
// SlotIncluded returns the inner proto slot included field.
func (a *ProcessedAttestation) SlotIncluded() uint64 {
return a.data.SlotIncluded
}

// AttesterBitfield represents which validator in the committee has voted.
func (a *Attestation) AttesterBitfield() []byte {
return a.data.AttesterBitfield
// AttestationKey generates the blake2b hash of the following attestation fields:
// slotNumber + shardID + blockHash
// This is used for attestation table look up in localDB.
func AttestationKey(attSigned *pb.AttestationSignedData) [32]byte {
key := make([]byte, binary.MaxVarintLen64)
binary.PutUvarint(key, attSigned.GetSlot())
binary.PutUvarint(key, attSigned.GetShard())
key = append(key, attSigned.GetShardBlockHash()...)
return hashutil.Hash(key)
}

// ObliqueParentHashes represents the block hashes this attestation is not attesting for.
func (a *Attestation) ObliqueParentHashes() [][32]byte {
var obliqueParentHashes [][32]byte
for _, hash := range a.data.ObliqueParentHashes {
var h [32]byte
copy(h[:], hash)
obliqueParentHashes = append(obliqueParentHashes, h)
}
return obliqueParentHashes
// AttesterBitfield represents which validator in the committee has voted.
func (a *AggregatedAttestation) AttesterBitfield() []byte {
return a.data.AttesterBitfield
}

// AggregateSig represents the aggregated signature from all the validators attesting to this block.
func (a *Attestation) AggregateSig() []uint64 {
func (a *AggregatedAttestation) AggregateSig() []uint64 {
return a.data.AggregateSig
}

// VerifyProposerAttestation verifies the proposer's attestation of the block.
// Proposers broadcast the attestation along with the block to its peers.
func (a *Attestation) VerifyProposerAttestation(pubKey [32]byte, proposerShardID uint64) error {
func VerifyProposerAttestation(attSigned *pb.AttestationSignedData, pubKey [32]byte, proposerShardID uint64) error {
// Verify the attestation attached with block response.
// Get proposer index and shardID.
attestationMsg := AttestationMsg(
a.ObliqueParentHashes(),
a.ShardBlockHash(),
a.SlotNumber(),
attSigned.GetShardBlockHash(),
attSigned.GetSlot(),
proposerShardID,
a.JustifiedSlotNumber(),
attSigned.GetJustifiedSlot(),
params.BeaconConfig().InitialForkVersion,
)
_ = attestationMsg
Expand All @@ -158,10 +186,9 @@ func (a *Attestation) VerifyProposerAttestation(pubKey [32]byte, proposerShardID

// ContainsValidator checks if the validator is included in the attestation.
// TODO(#569): Modify method to accept a single index rather than a bitfield.
func (a *Attestation) ContainsValidator(bitfield []byte) bool {
savedAttestationBitfield := a.AttesterBitfield()
func ContainsValidator(attesterBitfield []byte, bitfield []byte) bool {
for i := 0; i < len(bitfield); i++ {
if bitfield[i]&savedAttestationBitfield[i] != 0 {
if bitfield[i]&attesterBitfield[i] != 0 {
return true
}
}
Expand Down
66 changes: 34 additions & 32 deletions beacon-chain/core/types/attestation_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package types

import (
"bytes"
"reflect"
"testing"

Expand All @@ -10,26 +9,34 @@ import (

func TestAttestation(t *testing.T) {
data := &pb.AggregatedAttestation{
Slot: 0,
Shard: 0,
JustifiedSlot: 0,
JustifiedBlockHash: []byte{0},
ShardBlockHash: []byte{0},
AttesterBitfield: []byte{0},
ObliqueParentHashes: [][]byte{{0}},
AggregateSig: []uint64{0},
SignedData: &pb.AttestationSignedData{
Slot: 0,
Shard: 0,
JustifiedSlot: 0,
JustifiedBlockHash: []byte{0},
ShardBlockHash: []byte{0},
},
AttesterBitfield: []byte{0},
AggregateSig: []uint64{0},
}
attestation := NewAttestation(data)
attestation.SlotNumber()
attestation.ShardID()
attestation.JustifiedSlotNumber()
attestation.JustifiedBlockHash()
data2 := &pb.ProcessedAttestation{
SignedData: &pb.AttestationSignedData{
Slot: 0,
Shard: 0,
JustifiedSlot: 0,
JustifiedBlockHash: []byte{0},
ShardBlockHash: []byte{0},
},
SlotIncluded: 1,
}
attestation := NewAggregatedAttestation(data)
attestation2 := NewProcessedAttestation(data2)
attestation.AttesterBitfield()
attestation.ObliqueParentHashes()
attestation.AggregateSig()
attestation.Key()
attestation.SignedData()
attestation2.SlotIncluded()

emptyAttestation := &Attestation{}
emptyAttestation := &AggregatedAttestation{}
if _, err := emptyAttestation.Marshal(); err == nil {
t.Error("marshal with empty data should fail")
}
Expand All @@ -42,33 +49,28 @@ func TestAttestation(t *testing.T) {
if !reflect.DeepEqual(attestation.data, attestation.Proto()) {
t.Errorf("inner block data did not match proto: received %v, wanted %v", attestation.Proto(), attestation.data)
}
if attestation.SlotNumber() != 0 {
t.Errorf("mismatched attestation slot number: wanted 0, received %v", attestation.SlotNumber())
}
attestationWithNilData := NewAttestation(nil)
if attestationWithNilData.ShardID() != 0 {
t.Errorf("mismatched attestation shard id: wanted 0, received %v", attestation.ShardID())
}
if !bytes.Equal(attestation.ShardBlockHash(), []byte{0}) {
t.Errorf("mismatched shard block hash")
if attestation.SignedData().GetSlot() != 0 {
t.Errorf("mismatched attestation slot number: wanted 0, received %v", attestation.SignedData().GetSlot())
}
if err := attestation.VerifyProposerAttestation([32]byte{}, 0); err != nil {
if err := VerifyProposerAttestation(attestation.SignedData(), [32]byte{}, 0); err != nil {
t.Errorf("verify attestation failed: %v", err)
}
}

func TestContainsValidator(t *testing.T) {
attestation := NewAttestation(&pb.AggregatedAttestation{
Slot: 0,
Shard: 0,
attestation := NewAggregatedAttestation(&pb.AggregatedAttestation{
SignedData: &pb.AttestationSignedData{
Slot: 0,
Shard: 0,
},
AttesterBitfield: []byte{7}, // 0000 0111
})

if !attestation.ContainsValidator([]byte{4}) {
if !ContainsValidator(attestation.AttesterBitfield(), []byte{4}) {
t.Error("Attestation should contain validator")
}

if attestation.ContainsValidator([]byte{8}) {
if ContainsValidator(attestation.AttesterBitfield(), []byte{8}) {
t.Error("Attestation should not contain validator")
}
}
Loading