diff --git a/beacon-chain/blockchain/head.go b/beacon-chain/blockchain/head.go index 8ff06d2f2237..390982c4b809 100644 --- a/beacon-chain/blockchain/head.go +++ b/beacon-chain/blockchain/head.go @@ -2,10 +2,9 @@ package blockchain import ( "context" + stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/gogo/protobuf/proto" "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/shared/bytesutil" "github.com/prysmaticlabs/prysm/shared/featureconfig" @@ -100,7 +99,7 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error { // Cache the new head info. s.headSlot = newHead.Block.Slot s.canonicalRoots[newHead.Block.Slot] = headRoot[:] - s.headBlock = proto.Clone(newHead).(*ethpb.SignedBeaconBlock) + s.headBlock = stateTrie.CopySignedBeaconBlock(newHead) s.headState = headState // Save the new head root to DB. diff --git a/beacon-chain/blockchain/receive_block.go b/beacon-chain/blockchain/receive_block.go index 20f20ef53366..834a5eefc10e 100644 --- a/beacon-chain/blockchain/receive_block.go +++ b/beacon-chain/blockchain/receive_block.go @@ -4,8 +4,8 @@ import ( "bytes" "context" "encoding/hex" + stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/gogo/protobuf/proto" "github.com/pkg/errors" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/go-ssz" @@ -66,7 +66,7 @@ func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlo func (s *Service) ReceiveBlockNoPubsub(ctx context.Context, block *ethpb.SignedBeaconBlock) error { ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.ReceiveBlockNoPubsub") defer span.End() - blockCopy := proto.Clone(block).(*ethpb.SignedBeaconBlock) + blockCopy := stateTrie.CopySignedBeaconBlock(block) // Apply state transition on the new block. postState, err := s.onBlock(ctx, blockCopy) @@ -130,7 +130,7 @@ func (s *Service) ReceiveBlockNoPubsub(ctx context.Context, block *ethpb.SignedB func (s *Service) ReceiveBlockNoPubsubForkchoice(ctx context.Context, block *ethpb.SignedBeaconBlock) error { ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.ReceiveBlockNoForkchoice") defer span.End() - blockCopy := proto.Clone(block).(*ethpb.SignedBeaconBlock) + blockCopy := stateTrie.CopySignedBeaconBlock(block) // Apply state transition on the new block. _, err := s.onBlock(ctx, blockCopy) @@ -183,7 +183,7 @@ func (s *Service) ReceiveBlockNoPubsubForkchoice(ctx context.Context, block *eth func (s *Service) ReceiveBlockNoVerify(ctx context.Context, block *ethpb.SignedBeaconBlock) error { ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.ReceiveBlockNoVerify") defer span.End() - blockCopy := proto.Clone(block).(*ethpb.SignedBeaconBlock) + blockCopy := stateTrie.CopySignedBeaconBlock(block) // Apply state transition on the incoming newly received blockCopy without verifying its BLS contents. if err := s.onBlockInitialSyncStateTransition(ctx, blockCopy); err != nil { diff --git a/beacon-chain/blockchain/service.go b/beacon-chain/blockchain/service.go index d58edc194ab1..e506b33a3559 100644 --- a/beacon-chain/blockchain/service.go +++ b/beacon-chain/blockchain/service.go @@ -10,7 +10,6 @@ import ( "sync" "time" - "github.com/gogo/protobuf/proto" "github.com/pkg/errors" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/go-ssz" @@ -290,7 +289,7 @@ func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock, s.canonicalRoots[b.Block.Slot] = r[:] - s.headBlock = proto.Clone(b).(*ethpb.SignedBeaconBlock) + s.headBlock = stateTrie.CopySignedBeaconBlock(b) headState, err := s.beaconDB.State(ctx, r) if err != nil { diff --git a/beacon-chain/state/getters.go b/beacon-chain/state/getters.go index b2896bb1f8f3..e235d10c49ea 100644 --- a/beacon-chain/state/getters.go +++ b/beacon-chain/state/getters.go @@ -652,30 +652,38 @@ func CopyAttestation(att *ethpb.Attestation) *ethpb.Attestation { aggBytes := []byte(att.AggregationBits) newBitlist := make([]byte, len(aggBytes)) copy(newBitlist, aggBytes) - blockRoot := [32]byte{} - var dataPtr *ethpb.AttestationData - if att.Data != nil { - dataPtr = att.Data - } else { - dataPtr = ðpb.AttestationData{} - } sig := [96]byte{} if att.Signature != nil { copy(sig[:], att.Signature) } - data := ðpb.AttestationData{ + + return ðpb.Attestation{ + AggregationBits: newBitlist, + Data: CopyAttestationData(att.Data), + Signature: sig[:], + } +} + +func CopyAttestationData(attData *ethpb.AttestationData) *ethpb.AttestationData { + var dataPtr *ethpb.AttestationData + if attData != nil { + dataPtr = attData + } else { + dataPtr = ðpb.AttestationData{} + } + blockRoot := [32]byte{} + if attData.BeaconBlockRoot != nil { + copy(blockRoot[:], attData.BeaconBlockRoot) + } + + return ðpb.AttestationData{ Slot: dataPtr.Slot, CommitteeIndex: dataPtr.CommitteeIndex, BeaconBlockRoot: blockRoot[:], Source: dataPtr.Source, Target: dataPtr.Target, } - return ðpb.Attestation{ - AggregationBits: newBitlist, - Data: data, - Signature: sig[:], - } } // CopyCheckpoint copies the provided checkpoint. @@ -684,10 +692,264 @@ func CopyCheckpoint(cp *ethpb.Checkpoint) *ethpb.Checkpoint { return ðpb.Checkpoint{} } root := [32]byte{} - copy(root[:], cp.Root) + if cp.Root != nil { + copy(root[:], cp.Root) + } return ðpb.Checkpoint{ Epoch: cp.Epoch, Root: root[:], } } + +// CopySignedBeaconBlock copies the provided SignedBeaconBlock +func CopySignedBeaconBlock(sigBlock *ethpb.SignedBeaconBlock) *ethpb.SignedBeaconBlock { + if sigBlock == nil { + return ðpb.SignedBeaconBlock{} + } + sig := [96]byte{} + if sigBlock.Signature != nil { + copy(sig[:], sigBlock.Signature) + } + return ðpb.SignedBeaconBlock{ + Block: CopyBeaconBlock(sigBlock.Block), + Signature: sig[:], + } +} + +// CopyBeaconBlock copies the provided BeaconBlock +func CopyBeaconBlock(block *ethpb.BeaconBlock) *ethpb.BeaconBlock { + if block == nil { + return ðpb.BeaconBlock{} + } + parentRoot := [32]byte{} + stateRoot := [32]byte{} + if block.ParentRoot != nil { + copy(parentRoot[:], block.ParentRoot) + } + if block.StateRoot != nil { + copy(stateRoot[:], block.StateRoot) + } + return ðpb.BeaconBlock{ + Slot: block.Slot, + ParentRoot: parentRoot[:], + StateRoot: stateRoot[:], + Body: CopyBeaconBlockBody(block.Body), + } +} + +// CopyBeaconBlockBody copies the provided BeaconBlockBody +func CopyBeaconBlockBody(body *ethpb.BeaconBlockBody) *ethpb.BeaconBlockBody { + if body == nil { + return ðpb.BeaconBlockBody{} + } + + randaoReveal := [96]byte{} + graffiti := [32]byte{} + + if body.RandaoReveal != nil { + copy(randaoReveal[:], body.RandaoReveal) + } + if body.Graffiti != nil { + copy(graffiti[:], body.Graffiti) + } + + return ðpb.BeaconBlockBody{ + RandaoReveal: randaoReveal[:], + Eth1Data: CopyETH1Data(body.Eth1Data), + Graffiti: graffiti[:], + ProposerSlashings: CopyProposerSlashings(body.ProposerSlashings), + AttesterSlashings: CopyAttesterSlashings(body.AttesterSlashings), + Attestations: CopyAttestations(body.Attestations), + Deposits: CopyDeposits(body.Deposits), + VoluntaryExits: CopySignedVoluntaryExits(body.VoluntaryExits), + } +} + +// CopyProposerSlashing copies the provided ProposerSlashing array +func CopyProposerSlashings(slashings []*ethpb.ProposerSlashing) []*ethpb.ProposerSlashing { + if slashings == nil { + return slashings + } + newSlashings := [16]*ethpb.ProposerSlashing{} + for i, att := range slashings { + newSlashings[i] = CopyProposerSlashing(att) + } + return newSlashings[:] +} + +// CopyProposerSlashing copies the provided ProposerSlashing +func CopyProposerSlashing(slashing *ethpb.ProposerSlashing) *ethpb.ProposerSlashing { + if slashing == nil { + return slashing + } + return ðpb.ProposerSlashing{ + ProposerIndex: slashing.ProposerIndex, + Header_1: CopySignedBeaconBlockHeader(slashing.Header_1), + Header_2: CopySignedBeaconBlockHeader(slashing.Header_2), + } +} + +// CopySignedBeaconBlockHeader copies the provided SignedBeaconBlockHeader +func CopySignedBeaconBlockHeader(header *ethpb.SignedBeaconBlockHeader) *ethpb.SignedBeaconBlockHeader { + if header == nil { + return header + } + sig := [96]byte{} + if header.Signature != nil { + copy(sig[:], header.Signature) + } + return ðpb.SignedBeaconBlockHeader{ + Header: CopyBeaconBlockHeader(header.Header), + Signature: sig[:], + } +} + +// CopyBeaconBlockHeader copies the provided BeaconBlockHeader +func CopyBeaconBlockHeader(header *ethpb.BeaconBlockHeader) *ethpb.BeaconBlockHeader { + if header == nil { + return header + } + parentRoot := [32]byte{} + stateRoot := [32]byte{} + bodyRoot := [32]byte{} + + if header.ParentRoot != nil { + copy(parentRoot[:], header.ParentRoot) + } + if header.StateRoot != nil { + + copy(stateRoot[:], header.StateRoot) + } + if header.BodyRoot != nil { + copy(bodyRoot[:], header.BodyRoot) + } + + return ðpb.BeaconBlockHeader{ + Slot: header.Slot, + ParentRoot: parentRoot[:], + StateRoot: stateRoot[:], + BodyRoot: bodyRoot[:], + } +} + +// CopyAttesterSlashings copies the provided AttesterSlashings array (of size 1) +func CopyAttesterSlashings(slashings []*ethpb.AttesterSlashing) []*ethpb.AttesterSlashing { + if slashings == nil { + return slashings + } + newSlashings := [1]*ethpb.AttesterSlashing{} + newSlashings[0] = ðpb.AttesterSlashing{ + Attestation_1: CopyIndexedAttestation(slashings[0].Attestation_1), + Attestation_2: CopyIndexedAttestation(slashings[0].Attestation_2), + } + return newSlashings[:] +} + +// CopyIndexedAttestation copies the provided IndexedAttestation +func CopyIndexedAttestation(indexedAtt *ethpb.IndexedAttestation) *ethpb.IndexedAttestation { + if indexedAtt == nil { + return indexedAtt + } + indices := [2048]uint64{} + if indexedAtt.AttestingIndices != nil { + copy(indices[:], indexedAtt.AttestingIndices) + } + return ðpb.IndexedAttestation{ + AttestingIndices: indices[:], + Data: CopyAttestationData(indexedAtt.Data), + Signature: nil, + } + +} + +// CopyAttestation copies the provided Attestation array +func CopyAttestations(attestations []*ethpb.Attestation) []*ethpb.Attestation { + if attestations == nil { + return attestations + } + newAttestations := [128]*ethpb.Attestation{} + for i, att := range attestations { + newAttestations[i] = CopyAttestation(att) + } + return newAttestations[:] +} + +func CopyDeposits(deposits []*ethpb.Deposit) []*ethpb.Deposit { + if deposits == nil { + return deposits + } + newDeposits := [16]*ethpb.Deposit{} + for i, dep := range deposits { + newDeposits[i] = CopyDeposit(dep) + } + return newDeposits[:] +} + +func CopyDeposit(deposit *ethpb.Deposit) *ethpb.Deposit{ + if deposit == nil { + return deposit + } + var depData *ethpb.Deposit_Data + if deposit.Data == nil { + depData = ðpb.Deposit_Data{} + } else { + pubKey := [48]byte{} + creds := [32]byte{} + sig := [96]byte{} + if deposit.Data.PublicKey != nil { + copy(pubKey[:], deposit.Data.PublicKey) + } + if deposit.Data.WithdrawalCredentials != nil { + copy(creds[:], deposit.Data.WithdrawalCredentials) + } + if deposit.Data.Signature != nil { + copy(sig[:], deposit.Data.Signature) + } + depData = ðpb.Deposit_Data{ + PublicKey: pubKey[:], + WithdrawalCredentials: creds[:], + Amount: 0, + Signature: sig[:], + } + } + + return ðpb.Deposit{ + Proof: deposit.Proof, + Data: depData, + } +} + +func CopySignedVoluntaryExits(exits []*ethpb.SignedVoluntaryExit) []*ethpb.SignedVoluntaryExit { + + if exits == nil { + return exits + } + newExits := [16]*ethpb.SignedVoluntaryExit{} + for i, exit := range exits { + newExits[i] = CopySignedVoluntaryExit(exit) + } + return newExits[:] +} +func CopySignedVoluntaryExit(exit *ethpb.SignedVoluntaryExit) *ethpb.SignedVoluntaryExit { + if exit == nil { + return nil + } + sig := [96]byte{} + copy(sig[:], exit.Signature) + + return ðpb.SignedVoluntaryExit{ + Exit: CopyVoluntaryExit(exit.Exit), + Signature: sig[:], + } +} + +func CopyVoluntaryExit(exit *ethpb.VoluntaryExit) *ethpb.VoluntaryExit { + if exit == nil { + return nil + } + return ðpb.VoluntaryExit{ + Epoch: exit.Epoch, + ValidatorIndex: exit.ValidatorIndex, + } +} diff --git a/beacon-chain/state/setters.go b/beacon-chain/state/setters.go index c0b9bada8417..a46f7dea4738 100644 --- a/beacon-chain/state/setters.go +++ b/beacon-chain/state/setters.go @@ -76,7 +76,7 @@ func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { b.lock.Lock() defer b.lock.Unlock() - b.state.LatestBlockHeader = proto.Clone(val).(*ethpb.BeaconBlockHeader) + b.state.LatestBlockHeader = CopyBeaconBlockHeader(val) b.markFieldAsDirty(latestBlockHeader) return nil }