Skip to content

Commit

Permalink
feat: new changes
Browse files Browse the repository at this point in the history
  • Loading branch information
goran-ethernal committed Sep 17, 2024
1 parent 770de58 commit 6db72b4
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 21 deletions.
31 changes: 26 additions & 5 deletions agglayer/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)

type LeafType uint8

func (l LeafType) Uint8() uint8 {
return uint8(l)
}

const (
LeafTypeAsset LeafType = 0
LeafTypeMessage LeafType = 1
)

// Certificate is the data structure that will be sent to the aggLayer
type Certificate struct {
NetworkID uint32 `json:"network_id"`
Expand All @@ -35,8 +46,7 @@ func (c *Certificate) Hash() common.Hash {
// SignedCertificate is the struct that contains the certificate and the signature of the signer
type SignedCertificate struct {
*Certificate
Signature []byte `json:"signature"`
Signer common.Address `json:"signer"`
Signature []byte `json:"signature"`
}

// TokenInfo encapsulates the information to uniquely identify a token on the origin network.
Expand All @@ -45,9 +55,16 @@ type TokenInfo struct {
OriginTokenAddress common.Address `json:"origin_token_address"`
}

// GlobalIndex represents the global index of an imported bridge exit
type GlobalIndex struct {
MainnetFlag bool `json:"mainnet_flag"`
RollupIndex uint32 `json:"rollup_index"`
LeafIndex uint32 `json:"leaf_index"`
}

// BridgeExit represents a token bridge exit
type BridgeExit struct {
LeafType uint8 `json:"leaf_type"`
LeafType LeafType `json:"leaf_type"`
TokenInfo *TokenInfo `json:"token_info"`
DestinationNetwork uint32 `json:"destination_network"`
DestinationAddress common.Address `json:"destination_address"`
Expand All @@ -57,8 +74,12 @@ type BridgeExit struct {

// Hash returns a hash that uniquely identifies the bridge exit
func (c *BridgeExit) Hash() common.Hash {
if c.Amount == nil {
c.Amount = big.NewInt(0)
}

return crypto.Keccak256Hash(
cdkcommon.Uint8ToBytes(c.LeafType),
[]byte{c.LeafType.Uint8()},
cdkcommon.Uint32ToBytes(c.TokenInfo.OriginNetwork),
c.TokenInfo.OriginTokenAddress.Bytes(),
cdkcommon.Uint32ToBytes(c.DestinationNetwork),
Expand All @@ -74,7 +95,7 @@ type ImportedBridgeExit struct {
ImportedLocalExitRoot common.Hash `json:"imported_local_exit_root"`
InclusionProof [types.DefaultHeight]common.Hash `json:"inclusion_proof"`
InclusionProofRER [types.DefaultHeight]common.Hash `json:"inclusion_proof_rer"`
GlobalIndex *big.Int `json:"global_index"`
GlobalIndex *GlobalIndex `json:"global_index"`
}

// Hash returns a hash that uniquely identifies the imported bridge exit
Expand Down
31 changes: 24 additions & 7 deletions aggsender/aggsender.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,11 @@ func (a *AggSender) buildCertificate(ctx context.Context,
}

for _, claim := range claims {
importedBridgeExit := convertClaimToImportedBridgeExit(claim)
importedBridgeExit, err := convertClaimToImportedBridgeExit(claim)
if err != nil {
return nil, fmt.Errorf("error converting claim to imported bridge exit: %w", err)
}

importedBridgeExits = append(importedBridgeExits, importedBridgeExit)
}

Expand All @@ -136,7 +140,7 @@ func (a *AggSender) buildCertificate(ctx context.Context,

func convertBridgeToBridgeExit(bridge bridgesync.Bridge) *agglayer.BridgeExit {
return &agglayer.BridgeExit{
LeafType: bridge.LeafType,
LeafType: agglayer.LeafType(bridge.LeafType),
TokenInfo: &agglayer.TokenInfo{
OriginNetwork: bridge.OriginNetwork,
OriginTokenAddress: bridge.OriginAddress,
Expand All @@ -148,9 +152,14 @@ func convertBridgeToBridgeExit(bridge bridgesync.Bridge) *agglayer.BridgeExit {
}
}

func convertClaimToImportedBridgeExit(claim bridgesync.Claim) *agglayer.ImportedBridgeExit {
func convertClaimToImportedBridgeExit(claim bridgesync.Claim) (*agglayer.ImportedBridgeExit, error) {
leafType := agglayer.LeafTypeAsset
if claim.IsMessage {
leafType = agglayer.LeafTypeMessage
}

bridgeExit := &agglayer.BridgeExit{
// LeafType: claim.LeafType, TODO
LeafType: leafType,
TokenInfo: &agglayer.TokenInfo{
OriginNetwork: claim.OriginNetwork,
OriginTokenAddress: claim.OriginAddress,
Expand All @@ -161,13 +170,22 @@ func convertClaimToImportedBridgeExit(claim bridgesync.Claim) *agglayer.Imported
Metadata: claim.Metadata,
}

mainnetFlag, rollupIndex, leafIndex, err := bridgesync.DecodeGlobalIndex(claim.GlobalIndex)
if err != nil {
return nil, fmt.Errorf("error decoding global index: %w", err)
}

return &agglayer.ImportedBridgeExit{
BridgeExit: bridgeExit,
ImportedLocalExitRoot: tree.CalculateRoot(bridgeExit.Hash(), claim.ProofLocalExitRoot, uint32(claim.GlobalIndex.Uint64())),
InclusionProof: claim.ProofLocalExitRoot,
InclusionProofRER: claim.ProofRollupExitRoot,
GlobalIndex: claim.GlobalIndex,
}
GlobalIndex: &agglayer.GlobalIndex{
MainnetFlag: mainnetFlag,
RollupIndex: rollupIndex,
LeafIndex: leafIndex,
},
}, nil
}

// sendCertificatesForNetwork sends certificates for a network
Expand Down Expand Up @@ -286,6 +304,5 @@ func (a *AggSender) signCertificate(certificate *agglayer.Certificate) (*agglaye
return &agglayer.SignedCertificate{
Certificate: certificate,
Signature: sig,
Signer: crypto.PubkeyToAddress(a.sequencerKey.PublicKey),
}, nil
}
53 changes: 51 additions & 2 deletions bridgesync/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
_ "modernc.org/sqlite"
)

const globalIndexSize = 4

var (
// ErrBlockNotProcessed indicates that the given block(s) have not been processed yet.
ErrBlockNotProcessed = errors.New("given block(s) have not been processed yet")
Expand Down Expand Up @@ -301,7 +303,7 @@ func (p *processor) ProcessBlock(ctx context.Context, block sync.Block) error {
func GenerateGlobalIndex(mainnetFlag bool, rollupIndex uint32, localExitRootIndex uint32) *big.Int {
var (
globalIndexBytes []byte
buf [4]byte
buf [globalIndexSize]byte
)
if mainnetFlag {
globalIndexBytes = append(globalIndexBytes, big.NewInt(1).Bytes()...)
Expand All @@ -314,5 +316,52 @@ func GenerateGlobalIndex(mainnetFlag bool, rollupIndex uint32, localExitRootInde
leri := big.NewInt(0).SetUint64(uint64(localExitRootIndex)).FillBytes(buf[:])
globalIndexBytes = append(globalIndexBytes, leri...)

return big.NewInt(0).SetBytes(globalIndexBytes)
result := big.NewInt(0).SetBytes(globalIndexBytes)

return result
}

// Decodes global index to its three parts:
// 1. mainnetFlag - first byte
// 2. rollupIndex - next 4 bytes
// 3. localExitRootIndex - last 4 bytes
// NOTE - mainnet flag is not in the global index bytes if it is false
// NOTE - rollup index is 0 if mainnet flag is true
// NOTE - rollup index is not in the global index bytes if mainnet flag is false and rollup index is 0
func DecodeGlobalIndex(globalIndex *big.Int) (mainnetFlag bool, rollupIndex uint32, localExitRootIndex uint32, err error) {
globalIndexBytes := globalIndex.Bytes()
l := len(globalIndexBytes)

if l > 9 {

Check failure on line 335 in bridgesync/processor.go

View workflow job for this annotation

GitHub Actions / lint

Magic number: 9, in <condition> detected (mnd)
return false, 0, 0, errors.New("invalid global index length")
}

if l == 0 {
// false, 0, 0
return
}

if l == 9 {

Check failure on line 344 in bridgesync/processor.go

View workflow job for this annotation

GitHub Actions / lint

Magic number: 9, in <condition> detected (mnd)
// true, rollupIndex, localExitRootIndex
mainnetFlag = true
}

localExitRootFromIdx := l - globalIndexSize
if localExitRootFromIdx < 0 {
localExitRootFromIdx = 0
}

rollupIndexFromIdx := localExitRootFromIdx - globalIndexSize
if rollupIndexFromIdx < 0 {
rollupIndexFromIdx = 0
}

rollupIndex = convertBytesToUint32(globalIndexBytes[rollupIndexFromIdx:localExitRootFromIdx])
localExitRootIndex = convertBytesToUint32(globalIndexBytes[localExitRootFromIdx:])

return
}

func convertBytesToUint32(bytes []byte) uint32 {
return uint32(big.NewInt(0).SetBytes(bytes).Uint64())
}
85 changes: 85 additions & 0 deletions bridgesync/processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package bridgesync
import (
"context"
"encoding/json"
"errors"
"fmt"
"math/big"
"os"
Expand Down Expand Up @@ -582,3 +583,87 @@ func TestHashBridge(t *testing.T) {
})
}
}

func TestDecodeGlobalIndex(t *testing.T) {

Check failure on line 587 in bridgesync/processor_test.go

View workflow job for this annotation

GitHub Actions / lint

TestDecodeGlobalIndex's subtests should call t.Parallel (tparallel)
t.Parallel()

tests := []struct {
name string
globalIndex *big.Int
expectedMainnetFlag bool
expectedRollupIndex uint32
expectedLocalIndex uint32
expectedErr error
}{
{
name: "Mainnet flag true, rollup index 0",
globalIndex: GenerateGlobalIndex(true, 0, 2),
expectedMainnetFlag: true,
expectedRollupIndex: 0,
expectedLocalIndex: 2,
expectedErr: nil,
},
{
name: "Mainnet flag true, indexes 0",
globalIndex: GenerateGlobalIndex(true, 0, 0),
expectedMainnetFlag: true,
expectedRollupIndex: 0,
expectedLocalIndex: 0,
expectedErr: nil,
},
{
name: "Mainnet flag false, rollup index 0",
globalIndex: GenerateGlobalIndex(false, 0, 2),
expectedMainnetFlag: false,
expectedRollupIndex: 0,
expectedLocalIndex: 2,
expectedErr: nil,
},
{
name: "Mainnet flag false, rollup index non-zero",
globalIndex: GenerateGlobalIndex(false, 11, 0),
expectedMainnetFlag: false,
expectedRollupIndex: 11,
expectedLocalIndex: 0,
expectedErr: nil,
},
{
name: "Mainnet flag false, indexes 0",
globalIndex: GenerateGlobalIndex(false, 0, 0),
expectedMainnetFlag: false,
expectedRollupIndex: 0,
expectedLocalIndex: 0,
expectedErr: nil,
},
{
name: "Mainnet flag false, indexes non zero",
globalIndex: GenerateGlobalIndex(false, 1231, 111234),
expectedMainnetFlag: false,
expectedRollupIndex: 1231,
expectedLocalIndex: 111234,
expectedErr: nil,
},
{
name: "Invalid global index length",
globalIndex: big.NewInt(0).SetBytes([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}),
expectedMainnetFlag: false,
expectedRollupIndex: 0,
expectedLocalIndex: 0,
expectedErr: errors.New("invalid global index length"),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mainnetFlag, rollupIndex, localExitRootIndex, err := DecodeGlobalIndex(tt.globalIndex)
if tt.expectedErr != nil {
require.EqualError(t, err, tt.expectedErr.Error())
} else {
require.NoError(t, err)
}
require.Equal(t, tt.expectedMainnetFlag, mainnetFlag)
require.Equal(t, tt.expectedRollupIndex, rollupIndex)
require.Equal(t, tt.expectedLocalIndex, localExitRootIndex)
})
}
}
7 changes: 0 additions & 7 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,6 @@ func Uint32ToBytes(num uint32) []byte {
return key
}

// Uint8ToBytes converts a uint8 to a byte slice
func Uint8ToBytes(num uint8) []byte {
key := make([]byte, 1)
key[0] = num
return key
}

// BytesToUint32 converts a byte slice to a uint32
func BytesToUint32(bytes []byte) uint32 {
return binary.BigEndian.Uint32(bytes)
Expand Down

0 comments on commit 6db72b4

Please sign in to comment.