Skip to content

Commit

Permalink
Merge branch 'main' into feat/pvm-implement-interpreter-visitor
Browse files Browse the repository at this point in the history
  • Loading branch information
danielvladco committed Oct 2, 2024
2 parents 77443a0 + 71fdb79 commit 9507287
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 258 deletions.
12 changes: 12 additions & 0 deletions internal/block/ticket.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,15 @@ type TicketProof struct {
type TicketExtrinsic struct {
TicketProofs []TicketProof
}

// TODO: Bandersnatch. This is just a mock.
func ExtractTicketFromProof(proofs []TicketProof) []Ticket {
result:= make([]Ticket, len(proofs))
for i, proof := range proofs {
result[i] = Ticket{
EntryIndex: proof.EntryIndex,
Identifier: crypto.Hash(proof.Proof[:32]),
}
}
return result
}
4 changes: 2 additions & 2 deletions internal/polkavm/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ type HostCallResult struct {
Msg string
}

type HostCallCode int
type HostCallCode uint

const (
HostCallResultNone HostCallCode = 2<<32 - 1
Expand All @@ -120,7 +120,7 @@ const (
HostCallResultOk HostCallCode = 0
)

type HostCallInnerCode int
type HostCallInnerCode uint

const (
HostCallInnerCodeHalt HostCallInnerCode = 0
Expand Down
9 changes: 2 additions & 7 deletions internal/polkavm/interpreter/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ func (e ExecutionError) Error() string {
return fmt.Sprintf("execution error: %s", e.Err)
}

//lint:ignore U1000
type callFunc func(instance *instance) error

type instance struct {
Expand All @@ -38,9 +37,8 @@ type instance struct {
}

type memory struct {
rwData []byte
stack []byte
//lint:ignore U1000
rwData []byte
stack []byte
heapSize uint32
}

Expand All @@ -53,7 +51,6 @@ func newBasicMemory(memoryMap *memoryMap, rwData []byte) *memory {
return m
}

//lint:ignore U1000
func (m *memory) getMemorySlice(program polkavm.Program, memoryMap memoryMap, address uint32, length int) ([]byte, error) {
var start uint32
var memorySlice []byte
Expand All @@ -74,7 +71,6 @@ func (m *memory) getMemorySlice(program polkavm.Program, memoryMap memoryMap, ad
return memorySlice[offset : offset+length], nil
}

//lint:ignore U1000
func (m *memory) getMemorySlicePointer(memoryMap memoryMap, address uint32, length int) (*[]byte, error) {
var start uint32
var memorySlice []byte
Expand All @@ -94,7 +90,6 @@ func (m *memory) getMemorySlicePointer(memoryMap memoryMap, address uint32, leng
return &slice, nil
}

//lint:ignore U1000
func (m *memory) sbrk(memoryMap memoryMap, size uint32) (uint32, error) {
newHeapSize := m.heapSize + size
if newHeapSize > memoryMap.maxHeapSize {
Expand Down
12 changes: 6 additions & 6 deletions internal/safrole/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func DetermineNewSealingKeys(currentTimeslot jamtime.Timeslot, ticketAccumulator
var ticketsOrKeys TicketsOrKeys
// If we don't have the correct number of tickets, proceed with the F function
if len(ticketAccumulator) != int(jamtime.TimeslotsPerEpoch) {
fallbackKeys, err := SelectFallbackKeys(epochMarker)
fallbackKeys, err := selectFallbackKeys(epochMarker)
if err != nil {
return TicketsOrKeys{}, err
}
Expand All @@ -39,7 +39,7 @@ func DetermineNewSealingKeys(currentTimeslot jamtime.Timeslot, ticketAccumulator
}
} else {
// Everything is in order, proceed with the outside-in sequencer function Z
orderedTickets := OutsideInSequence(ticketAccumulator)
orderedTickets := outsideInSequence(ticketAccumulator)
err := ticketsOrKeys.SetValue(TicketsBodies(orderedTickets))
if err != nil {
return TicketsOrKeys{}, err
Expand All @@ -48,8 +48,8 @@ func DetermineNewSealingKeys(currentTimeslot jamtime.Timeslot, ticketAccumulator
return ticketsOrKeys, nil
}

// SelectFallbackKeys selects the fallback keys for the sealing key series. Implements the F function from the graypaper
func SelectFallbackKeys(em *block.EpochMarker) (crypto.EpochKeys, error) {
// selectFallbackKeys selects the fallback keys for the sealing key series. Implements the F function from the graypaper
func selectFallbackKeys(em *block.EpochMarker) (crypto.EpochKeys, error) {
var fallbackKeys crypto.EpochKeys
serializer := serialization.NewSerializer(&codec.JAMCodec{})
for i := uint32(0); i < jamtime.TimeslotsPerEpoch; i++ {
Expand All @@ -74,8 +74,8 @@ func SelectFallbackKeys(em *block.EpochMarker) (crypto.EpochKeys, error) {
return fallbackKeys, nil
}

// OutsideInSequence implements the Z function from the graypaper
func OutsideInSequence(tickets []block.Ticket) []block.Ticket {
// outsideInSequence implements the Z function from the graypaper
func outsideInSequence(tickets []block.Ticket) []block.Ticket {
n := len(tickets)
result := make([]block.Ticket, n)
left, right := 0, n-1
Expand Down
25 changes: 16 additions & 9 deletions internal/state/block_seal.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func getWinningTicketOrKey(header *block.Header, state *State) (interface{}, err
}
}

// TODO: implement this function. This is just a mock.
// TODO: Bandersnatch implement this function. This is just a mock.
func isWinningKey(key crypto.BandersnatchSerializedPublicKey, header *block.Header, state *State) bool {
winningTicketOrKey, err := getWinningTicketOrKey(header, state)
if err != nil {
Expand Down Expand Up @@ -135,6 +135,11 @@ func createVRFSignature(header *block.Header, privateKey *bandersnatch.PrivateKe
return nil
}

// TODO: Bandersnatch Mock implementation of verifying the VRF proof
func extractVRFOutput(header block.Header) (crypto.VrfOutput, error) {
return crypto.VrfOutput{}, nil
}

// Implements equations 66 and 67
func updateEntropyAccumulator(header *block.Header, state *State, privateKey *bandersnatch.PrivateKey) error {
// Constants
Expand All @@ -153,21 +158,23 @@ func updateEntropyAccumulator(header *block.Header, state *State, privateKey *ba
}

// Equation 66: η'0 ≡ H(η0 ⌢ Y(Hv))
newEntropy := append(state.EntropyPool[0][:], vrfOutput[:]...)
state.EntropyPool[0] = crypto.Hash(newEntropy)
newEntropy := crypto.Hash(append(state.EntropyPool[0][:], vrfOutput[:]...))
entropyPool:= EntropyPool{}

// Equation 67: Rotate entropy accumulators on epoch change
if header.TimeSlotIndex.IsFirstTimeslotInEpoch() {
rotateEntropyPool(state)
entropyPool = rotateEntropyPool(state.EntropyPool)
}

entropyPool[0] = newEntropy
state.EntropyPool = entropyPool
return nil
}

func rotateEntropyPool(state *State) {
state.EntropyPool[3] = state.EntropyPool[2]
state.EntropyPool[2] = state.EntropyPool[1]
state.EntropyPool[1] = state.EntropyPool[0]
func rotateEntropyPool(pool EntropyPool) EntropyPool{
pool[3] = pool[2]
pool[2] = pool[1]
pool[1] = pool[0]
return pool
}

// Should be called after a check if the validator has are winning key.
Expand Down
11 changes: 4 additions & 7 deletions internal/state/block_seal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,8 @@ func TestRotateEntropyPool(t *testing.T) {
testutils.RandomHash(t),
testutils.RandomHash(t),
}
state := &State{
EntropyPool: initialEntropyPool,
}
rotateEntropyPool(state)
assert.Equal(t, initialEntropyPool[2], state.EntropyPool[3])
assert.Equal(t, initialEntropyPool[1], state.EntropyPool[2])
assert.Equal(t, initialEntropyPool[0], state.EntropyPool[1])
result:= rotateEntropyPool(initialEntropyPool)
assert.Equal(t, initialEntropyPool[2], result[3])
assert.Equal(t, initialEntropyPool[1], result[2])
assert.Equal(t, initialEntropyPool[0], result[1])
}
43 changes: 32 additions & 11 deletions internal/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package state

// Import necessary packages
import (
"log"

"github.com/eigerco/strawberry/internal/block"
"github.com/eigerco/strawberry/internal/jamtime"
)
Expand Down Expand Up @@ -49,30 +51,49 @@ func (s *State) UpdateState(newBlock block.Block) {
intermediateRecentBlocks := calculateIntermediateBlockState(newBlock.Header, s.RecentBlocks)
newRecentBlocks := calculateNewRecentBlocks(newBlock.Header, newBlock.Extrinsic.EG, intermediateRecentBlocks, context)

newEntropyPool := calculateNewEntropyPool(newBlock.Header, s.TimeslotIndex, s.EntropyPool)
newEntropyPool, err := calculateNewEntropyPool(newBlock.Header, s.TimeslotIndex, s.EntropyPool)
if err != nil {
// TODO handle error
log.Printf("Error calculating new Entropy pool: %v", err)
} else {
s.EntropyPool = newEntropyPool
}

newJudgements := calculateNewJudgements(newBlock.Extrinsic.ED, s.PastJudgements)

newCoreAuthorizations := calculateNewCoreAuthorizations(newBlock.Extrinsic.EG, newPendingCoreAuthorizations, s.CoreAuthorizersPool)

newValidators := calculateNewValidators(newBlock.Header, s.TimeslotIndex, s.ValidatorState.Validators, s.ValidatorState.SafroleState.NextValidators, newJudgements)

newSafroleState := calculateNewSafroleState(newBlock.Header, s.TimeslotIndex, newBlock.Extrinsic.ET, s.ValidatorState.SafroleState.NextValidators, s.ValidatorState.QueuedValidators, newEntropyPool, newValidators)

newArchivedValidators := calculateNewArchivedValidators(newBlock.Header, s.TimeslotIndex, s.ValidatorState.ArchivedValidators, s.ValidatorState.Validators)
newValidators, err := calculateNewValidators(newBlock.Header, s.TimeslotIndex, s.ValidatorState.Validators, s.ValidatorState.SafroleState.NextValidators)
if err != nil {
// TODO handle error
log.Printf("Error calculating new Validators: %v", err)
} else {
s.ValidatorState.Validators = newValidators
}

newArchivedValidators, err:= calculateNewArchivedValidators(newBlock.Header, s.TimeslotIndex, s.ValidatorState.ArchivedValidators, s.ValidatorState.Validators)
if err != nil {
// TODO handle error
log.Printf("Error calculating new Archived Validators: %v", err)
} else {
s.ValidatorState.ArchivedValidators = newArchivedValidators
}

newSafroleState, err := calculateNewSafroleState(newBlock.Header, s.TimeslotIndex, newBlock.Extrinsic.ET, s.ValidatorState.QueuedValidators)
if err != nil {
// TODO handle error
log.Printf("Error calculating new Safrole state: %v", err)
} else {
s.ValidatorState.SafroleState = newSafroleState
}

// Update the state with newSafroleState values

s.TimeslotIndex = newTimeState
s.ValidatorStatistics = newValidatorStatistics
s.RecentBlocks = newRecentBlocks
s.CoreAssignments = newCoreAssignments
s.EntropyPool = newEntropyPool
s.PastJudgements = newJudgements
s.CoreAuthorizersPool = newCoreAuthorizations
s.ValidatorState.SafroleState = newSafroleState
s.ValidatorState.ArchivedValidators = newArchivedValidators
s.ValidatorState.Validators = newValidators
s.ValidatorState.QueuedValidators = newQueuedValidators
s.Services = newServices
s.PrivilegedServices = newPrivilegedServices
Expand Down
49 changes: 41 additions & 8 deletions internal/state/transitions.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package state

import (
"errors"

"github.com/eigerco/strawberry/internal/block"
"github.com/eigerco/strawberry/internal/crypto"
"github.com/eigerco/strawberry/internal/jamtime"
"github.com/eigerco/strawberry/internal/safrole"
)
Expand Down Expand Up @@ -43,13 +46,37 @@ func calculateNewRecentBlocks(header block.Header, guarantees block.GuaranteesEx
}

// calculateNewSafroleState Equation 19: γ′ ≺ (H, τ, ET , γ, ι, η′, κ′)
func calculateNewSafroleState(header block.Header, timeslot jamtime.Timeslot, tickets block.TicketExtrinsic, nextValidators safrole.ValidatorsData, queuedValidators safrole.ValidatorsData, newEntropyPool EntropyPool, newValidators safrole.ValidatorsData) safrole.State {
return safrole.State{}
func calculateNewSafroleState(header block.Header, timeslot jamtime.Timeslot, tickets block.TicketExtrinsic, queuedValidators safrole.ValidatorsData) (safrole.State, error) {
if !header.TimeSlotIndex.IsFirstTimeslotInEpoch() {
return safrole.State{}, errors.New("not first timeslot in epoch")
}
validTickets := block.ExtractTicketFromProof(tickets.TicketProofs)
newSafrole := safrole.State{}
newNextValidators := nullifyOffenders(queuedValidators, header.OffendersMarkers)
ringCommitment := CalculateRingCommitment(newNextValidators)
newSealingKeySeries, err := safrole.DetermineNewSealingKeys(timeslot, validTickets, safrole.TicketsOrKeys{}, header.EpochMarker)
if err != nil {
return safrole.State{}, err
}
newSafrole.NextValidators = newNextValidators
newSafrole.RingCommitment = ringCommitment
newSafrole.SealingKeySeries = newSealingKeySeries
return newSafrole, nil
}

// calculateNewEntropyPool Equation 20: η′ ≺ (H, τ, η)
func calculateNewEntropyPool(header block.Header, timeslot jamtime.Timeslot, entropyPool EntropyPool) EntropyPool {
return EntropyPool{}
func calculateNewEntropyPool(header block.Header, timeslot jamtime.Timeslot, entropyPool EntropyPool) (EntropyPool, error) {
newEntropyPool := entropyPool
vrfOutput, err:= extractVRFOutput(header)
if err != nil {
return EntropyPool{}, err
}
newEntropy := crypto.Hash(append(entropyPool[0][:], vrfOutput[:]...))
if header.TimeSlotIndex.IsFirstTimeslotInEpoch() {
newEntropyPool = rotateEntropyPool(entropyPool)
}
newEntropyPool[0] = newEntropy
return newEntropyPool, nil
}

// calculateNewCoreAuthorizations Equation 29: α' ≺ (EG, φ', α)
Expand All @@ -58,8 +85,11 @@ func calculateNewCoreAuthorizations(guarantees block.GuaranteesExtrinsic, pendin
}

// calculateNewValidators Equation 21: κ′ ≺ (H, τ, κ, γ, ψ′)
func calculateNewValidators(header block.Header, timeslot jamtime.Timeslot, validators safrole.ValidatorsData, nextValidators safrole.ValidatorsData, judgements Judgements) safrole.ValidatorsData {
return safrole.ValidatorsData{}
func calculateNewValidators(header block.Header, timeslot jamtime.Timeslot, validators safrole.ValidatorsData, nextValidators safrole.ValidatorsData) (safrole.ValidatorsData, error) {
if !header.TimeSlotIndex.IsFirstTimeslotInEpoch() {
return validators, errors.New("not first timeslot in epoch")
}
return nextValidators, nil
}

// calculateNewJudgements Equation 23: ψ′ ≺ (ED, ψ)
Expand All @@ -73,8 +103,11 @@ func calculateNewCoreAssignments(guarantees block.GuaranteesExtrinsic, coreAssig
}

// calculateNewArchivedValidators Equation 22: λ′ ≺ (H, τ, λ, κ)
func calculateNewArchivedValidators(header block.Header, timeslot jamtime.Timeslot, archivedValidators safrole.ValidatorsData, validators safrole.ValidatorsData) safrole.ValidatorsData {
return safrole.ValidatorsData{}
func calculateNewArchivedValidators(header block.Header, timeslot jamtime.Timeslot, archivedValidators safrole.ValidatorsData, validators safrole.ValidatorsData) (safrole.ValidatorsData, error) {
if !header.TimeSlotIndex.IsFirstTimeslotInEpoch() {
return archivedValidators, errors.New("not first timeslot in epoch")
}
return validators, nil
}

// calculateServiceState Equation 28: δ′, 𝝌′, ι′, φ′, C ≺ (EA, ρ′, δ†, 𝝌, ι, φ)
Expand Down
Loading

0 comments on commit 9507287

Please sign in to comment.