Skip to content

Commit

Permalink
Merge pull request #93 from ElrondNetwork/feat/websocket-outport-driver
Browse files Browse the repository at this point in the history
`feat/websocket outport driver`
  • Loading branch information
miiu96 authored Nov 11, 2022
2 parents 540b231 + ec3eef6 commit 7715eef
Show file tree
Hide file tree
Showing 46 changed files with 3,262 additions and 85 deletions.
17 changes: 17 additions & 0 deletions core/computers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (
"strconv"
"strings"
"time"

"github.com/ElrondNetwork/elrond-go-core/core/check"
"github.com/ElrondNetwork/elrond-go-core/data"
)

// MaxInt32 returns the maximum of two given numbers
Expand Down Expand Up @@ -182,3 +185,17 @@ func IsValidESDTRole(role string) bool {
return false
}
}

// GetHeaderType will return the type of the provided header
func GetHeaderType(header data.HeaderHandler) HeaderType {
switch {
case check.IfNil(header):
return ""
case header.GetShardID() == MetachainShardId:
return MetaHeader
case check.IfNil(header.GetAdditionalData()):
return ShardHeaderV1
default:
return ShardHeaderV2
}
}
15 changes: 15 additions & 0 deletions core/computers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"time"

"github.com/ElrondNetwork/elrond-go-core/core"
dataCore "github.com/ElrondNetwork/elrond-go-core/data"
"github.com/ElrondNetwork/elrond-go-core/data/block"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -502,3 +504,16 @@ func TestIsValidESDTRole(t *testing.T) {
require.Equal(t, tt.output, core.IsValidESDTRole(tt.input))
}
}

func TestGetHeaderType(t *testing.T) {
t.Parallel()

require.Equal(t, core.HeaderType(""), core.GetHeaderType(nil))

var nilHeader dataCore.HeaderHandler
require.Equal(t, core.HeaderType(""), core.GetHeaderType(nilHeader))

require.Equal(t, core.MetaHeader, core.GetHeaderType(&block.MetaBlock{}))
require.Equal(t, core.ShardHeaderV1, core.GetHeaderType(&block.Header{}))
require.Equal(t, core.ShardHeaderV2, core.GetHeaderType(&block.HeaderV2{}))
}
24 changes: 24 additions & 0 deletions core/constants.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
package core

// HeaderType defines the type to be used for the header that is sent
type HeaderType string

const (
// MetaHeader defines the type of *block.MetaBlock
MetaHeader HeaderType = "MetaBlock"
// ShardHeaderV1 defines the type of *block.Header
ShardHeaderV1 HeaderType = "Header"
// ShardHeaderV2 defines the type of *block.HeaderV2
ShardHeaderV2 HeaderType = "HeaderV2"
)

// NodeType represents the node's role in the network
type NodeType string

Expand Down Expand Up @@ -230,3 +242,15 @@ const SCDeployIdentifier = "SCDeploy"

// SCUpgradeIdentifier is the identifier for a smart contract upgrade
const SCUpgradeIdentifier = "SCUpgrade"

// WriteLogIdentifier is the identifier for the information log that is generated by a smart contract call/esdt transfer
const WriteLogIdentifier = "writeLog"

// SignalErrorOperation is the identifier for the log that is generated when a smart contract is executed but return an error
const SignalErrorOperation = "signalError"

// CompletedTxEventIdentifier is the identifier for the log that is generated when the execution of a smart contract call is done
const CompletedTxEventIdentifier = "completedTxEvent"

// GasRefundForRelayerMessage is the return message for to the smart contract result with refund for the relayer
const GasRefundForRelayerMessage = "gas refund for relayer"
9 changes: 9 additions & 0 deletions core/sharding/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package sharding

import "errors"

// ErrInvalidNumberOfShards signals that an invalid number of shards was passed to the sharding registry
var ErrInvalidNumberOfShards = errors.New("the number of shards must be greater than zero")

// ErrInvalidShardId signals that an invalid shard is was passed
var ErrInvalidShardId = errors.New("shard id must be smaller than the total number of shards")
134 changes: 134 additions & 0 deletions core/sharding/multiShardCoordinator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package sharding

import (
"bytes"
"math"

"github.com/ElrondNetwork/elrond-go-core/core"
)

// multiShardCoordinator struct defines the functionality for handling transaction dispatching to
// the corresponding shards. The number of shards is currently passed as a constructor
// parameter and later it should be calculated by this structure
type multiShardCoordinator struct {
maskHigh uint32
maskLow uint32
selfId uint32
numberOfShards uint32
}

// NewMultiShardCoordinator returns a new multiShardCoordinator and initializes the masks
func NewMultiShardCoordinator(numberOfShards, selfId uint32) (*multiShardCoordinator, error) {
if numberOfShards < 1 {
return nil, ErrInvalidNumberOfShards
}
if selfId >= numberOfShards && selfId != core.MetachainShardId {
return nil, ErrInvalidShardId
}

sr := &multiShardCoordinator{}
sr.selfId = selfId
sr.numberOfShards = numberOfShards
sr.maskHigh, sr.maskLow = calculateMasks(numberOfShards)

return sr, nil
}

// calculateMasks will create two numbers who's binary form is composed from as many
// ones needed to be taken into consideration for the shard assignment. The result
// of a bitwise AND operation of an address with this mask will result in the
// shard id where a transaction from that address will be dispatched
func calculateMasks(numOfShards uint32) (uint32, uint32) {
n := math.Ceil(math.Log2(float64(numOfShards)))
return (1 << uint(n)) - 1, (1 << uint(n-1)) - 1
}

// ComputeId calculates the shard for a given address container
func (msc *multiShardCoordinator) ComputeId(address []byte) uint32 {
return msc.ComputeIdFromBytes(address)
}

// ComputeShardID will compute shard id of the given address based on the number of shards parameter
func ComputeShardID(address []byte, numberOfShards uint32) uint32 {
maskHigh, maskLow := calculateMasks(numberOfShards)

return computeIdBasedOfNrOfShardAndMasks(address, numberOfShards, maskHigh, maskLow)
}

// ComputeIdFromBytes calculates the shard for a given address
func (msc *multiShardCoordinator) ComputeIdFromBytes(address []byte) uint32 {
if core.IsEmptyAddress(address) {
return msc.selfId
}

return computeIdBasedOfNrOfShardAndMasks(address, msc.numberOfShards, msc.maskHigh, msc.maskLow)
}

func computeIdBasedOfNrOfShardAndMasks(address []byte, numberOfShards, maskHigh, maskLow uint32) uint32 {
var bytesNeed int
if numberOfShards <= 256 {
bytesNeed = 1
} else if numberOfShards <= 65536 {
bytesNeed = 2
} else if numberOfShards <= 16777216 {
bytesNeed = 3
} else {
bytesNeed = 4
}

startingIndex := 0
if len(address) > bytesNeed {
startingIndex = len(address) - bytesNeed
}

buffNeeded := address[startingIndex:]
if core.IsSmartContractOnMetachain(buffNeeded, address) {
return core.MetachainShardId
}

addr := uint32(0)
for i := 0; i < len(buffNeeded); i++ {
addr = addr<<8 + uint32(buffNeeded[i])
}

shard := addr & maskHigh
if shard > numberOfShards-1 {
shard = addr & maskLow
}

return shard
}

// NumberOfShards returns the number of shards
func (msc *multiShardCoordinator) NumberOfShards() uint32 {
return msc.numberOfShards
}

// SelfId gets the shard id of the current node
func (msc *multiShardCoordinator) SelfId() uint32 {
return msc.selfId
}

// SameShard returns weather two addresses belong to the same shard
func (msc *multiShardCoordinator) SameShard(firstAddress, secondAddress []byte) bool {
if core.IsEmptyAddress(firstAddress) || core.IsEmptyAddress(secondAddress) {
return true
}

if bytes.Equal(firstAddress, secondAddress) {
return true
}

return msc.ComputeId(firstAddress) == msc.ComputeId(secondAddress)
}

// CommunicationIdentifier returns the identifier between current shard ID and destination shard ID
// identifier is generated such as the first shard from identifier is always smaller or equal than the last
func (msc *multiShardCoordinator) CommunicationIdentifier(destShardID uint32) string {
return core.CommunicationIdentifierBetweenShards(msc.selfId, destShardID)
}

// IsInterfaceNil returns true if there is no value under the interface
func (msc *multiShardCoordinator) IsInterfaceNil() bool {
return msc == nil
}
Loading

0 comments on commit 7715eef

Please sign in to comment.