Skip to content

Commit

Permalink
Merge pull request #2 from Layr-Labs/refactor-project
Browse files Browse the repository at this point in the history
Refactor project
  • Loading branch information
mooselumph authored May 31, 2023
2 parents 3a375b8 + a124cf0 commit 5636540
Show file tree
Hide file tree
Showing 36 changed files with 1,158 additions and 43 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test/resources/kzg/*
25 changes: 0 additions & 25 deletions assignment.go

This file was deleted.

184 changes: 184 additions & 0 deletions core/assignment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package core

import (
"errors"
"math/big"

"github.com/ethereum/go-ethereum/common"
)

// Assignment

type OperatorId common.Address

type OperatorIndex uint

type ChunkIndex uint

type Assignments struct {
StakeThreshold uint
NumChunks uint
Assignments []Assignment
}

type Assignment struct {
StartIndex uint
NumChunks uint
}

func (c *Assignment) GetIndices() []ChunkIndex {
indices := make([]ChunkIndex, c.NumChunks)
for ind := range indices {
indices[ind] = ChunkIndex(c.StartIndex + uint(ind))
}
return indices
}

type AssignmentCoordinator interface {
GetAssignments(state OperatorState, quorum QuorumParams) (Assignments, error)

GetOperatorAssignment(state OperatorState, quorum QuorumParams, id OperatorId) (Assignment, error)

ValidateConglomerateChunkSize(state OperatorState, headers []BlobHeader, chunkSize uint) error

GetChunkSize(state OperatorState, header BlobHeader) (uint, error)
}

// Implementation

const BIP_MULTIPLIER = 10000

var (
ErrNotFound = errors.New("not found")
)

func roundUpDivide(a, b *big.Int) *big.Int {

one := new(big.Int).SetUint64(1)
res := new(big.Int)
res.Sub(a, one)
res.Div(res, b)
res.Add(res, one)
return res

}

type BasicAssignmentCoordinator struct {
}

func getStakeThreshold(state OperatorState, quorum QuorumParams) uint {

// Get stake threshold
quorumThreshold := new(big.Int).SetUint64(uint64(quorum.QuorumThresholdBPs))
stakeThreshold := new(big.Int)
stakeThreshold.Mul(quorumThreshold, state.TotalStake.QuorumStakes[quorum.QuorumID])
stakeThreshold = roundUpDivide(stakeThreshold, new(big.Int).SetUint64(BIP_MULTIPLIER))

return uint(stakeThreshold.Uint64())
}

func (c *BasicAssignmentCoordinator) GetAssignments(state OperatorState, quorum QuorumParams) (Assignments, error) {

numOperators := len(state.Operators)
numOperatorsBig := new(big.Int).SetUint64(uint64(numOperators))

chunksByOperator := make([]uint, numOperators)

// Get NumPar
numChunks := uint(0)
totalStakes := state.TotalStake.QuorumStakes[quorum.QuorumID]
for ind, r := range state.Operators {

m := new(big.Int).Mul(numOperatorsBig, r.QuorumStakes[quorum.QuorumID])
m = roundUpDivide(m, totalStakes)

numChunks += uint(m.Uint64())
chunksByOperator[ind] = uint(m.Uint64())
}

currentIndex := uint(0)
assignments := make([]Assignment, numOperators)

headerHash := [32]byte{}

for orderedInd := range chunksByOperator {

// Find the operator that should be at index currentIndex
operatorInd := GetOperatorAtIndex(headerHash, orderedInd, numOperators)
m := chunksByOperator[operatorInd]

assignments[operatorInd] = Assignment{
StartIndex: currentIndex,
NumChunks: m,
}

currentIndex += m

}

stakeThreshold := getStakeThreshold(state, quorum)

return Assignments{
StakeThreshold: stakeThreshold,
NumChunks: numChunks,
Assignments: assignments,
}, nil

}

// Returns the operator at a given index within the reordered sequence. We reorder the sequence
// by letting the reordered_index = operator_index + headerHash.
// Thus, get get the operator at a given reordered_index, we simply reverse:
// operator_index = reordered_index - headerHash
func GetOperatorAtIndex(headerHash [32]byte, index, numOperators int) int {

indexBig := new(big.Int).SetUint64(uint64(index))
offset := new(big.Int).SetBytes(headerHash[:])

operatorIndex := new(big.Int).Sub(indexBig, offset)

operatorIndex.Mod(operatorIndex, new(big.Int).SetUint64(uint64(numOperators)))

return int(operatorIndex.Uint64())
}

func (c *BasicAssignmentCoordinator) GetOperatorAssignment(state OperatorState, quorum QuorumParams, id OperatorId) (Assignment, error) {

assignments, err := c.GetAssignments(state, quorum)
if err != nil {
return Assignment{}, err
}

operator, ok := state.OperatorMap[id]
if !ok {
return Assignment{}, ErrNotFound
}

return assignments.Assignments[operator.Index], nil
}

func (c *BasicAssignmentCoordinator) ValidateConglomerateChunkSize(state OperatorState, headers []BlobHeader, chunkSize uint) error {
return nil
}

func (c *BasicAssignmentCoordinator) GetChunkSize(state OperatorState, header BlobHeader) ([]uint, error) {

numOperators := len(state.Operators)
numOperatorsBig := new(big.Int).SetUint64(uint64(numOperators))

chunkSizes := make([]uint, len(header.Quorums))

for ind, quorum := range header.Quorums {
quorumThreshold := new(big.Int).SetUint64(uint64(quorum.QuorumThresholdBPs))
adversaryThreshold := new(big.Int).SetUint64(uint64(quorum.AdversaryThresholdBPs))

// Get NumSys
numSys := new(big.Int).Sub(quorumThreshold, adversaryThreshold)
numSys.Mul(numSys, numOperatorsBig)
numSys = roundUpDivide(numSys, new(big.Int).SetUint64(BIP_MULTIPLIER))

chunkSizes[ind] = uint(header.OrigDataSize)/uint(numSys.Uint64()) + 1
}

return chunkSizes, nil
}
6 changes: 4 additions & 2 deletions data.go → core/data.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package domain
package core

// Blob

type QuorumParams struct {
QuorumID uint8
QuorumID uint8
AdversaryThresholdBPs uint16
QuorumThresholdBPs uint16
}

type Blob struct {
Expand Down
2 changes: 1 addition & 1 deletion encoding.go → core/encoding.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package domain
package core

// Encoding

Expand Down
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions core/indexer/state.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package indexer

type ChainData struct {
}
13 changes: 13 additions & 0 deletions core/mock/state.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package mock

import (
"github.com/Layr-Labs/eigenda/core"
)

type ChainDataMock struct {
}

func (m *ChainDataMock) GetOperatorState(blockNumber uint) (core.OperatorState, error) {

return core.OperatorState{}, nil
}
6 changes: 3 additions & 3 deletions state.go → core/state.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package domain
package core

import (
"math/big"
Expand Down Expand Up @@ -39,8 +39,8 @@ type TotalOperator struct {
}

type OperatorState struct {
Registrants []*OperatorView
RegistrantMap map[common.Address]*OperatorView
Operators []*OperatorView
OperatorMap map[OperatorId]*OperatorView
BlockNumber uint32
TotalStake *TotalStake
TotalOperator *TotalOperator
Expand Down
6 changes: 3 additions & 3 deletions disperser/disperser.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package disperser

import (
da "github.com/Layr-Labs/eigenda"
"github.com/Layr-Labs/eigenda/core"
)

type Server interface {
//GRPC method to accept blob request
}

type Batcher interface {
AddBlob(da.Blob)
AddBlob(core.Blob)
}

type Disperser interface {
DisperseBatch(da.Batch) error
DisperseBatch(core.Batch) error
}

type DispersalClient interface {
Expand Down
27 changes: 27 additions & 0 deletions docs/contributing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@


# Organization

The EigenDA repo is organized as a monorepo, with each project adhering to the "Ben Johnson" project structure style. Within the core project directories (e.g., `core`, `disperser`, `node`, `retriever`, `indexer`), the main interfaces and data types are defined at the root of the project, while implementations are organized by dependency. For instance, the folder `indexer/inmem` contains implementations of the interfaces in `indexer` which use in-memory storage, while `indexer/leveldb` may contain implementations of the same interfaces that use `leveldb`. Mocks of all interfaces in the `indexer` project go in `indexer/mock`.

The same pattern is used for intra-project and inter-project dependencies. For instance, the folder `indexer/indexer` contains implementations of the interfaces in `core` which depend on the `indexer` project.

In general, the `core` project contains implementation all of the important business logic responsible for the security guarantees of the EigenDA protocol, while the other projects add the networking layers needed to run the distributed system.


# Directory structure
<pre>
┌── <a href="./api">api</a> Protobuf definitions and contract bindings
├── <a href="./contracts">contracts</a>
| ├── <a href="./contracts/eignlayer-contracts">eigenlayer-contracts</a>: Contracts for the EigenLayer restaking platform
┌── <a href="./core">core</a>: Core logic of the EigenDA protocol
├── <a href="./disperser">disperser</a>: Disperser service
├── <a href="./docs">docs</a>: Documentation and specification
── <a href="./indexer">indexer</a>: A simple indexer for efficently tracking chain state and maintaining accumulators
├── <a href="./node">node</a>: DA node service
├── <a href="./pkg">pkg</a>
| ├── <a href="./pkg/encoding">encoding</a>: Core encoding/decoding functionality and multiproof generation
| └── <a href="./pkg/kzg">kzg</a>: kzg libraries
├── <a href="./retriever">retriever</a>: Retriever service
├── <a href="./test">test</a>: Tools for running integration tests
</pre>
1 change: 1 addition & 0 deletions docs/spec/contracts-registry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# BLS Registry
Loading

0 comments on commit 5636540

Please sign in to comment.