From b8c3db3a3783822686f74a752b9f154c8aa0be55 Mon Sep 17 00:00:00 2001 From: "Ching-Hua (Vivian) Lin" <jkrvivian@gmail.com> Date: Mon, 21 Sep 2020 13:45:57 +0800 Subject: [PATCH] refactor: Remove binary/messagelayer and replace with tangle package (#740) * refactor: Move messagelayer/message to tangle/ * refactor: Modify the method receiver and annotate the error messages * refactor: Move messagelayer/payload to tangle/ * refactor: Modify the method receiver and annotate err messages in payload * refactor: Move messagelayer/messagerequester to tangle/ * refactor: Modify the method receiver in requester * refactor: Move messageparser/builtinfilter to tangle/ * refactor: Move messageparser/ to tangle/ * fix: Import fmt and minor fixes * refactor: Move messagefactory/ to tangle/ * refactor: Move tipselector/ to tangle/ * refactor: Rename method receivers in tipselector * refactor: Move messagelayer/tangle to tangle/ * refactor: Rename method receivers and annotate error messages in tangle * refactor: Move messagelayer/test to tangle/ * fix: Update to the develop branch * refactor: Create data payload in testing message creation * refactor: Use tangle package in gossip * fix: Fix :dog: * fix: Rename for consistency * fix: Move message related const from payload.go to message.go * refactor: Use single character for method receivers * fix: Fix the unit test by using the correct variable name * refactor: Use tangle package in spammer * refactor: Use tangle package in faucet * refactor: Use tangle package in networkdelay * refactor: Use tangle package in valuetransfer * refactor: Use tangle package in messagelayer plugin * refactor: Use tangle package in gossip plugin * refactor: Use tangle package in syncbeacon plugin * refactor: Use tangle package in syncbeaconfollower plugin * refactor: Use tangle package in webapi plugin * refactor: Use tangle package in issuer plugin * refactor: Use tangle package in pow plugin * refactor: Use tangle package in metrics plugin * refactor: Use tangle package in drng plugin * refactor: Use tangle package in prometheus plugin * refactor: Use tangle package in dashboard plugin * refactor: Use tangle package in integration tests * fix: Fix unit tests * refactor: Remove binary/messaglayer * Feat: merged marshal changes * Feat: removed superfluous test * Fix: fixed wrong comment * refactor: Annotate error messages in marshal functions * refactor: Import fmt package * refactor: Aggregate all filters into filter.go * refactor: Rename Factory to MessageFactory to clarify the functionality * refactor: Rename Parser to MessageParser to clarify the functionality * refactor: Rename Requester to MessageRequester to clarify the functionality * refactor: Rename Parse to FromMarshalUtil for naming consistency * refactor: Fix comments * refactor: Fix comments * fix: Use the correct function Co-authored-by: Hans Moog <hm@mkjc.net> --- dapps/faucet/dapp.go | 5 +- dapps/faucet/packages/faucet.go | 8 +- dapps/faucet/packages/faucet_test.go | 17 +- dapps/faucet/packages/payload/payload.go | 33 +- dapps/faucet/packages/payload/payload_test.go | 8 +- dapps/networkdelay/dapp.go | 4 +- dapps/networkdelay/object.go | 8 +- dapps/valuetransfers/dapp.go | 34 +- .../packages/payload/payload.go | 106 ++--- .../packages/payload/payload_test.go | 8 +- .../packages/tangle/payloadapprover.go | 4 +- .../packages/tangle/signature_filter.go | 19 +- .../packages/tangle/signature_filter_test.go | 28 +- packages/binary/drng/payload/payload.go | 8 +- .../collectivebeacon/payload/payload.go | 50 +-- packages/binary/messagelayer/message/id.go | 86 ---- .../binary/messagelayer/message/message.go | 342 ---------------- .../messagelayer/messagefactory/events.go | 26 -- .../messagefactory/messagefactory.go | 155 -------- .../messagefactory/messagefactory_test.go | 163 -------- .../message_signature_filter.go | 64 --- .../builtinfilters/pow_filter.go | 99 ----- .../builtinfilters/pow_filter_test.go | 73 ---- .../recently_seen_bytes_filter.go | 67 ---- .../messageparser/bytes_filter.go | 16 - .../messagelayer/messageparser/events.go | 55 --- .../messageparser/message_filter.go | 18 - .../messageparser/message_parser.go | 129 ------ .../messageparser/message_parser_test.go | 55 --- .../messagerequester/constants.go | 10 - .../messagelayer/messagerequester/events.go | 39 -- .../messagerequester/messagerequester.go | 104 ----- .../messagelayer/messagerequester/options.go | 32 -- packages/binary/messagelayer/payload/data.go | 90 ----- packages/binary/messagelayer/payload/id.go | 19 - .../binary/messagelayer/payload/payload.go | 97 ----- packages/binary/messagelayer/payload/type.go | 4 - .../messagelayer/payload/type_register.go | 58 --- .../binary/messagelayer/tangle/approver.go | 147 ------- packages/binary/messagelayer/tangle/events.go | 57 --- .../messagelayer/tangle/messagemetadata.go | 177 --------- .../messagelayer/tangle/missingmessage.go | 93 ----- .../messagelayer/tangle/storageprefixes.go | 12 - packages/binary/messagelayer/tangle/tangle.go | 375 ------------------ .../binary/messagelayer/tangle/tangle_test.go | 240 ----------- .../messagelayer/test/data_payload_test.go | 79 ---- .../binary/messagelayer/test/message_test.go | 57 --- .../messagelayer/test/retrievealltips_test.go | 48 --- .../binary/messagelayer/tipselector/events.go | 26 -- .../messagelayer/tipselector/tipselector.go | 81 ---- .../tipselector/tipselector_test.go | 56 --- packages/binary/spammer/spammer.go | 7 +- packages/gossip/manager.go | 6 +- packages/gossip/manager_test.go | 6 +- packages/tangle/message_test.go | 3 +- packages/tangle/payload_test.go | 5 +- packages/tangle/tangle.go | 3 + plugins/dashboard/explorer_routes.go | 20 +- plugins/dashboard/livefeed.go | 5 +- plugins/dashboard/payload_handler.go | 14 +- plugins/dashboard/visualizer.go | 15 +- plugins/drng/plugin.go | 5 +- plugins/gossip/gossip.go | 4 +- plugins/gossip/plugin.go | 5 +- plugins/gossip/tips_broadcaster.go | 20 +- plugins/issuer/plugin.go | 5 +- plugins/messagelayer/plugin.go | 39 +- plugins/metrics/message.go | 10 +- plugins/metrics/message_test.go | 6 +- plugins/metrics/plugin.go | 7 +- plugins/pow/plugin.go | 7 +- plugins/prometheus/tangle.go | 4 +- plugins/syncbeacon/payload/payload.go | 11 +- plugins/syncbeaconfollower/plugin.go | 13 +- plugins/webapi/data/plugin.go | 4 +- plugins/webapi/message/plugin.go | 4 +- plugins/webapi/message/sendPayload.go | 4 +- .../webapi/tools/message/pastcone/handler.go | 14 +- .../tester/tests/testutil.go | 4 +- 79 files changed, 284 insertions(+), 3555 deletions(-) delete mode 100644 packages/binary/messagelayer/message/id.go delete mode 100644 packages/binary/messagelayer/message/message.go delete mode 100644 packages/binary/messagelayer/messagefactory/events.go delete mode 100644 packages/binary/messagelayer/messagefactory/messagefactory.go delete mode 100644 packages/binary/messagelayer/messagefactory/messagefactory_test.go delete mode 100644 packages/binary/messagelayer/messageparser/builtinfilters/message_signature_filter.go delete mode 100644 packages/binary/messagelayer/messageparser/builtinfilters/pow_filter.go delete mode 100644 packages/binary/messagelayer/messageparser/builtinfilters/pow_filter_test.go delete mode 100644 packages/binary/messagelayer/messageparser/builtinfilters/recently_seen_bytes_filter.go delete mode 100644 packages/binary/messagelayer/messageparser/bytes_filter.go delete mode 100644 packages/binary/messagelayer/messageparser/events.go delete mode 100644 packages/binary/messagelayer/messageparser/message_filter.go delete mode 100644 packages/binary/messagelayer/messageparser/message_parser.go delete mode 100644 packages/binary/messagelayer/messageparser/message_parser_test.go delete mode 100644 packages/binary/messagelayer/messagerequester/constants.go delete mode 100644 packages/binary/messagelayer/messagerequester/events.go delete mode 100644 packages/binary/messagelayer/messagerequester/messagerequester.go delete mode 100644 packages/binary/messagelayer/messagerequester/options.go delete mode 100644 packages/binary/messagelayer/payload/data.go delete mode 100644 packages/binary/messagelayer/payload/id.go delete mode 100644 packages/binary/messagelayer/payload/payload.go delete mode 100644 packages/binary/messagelayer/payload/type.go delete mode 100644 packages/binary/messagelayer/payload/type_register.go delete mode 100644 packages/binary/messagelayer/tangle/approver.go delete mode 100644 packages/binary/messagelayer/tangle/events.go delete mode 100644 packages/binary/messagelayer/tangle/messagemetadata.go delete mode 100644 packages/binary/messagelayer/tangle/missingmessage.go delete mode 100644 packages/binary/messagelayer/tangle/storageprefixes.go delete mode 100644 packages/binary/messagelayer/tangle/tangle.go delete mode 100644 packages/binary/messagelayer/tangle/tangle_test.go delete mode 100644 packages/binary/messagelayer/test/data_payload_test.go delete mode 100644 packages/binary/messagelayer/test/message_test.go delete mode 100644 packages/binary/messagelayer/test/retrievealltips_test.go delete mode 100644 packages/binary/messagelayer/tipselector/events.go delete mode 100644 packages/binary/messagelayer/tipselector/tipselector.go delete mode 100644 packages/binary/messagelayer/tipselector/tipselector_test.go diff --git a/dapps/faucet/dapp.go b/dapps/faucet/dapp.go index 977c1828..0fe4a8ac 100644 --- a/dapps/faucet/dapp.go +++ b/dapps/faucet/dapp.go @@ -8,10 +8,9 @@ import ( faucet "github.com/iotaledger/goshimmer/dapps/faucet/packages" faucetpayload "github.com/iotaledger/goshimmer/dapps/faucet/packages/payload" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle" "github.com/iotaledger/goshimmer/packages/pow" "github.com/iotaledger/goshimmer/packages/shutdown" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/config" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/daemon" @@ -100,7 +99,7 @@ func configure(*node.Plugin) { Faucet() fundingWorkerPool = workerpool.New(func(task workerpool.Task) { - msg := task.Param(0).(*message.Message) + msg := task.Param(0).(*tangle.Message) addr := msg.Payload().(*faucetpayload.Payload).Address() msg, txID, err := Faucet().SendFunds(msg) if err != nil { diff --git a/dapps/faucet/packages/faucet.go b/dapps/faucet/packages/faucet.go index 2e4d57e4..f56c288a 100644 --- a/dapps/faucet/packages/faucet.go +++ b/dapps/faucet/packages/faucet.go @@ -12,9 +12,9 @@ import ( "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address/signaturescheme" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance" - "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/tangle" + valuetangle "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/tangle" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/issuer" "github.com/iotaledger/hive.go/datastructure/orderedmap" ) @@ -73,7 +73,7 @@ func (f *Faucet) addAddressToBlacklist(addr address.Address) { } // SendFunds sends IOTA tokens to the address from faucet request. -func (f *Faucet) SendFunds(msg *message.Message) (m *message.Message, txID string, err error) { +func (f *Faucet) SendFunds(msg *tangle.Message) (m *tangle.Message, txID string, err error) { // ensure that only one request is being processed any given time f.Lock() defer f.Unlock() @@ -143,7 +143,7 @@ func (f *Faucet) collectUTXOsForFunding() (outputIds []transaction.OutputID, add // get a list of address for inputs for i = 0; total > 0; i++ { addr := f.seed.Address(i).Address - valuetransfers.Tangle().OutputsOnAddress(addr).Consume(func(output *tangle.Output) { + valuetransfers.Tangle().OutputsOnAddress(addr).Consume(func(output *valuetangle.Output) { if output.ConsumerCount() > 0 || total == 0 { return } diff --git a/dapps/faucet/packages/faucet_test.go b/dapps/faucet/packages/faucet_test.go index 2e5853b8..2dfda0bc 100644 --- a/dapps/faucet/packages/faucet_test.go +++ b/dapps/faucet/packages/faucet_test.go @@ -12,8 +12,7 @@ import ( faucet "github.com/iotaledger/goshimmer/dapps/faucet/packages/payload" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - data "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" ) func TestIsFaucetReq(t *testing.T) { @@ -25,9 +24,9 @@ func TestIsFaucetReq(t *testing.T) { require.NoError(t, err) return } - faucetMsg := message.New( - message.EmptyID, - message.EmptyID, + faucetMsg := tangle.NewMessage( + tangle.EmptyMessageID, + tangle.EmptyMessageID, time.Now(), local.PublicKey(), 0, @@ -36,13 +35,13 @@ func TestIsFaucetReq(t *testing.T) { ed25519.EmptySignature, ) - dataMsg := message.New( - message.EmptyID, - message.EmptyID, + dataMsg := tangle.NewMessage( + tangle.EmptyMessageID, + tangle.EmptyMessageID, time.Now(), local.PublicKey(), 0, - data.NewData([]byte("data")), + tangle.NewDataPayload([]byte("data")), 0, ed25519.EmptySignature, ) diff --git a/dapps/faucet/packages/payload/payload.go b/dapps/faucet/packages/payload/payload.go index 3d2b39e8..f9e73a97 100644 --- a/dapps/faucet/packages/payload/payload.go +++ b/dapps/faucet/packages/payload/payload.go @@ -8,13 +8,12 @@ import ( // Only want to use init _ "golang.org/x/crypto/blake2b" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" "github.com/iotaledger/goshimmer/packages/pow" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/hive.go/stringify" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" ) const ( @@ -24,13 +23,13 @@ const ( // Payload represents a request which contains an address for the faucet to send funds to. type Payload struct { - payloadType payload.Type + payloadType tangle.PayloadType address address.Address nonce uint64 } // Type represents the identifier for the faucet Payload type. -var Type = payload.Type(2) +var Type = tangle.PayloadType(2) var powWorker = pow.New(crypto.BLAKE2b_512, 1) // New is the constructor of a Payload and creates a new Payload object from the given details. @@ -52,7 +51,7 @@ func New(addr address.Address, powTarget int) (*Payload, error) { } func init() { - payload.RegisterType(Type, ObjectName, PayloadUnmarshaler) + tangle.RegisterPayloadType(Type, ObjectName, PayloadUnmarshaler) } // FromBytes parses the marshaled version of a Payload into an object. @@ -96,39 +95,39 @@ func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) { } // Type returns the type of the faucet Payload. -func (faucetPayload *Payload) Type() payload.Type { - return faucetPayload.payloadType +func (p *Payload) Type() tangle.PayloadType { + return p.payloadType } // Address returns the address of the faucet Payload. -func (faucetPayload *Payload) Address() address.Address { - return faucetPayload.address +func (p *Payload) Address() address.Address { + return p.address } // Bytes marshals the data payload into a sequence of bytes. -func (faucetPayload *Payload) Bytes() []byte { +func (p *Payload) Bytes() []byte { // initialize helper marshalUtil := marshalutil.New() // marshal the payload specific information marshalUtil.WriteUint32(uint32(address.Length + pow.NonceBytes)) - marshalUtil.WriteUint32(faucetPayload.Type()) - marshalUtil.WriteBytes(faucetPayload.address.Bytes()) - marshalUtil.WriteUint64(faucetPayload.nonce) + marshalUtil.WriteUint32(p.Type()) + marshalUtil.WriteBytes(p.address.Bytes()) + marshalUtil.WriteUint64(p.nonce) // return result return marshalUtil.Bytes() } // String returns a human readable version of faucet payload (for debug purposes). -func (faucetPayload *Payload) String() string { +func (p *Payload) String() string { return stringify.Struct("FaucetPayload", - stringify.StructField("address", faucetPayload.Address().String()), + stringify.StructField("address", p.Address().String()), ) } // PayloadUnmarshaler sets the generic unmarshaler. -func PayloadUnmarshaler(data []byte) (payload payload.Payload, err error) { +func PayloadUnmarshaler(data []byte) (payload tangle.Payload, err error) { payload, _, err = FromBytes(data) if err != nil { err = fmt.Errorf("failed to unmarshal faucet payload from bytes: %w", err) @@ -138,6 +137,6 @@ func PayloadUnmarshaler(data []byte) (payload payload.Payload, err error) { } // IsFaucetReq checks if the message is faucet payload. -func IsFaucetReq(msg *message.Message) bool { +func IsFaucetReq(msg *tangle.Message) bool { return msg.Payload().Type() == Type } diff --git a/dapps/faucet/packages/payload/payload_test.go b/dapps/faucet/packages/payload/payload_test.go index 7bf0a0b6..5635d765 100644 --- a/dapps/faucet/packages/payload/payload_test.go +++ b/dapps/faucet/packages/payload/payload_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" + "github.com/iotaledger/goshimmer/packages/tangle" ) func ExamplePayload() { @@ -24,9 +24,9 @@ func ExamplePayload() { } // 2. build actual message - tx := message.New( - message.EmptyID, - message.EmptyID, + tx := tangle.NewMessage( + tangle.EmptyMessageID, + tangle.EmptyMessageID, time.Now(), local.PublicKey(), 0, diff --git a/dapps/networkdelay/dapp.go b/dapps/networkdelay/dapp.go index 65098f91..b72c09f7 100644 --- a/dapps/networkdelay/dapp.go +++ b/dapps/networkdelay/dapp.go @@ -4,7 +4,7 @@ import ( "sync" "time" - messageTangle "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/autopeering/local" "github.com/iotaledger/goshimmer/plugins/config" "github.com/iotaledger/goshimmer/plugins/messagelayer" @@ -76,7 +76,7 @@ func configure(_ *node.Plugin) { messagelayer.Tangle().Events.MessageSolid.Attach(events.NewClosure(onReceiveMessageFromMessageLayer)) } -func onReceiveMessageFromMessageLayer(cachedMessageEvent *messageTangle.CachedMessageEvent) { +func onReceiveMessageFromMessageLayer(cachedMessageEvent *tangle.CachedMessageEvent) { defer cachedMessageEvent.Message.Release() defer cachedMessageEvent.MessageMetadata.Release() diff --git a/dapps/networkdelay/object.go b/dapps/networkdelay/object.go index 3b5c2980..a331e4b1 100644 --- a/dapps/networkdelay/object.go +++ b/dapps/networkdelay/object.go @@ -4,7 +4,7 @@ import ( "fmt" "sync" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/hive.go/stringify" "github.com/mr-tron/base58" @@ -131,15 +131,15 @@ func (o *Object) String() string { // region Payload implementation /////////////////////////////////////////////////////////////////////////////////////// // Type represents the identifier which addresses the network delay Object type. -const Type = payload.Type(189) +const Type = tangle.PayloadType(189) // Type returns the type of the Object. -func (o *Object) Type() payload.Type { +func (o *Object) Type() tangle.PayloadType { return Type } func init() { - payload.RegisterType(Type, ObjectName, func(data []byte) (payload payload.Payload, err error) { + tangle.RegisterPayloadType(Type, ObjectName, func(data []byte) (payload tangle.Payload, err error) { payload, _, err = FromBytes(data) return diff --git a/dapps/valuetransfers/dapp.go b/dapps/valuetransfers/dapp.go index 0b28fd31..27ccee4f 100644 --- a/dapps/valuetransfers/dapp.go +++ b/dapps/valuetransfers/dapp.go @@ -8,11 +8,11 @@ import ( "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/consensus" valuepayload "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload" - "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/tangle" + valuetangle "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/tangle" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/tipmanager" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction" - messageTangle "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle" "github.com/iotaledger/goshimmer/packages/shutdown" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/packages/vote" "github.com/iotaledger/goshimmer/plugins/config" "github.com/iotaledger/goshimmer/plugins/database" @@ -53,14 +53,14 @@ var ( appOnce sync.Once // _tangle represents the value tangle that is used to express votes on value transactions. - _tangle *tangle.Tangle + _tangle *valuetangle.Tangle tangleOnce sync.Once // fcob contains the fcob consensus logic. fcob *consensus.FCOB // ledgerState represents the ledger state, that keeps track of the liked branches and offers an API to access funds. - ledgerState *tangle.LedgerState + ledgerState *valuetangle.LedgerState // log holds a reference to the logger used by this app. log *logger.Logger @@ -68,7 +68,7 @@ var ( tipManager *tipmanager.TipManager tipManagerOnce sync.Once - valueObjectFactory *tangle.ValueObjectFactory + valueObjectFactory *valuetangle.ValueObjectFactory valueObjectFactoryOnce sync.Once ) @@ -82,9 +82,9 @@ func App() *node.Plugin { // Tangle gets the tangle instance. // tangle represents the value tangle that is used to express votes on value transactions. -func Tangle() *tangle.Tangle { +func Tangle() *valuetangle.Tangle { tangleOnce.Do(func() { - _tangle = tangle.New(database.Store()) + _tangle = valuetangle.New(database.Store()) }) return _tangle } @@ -97,7 +97,7 @@ func FCOB() *consensus.FCOB { // LedgerState gets the ledgerState instance. // ledgerState represents the ledger state, that keeps track of the liked branches and offers an API to access funds. -func LedgerState() *tangle.LedgerState { +func LedgerState() *valuetangle.LedgerState { return ledgerState } @@ -109,12 +109,12 @@ func configure(_ *node.Plugin) { _tangle = Tangle() // configure LedgerState - ledgerState = tangle.NewLedgerState(Tangle()) + ledgerState = valuetangle.NewLedgerState(Tangle()) // read snapshot file snapshotFilePath := config.Node().GetString(CfgValueLayerSnapshotFile) if len(snapshotFilePath) != 0 { - snapshot := tangle.Snapshot{} + snapshot := valuetangle.Snapshot{} f, err := os.Open(snapshotFilePath) if err != nil { log.Panic("can not open snapshot file:", err) @@ -134,11 +134,11 @@ func configure(_ *node.Plugin) { tipManager = TipManager() valueObjectFactory = ValueObjectFactory() - _tangle.Events.PayloadLiked.Attach(events.NewClosure(func(cachedPayloadEvent *tangle.CachedPayloadEvent) { + _tangle.Events.PayloadLiked.Attach(events.NewClosure(func(cachedPayloadEvent *valuetangle.CachedPayloadEvent) { cachedPayloadEvent.PayloadMetadata.Release() cachedPayloadEvent.Payload.Consume(tipManager.AddTip) })) - _tangle.Events.PayloadDisliked.Attach(events.NewClosure(func(cachedPayloadEvent *tangle.CachedPayloadEvent) { + _tangle.Events.PayloadDisliked.Attach(events.NewClosure(func(cachedPayloadEvent *valuetangle.CachedPayloadEvent) { cachedPayloadEvent.PayloadMetadata.Release() cachedPayloadEvent.Payload.Consume(tipManager.RemoveTip) })) @@ -167,7 +167,7 @@ func configure(_ *node.Plugin) { })) // register SignatureFilter in Parser - messagelayer.MessageParser().AddMessageFilter(tangle.NewSignatureFilter()) + messagelayer.MessageParser().AddMessageFilter(valuetangle.NewSignatureFilter()) // subscribe to message-layer messagelayer.Tangle().Events.MessageSolid.Attach(events.NewClosure(onReceiveMessageFromMessageLayer)) @@ -186,7 +186,7 @@ func run(*node.Plugin) { runFPC() } -func onReceiveMessageFromMessageLayer(cachedMessageEvent *messageTangle.CachedMessageEvent) { +func onReceiveMessageFromMessageLayer(cachedMessageEvent *tangle.CachedMessageEvent) { defer cachedMessageEvent.Message.Release() defer cachedMessageEvent.MessageMetadata.Release() @@ -221,9 +221,9 @@ func TipManager() *tipmanager.TipManager { } // ValueObjectFactory returns the ValueObjectFactory singleton. -func ValueObjectFactory() *tangle.ValueObjectFactory { +func ValueObjectFactory() *valuetangle.ValueObjectFactory { valueObjectFactoryOnce.Do(func() { - valueObjectFactory = tangle.NewValueObjectFactory(Tangle(), TipManager()) + valueObjectFactory = valuetangle.NewValueObjectFactory(Tangle(), TipManager()) }) return valueObjectFactory } @@ -235,7 +235,7 @@ func AwaitTransactionToBeBooked(txID transaction.ID, maxAwait time.Duration) err // reason the same transaction gets booked multiple times exit := make(chan struct{}) defer close(exit) - closure := events.NewClosure(func(cachedTransactionBookEvent *tangle.CachedTransactionBookEvent) { + closure := events.NewClosure(func(cachedTransactionBookEvent *valuetangle.CachedTransactionBookEvent) { defer cachedTransactionBookEvent.Transaction.Release() defer cachedTransactionBookEvent.TransactionMetadata.Release() if cachedTransactionBookEvent.Transaction.Unwrap().ID() != txID { diff --git a/dapps/valuetransfers/packages/payload/payload.go b/dapps/valuetransfers/packages/payload/payload.go index f191d206..5db6de03 100644 --- a/dapps/valuetransfers/packages/payload/payload.go +++ b/dapps/valuetransfers/packages/payload/payload.go @@ -10,7 +10,7 @@ import ( "golang.org/x/crypto/blake2b" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" ) const ( @@ -119,122 +119,122 @@ func Parse(marshalUtil *marshalutil.MarshalUtil) (result *Payload, err error) { } // ID returns the identifier if the Payload. -func (payload *Payload) ID() ID { +func (p *Payload) ID() ID { // acquire lock for reading id - payload.idMutex.RLock() + p.idMutex.RLock() // return if id has been calculated already - if payload.id != nil { - defer payload.idMutex.RUnlock() + if p.id != nil { + defer p.idMutex.RUnlock() - return *payload.id + return *p.id } // switch to write lock - payload.idMutex.RUnlock() - payload.idMutex.Lock() - defer payload.idMutex.Unlock() + p.idMutex.RUnlock() + p.idMutex.Lock() + defer p.idMutex.Unlock() // return if id has been calculated in the mean time - if payload.id != nil { - return *payload.id + if p.id != nil { + return *p.id } // otherwise calculate the id marshalUtil := marshalutil.New(IDLength + IDLength + transaction.IDLength) - marshalUtil.WriteBytes(payload.parent1PayloadID.Bytes()) - marshalUtil.WriteBytes(payload.parent2PayloadID.Bytes()) - marshalUtil.WriteBytes(payload.Transaction().ID().Bytes()) + marshalUtil.WriteBytes(p.parent1PayloadID.Bytes()) + marshalUtil.WriteBytes(p.parent2PayloadID.Bytes()) + marshalUtil.WriteBytes(p.Transaction().ID().Bytes()) var id ID = blake2b.Sum256(marshalUtil.Bytes()) - payload.id = &id + p.id = &id return id } // Parent1ID returns the first Payload that is referenced by this Payload. -func (payload *Payload) Parent1ID() ID { - return payload.parent1PayloadID +func (p *Payload) Parent1ID() ID { + return p.parent1PayloadID } // Parent2ID returns the second Payload that is referenced by this Payload. -func (payload *Payload) Parent2ID() ID { - return payload.parent2PayloadID +func (p *Payload) Parent2ID() ID { + return p.parent2PayloadID } // Transaction returns the Transaction that is being attached in this Payload. -func (payload *Payload) Transaction() *transaction.Transaction { - return payload.transaction +func (p *Payload) Transaction() *transaction.Transaction { + return p.transaction } // Bytes returns a marshaled version of this Payload. -func (payload *Payload) Bytes() []byte { - return payload.ObjectStorageValue() +func (p *Payload) Bytes() []byte { + return p.ObjectStorageValue() } -func (payload *Payload) String() string { +func (p *Payload) String() string { return stringify.Struct("Payload", - stringify.StructField("id", payload.ID()), - stringify.StructField("parent1", payload.Parent1ID()), - stringify.StructField("parent2", payload.Parent2ID()), - stringify.StructField("transfer", payload.Transaction()), + stringify.StructField("id", p.ID()), + stringify.StructField("parent1", p.Parent1ID()), + stringify.StructField("parent2", p.Parent2ID()), + stringify.StructField("transfer", p.Transaction()), ) } // region Payload implementation /////////////////////////////////////////////////////////////////////////////////////// // Type represents the identifier which addresses the value Payload type. -const Type = payload.Type(1) +const Type = tangle.PayloadType(1) // Type returns the type of the Payload. -func (payload *Payload) Type() payload.Type { +func (p *Payload) Type() tangle.PayloadType { return Type } // ObjectStorageValue returns the bytes that represent all remaining information (not stored in the key) of a marshaled // Parent2. -func (payload *Payload) ObjectStorageValue() (bytes []byte) { +func (p *Payload) ObjectStorageValue() (bytes []byte) { // acquire lock for reading bytes - payload.bytesMutex.RLock() + p.bytesMutex.RLock() // return if bytes have been determined already - if bytes = payload.bytes; bytes != nil { - defer payload.bytesMutex.RUnlock() + if bytes = p.bytes; bytes != nil { + defer p.bytesMutex.RUnlock() return } // switch to write lock - payload.bytesMutex.RUnlock() - payload.bytesMutex.Lock() - defer payload.bytesMutex.Unlock() + p.bytesMutex.RUnlock() + p.bytesMutex.Lock() + defer p.bytesMutex.Unlock() // return if bytes have been determined in the mean time - if bytes = payload.bytes; bytes != nil { + if bytes = p.bytes; bytes != nil { return } // retrieve bytes of transfer - transferBytes := payload.Transaction().ObjectStorageValue() + transferBytes := p.Transaction().ObjectStorageValue() // marshal fields payloadLength := IDLength + IDLength + len(transferBytes) marshalUtil := marshalutil.New(marshalutil.UINT32_SIZE + marshalutil.UINT32_SIZE + payloadLength) marshalUtil.WriteUint32(uint32(payloadLength)) marshalUtil.WriteUint32(Type) - marshalUtil.WriteBytes(payload.parent1PayloadID.Bytes()) - marshalUtil.WriteBytes(payload.parent2PayloadID.Bytes()) + marshalUtil.WriteBytes(p.parent1PayloadID.Bytes()) + marshalUtil.WriteBytes(p.parent2PayloadID.Bytes()) marshalUtil.WriteBytes(transferBytes) bytes = marshalUtil.Bytes() // store result - payload.bytes = bytes + p.bytes = bytes return } func init() { - payload.RegisterType(Type, ObjectName, func(data []byte) (payload payload.Payload, err error) { + tangle.RegisterPayloadType(Type, ObjectName, func(data []byte) (payload tangle.Payload, err error) { payload, _, err = FromBytes(data) return @@ -242,19 +242,19 @@ func init() { } // define contract (ensure that the struct fulfills the corresponding interface) -var _ payload.Payload = &Payload{} +var _ tangle.Payload = &Payload{} // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// // region StorableObject implementation //////////////////////////////////////////////////////////////////////////////// // ObjectStorageKey returns the bytes that are used a key when storing the Payload in an objectstorage. -func (payload *Payload) ObjectStorageKey() []byte { - return payload.ID().Bytes() +func (p *Payload) ObjectStorageKey() []byte { + return p.ID().Bytes() } // Update is disabled but needs to be implemented to be compatible with the objectstorage. -func (payload *Payload) Update(other objectstorage.StorableObject) { +func (p *Payload) Update(other objectstorage.StorableObject) { panic("a Payload should never be updated") } @@ -273,20 +273,20 @@ type CachedPayload struct { } // Retain wraps the underlying method to return a new "wrapped object". -func (cachedPayload *CachedPayload) Retain() *CachedPayload { - return &CachedPayload{cachedPayload.CachedObject.Retain()} +func (c *CachedPayload) Retain() *CachedPayload { + return &CachedPayload{c.CachedObject.Retain()} } // Consume wraps the underlying method to return the correctly typed objects in the callback. -func (cachedPayload *CachedPayload) Consume(consumer func(payload *Payload)) bool { - return cachedPayload.CachedObject.Consume(func(object objectstorage.StorableObject) { +func (c *CachedPayload) Consume(consumer func(payload *Payload)) bool { + return c.CachedObject.Consume(func(object objectstorage.StorableObject) { consumer(object.(*Payload)) }) } // Unwrap provides a way to "Get" a type casted version of the underlying object. -func (cachedPayload *CachedPayload) Unwrap() *Payload { - untypedTransaction := cachedPayload.Get() +func (c *CachedPayload) Unwrap() *Payload { + untypedTransaction := c.Get() if untypedTransaction == nil { return nil } diff --git a/dapps/valuetransfers/packages/payload/payload_test.go b/dapps/valuetransfers/packages/payload/payload_test.go index 5dc5fb27..3b0f8761 100644 --- a/dapps/valuetransfers/packages/payload/payload_test.go +++ b/dapps/valuetransfers/packages/payload/payload_test.go @@ -12,7 +12,7 @@ import ( "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address/signaturescheme" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" + "github.com/iotaledger/goshimmer/packages/tangle" ) func ExamplePayload() { @@ -45,12 +45,12 @@ func ExamplePayload() { ) // 3. build actual transaction (the base layer creates this and wraps the ontology provided payload) - tx := message.New( + tx := tangle.NewMessage( // parent1 in "network tangle" ontology (filled by tipSelector) - message.EmptyID, + tangle.EmptyMessageID, // parent2 in "network tangle" ontology (filled by tipSelector) - message.EmptyID, + tangle.EmptyMessageID, // the time when the transaction was created time.Now(), diff --git a/dapps/valuetransfers/packages/tangle/payloadapprover.go b/dapps/valuetransfers/packages/tangle/payloadapprover.go index b24c6540..6489960e 100644 --- a/dapps/valuetransfers/packages/tangle/payloadapprover.go +++ b/dapps/valuetransfers/packages/tangle/payloadapprover.go @@ -40,11 +40,11 @@ func PayloadApproverFromBytes(bytes []byte) (result *PayloadApprover, consumedBy func ParsePayloadApprover(marshalUtil *marshalutil.MarshalUtil) (result *PayloadApprover, err error) { result = &PayloadApprover{} if result.referencedPayloadID, err = payload.ParseID(marshalUtil); err != nil { - err = fmt.Errorf("failed to parse payload id of approver: %w", err) + err = fmt.Errorf("failed to parse referenced payload id of approver: %w", err) return } if result.approvingPayloadID, err = payload.ParseID(marshalUtil); err != nil { - err = fmt.Errorf("failed to parse payload id of approver: %w", err) + err = fmt.Errorf("failed to parse approving payload id of approver: %w", err) return } diff --git a/dapps/valuetransfers/packages/tangle/signature_filter.go b/dapps/valuetransfers/packages/tangle/signature_filter.go index a7e7e2cc..abc3d802 100644 --- a/dapps/valuetransfers/packages/tangle/signature_filter.go +++ b/dapps/valuetransfers/packages/tangle/signature_filter.go @@ -5,15 +5,14 @@ import ( "sync" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messageparser" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/hive.go/autopeering/peer" ) // SignatureFilter represents a filter for the MessageParser that filters out transactions with an invalid signature. type SignatureFilter struct { - onAcceptCallback func(message *message.Message, peer *peer.Peer) - onRejectCallback func(message *message.Message, err error, peer *peer.Peer) + onAcceptCallback func(message *tangle.Message, peer *peer.Peer) + onRejectCallback func(message *tangle.Message, err error, peer *peer.Peer) onAcceptCallbackMutex sync.RWMutex onRejectCallbackMutex sync.RWMutex } @@ -25,7 +24,7 @@ func NewSignatureFilter() *SignatureFilter { // Filter get's called whenever a new message is received. It rejects the message, if the message is not a valid value // message. -func (filter *SignatureFilter) Filter(message *message.Message, peer *peer.Peer) { +func (filter *SignatureFilter) Filter(message *tangle.Message, peer *peer.Peer) { // accept message if the message is not a value message (it will be checked by other filters) valuePayload := message.Payload() if valuePayload.Type() != payload.Type { @@ -54,7 +53,7 @@ func (filter *SignatureFilter) Filter(message *message.Message, peer *peer.Peer) } // OnAccept registers the given callback as the acceptance function of the filter. -func (filter *SignatureFilter) OnAccept(callback func(message *message.Message, peer *peer.Peer)) { +func (filter *SignatureFilter) OnAccept(callback func(message *tangle.Message, peer *peer.Peer)) { filter.onAcceptCallbackMutex.Lock() defer filter.onAcceptCallbackMutex.Unlock() @@ -62,7 +61,7 @@ func (filter *SignatureFilter) OnAccept(callback func(message *message.Message, } // OnReject registers the given callback as the rejection function of the filter. -func (filter *SignatureFilter) OnReject(callback func(message *message.Message, err error, peer *peer.Peer)) { +func (filter *SignatureFilter) OnReject(callback func(message *tangle.Message, err error, peer *peer.Peer)) { filter.onRejectCallbackMutex.Lock() defer filter.onRejectCallbackMutex.Unlock() @@ -70,7 +69,7 @@ func (filter *SignatureFilter) OnReject(callback func(message *message.Message, } // getAcceptCallback returns the callback that is executed when a message passes the filter. -func (filter *SignatureFilter) getAcceptCallback() func(message *message.Message, peer *peer.Peer) { +func (filter *SignatureFilter) getAcceptCallback() func(message *tangle.Message, peer *peer.Peer) { filter.onAcceptCallbackMutex.RLock() defer filter.onAcceptCallbackMutex.RUnlock() @@ -78,7 +77,7 @@ func (filter *SignatureFilter) getAcceptCallback() func(message *message.Message } // getRejectCallback returns the callback that is executed when a message is blocked by the filter. -func (filter *SignatureFilter) getRejectCallback() func(message *message.Message, err error, peer *peer.Peer) { +func (filter *SignatureFilter) getRejectCallback() func(message *tangle.Message, err error, peer *peer.Peer) { filter.onRejectCallbackMutex.RLock() defer filter.onRejectCallbackMutex.RUnlock() @@ -86,4 +85,4 @@ func (filter *SignatureFilter) getRejectCallback() func(message *message.Message } // interface contract (allow the compiler to check if the implementation has all of the required methods). -var _ messageparser.MessageFilter = &SignatureFilter{} +var _ tangle.MessageFilter = &SignatureFilter{} diff --git a/dapps/valuetransfers/packages/tangle/signature_filter_test.go b/dapps/valuetransfers/packages/tangle/signature_filter_test.go index c8640ad5..1cb93f67 100644 --- a/dapps/valuetransfers/packages/tangle/signature_filter_test.go +++ b/dapps/valuetransfers/packages/tangle/signature_filter_test.go @@ -9,11 +9,7 @@ import ( "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance" valuePayload "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messagefactory" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messageparser" - messagePayload "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tipselector" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/hive.go/autopeering/peer" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/identity" @@ -28,7 +24,7 @@ func TestSignatureFilter(t *testing.T) { // create helper instances seed := newSeed() - messageFactory := messagefactory.New(mapdb.NewMapDB(), []byte("sequenceKey"), identity.GenerateLocalIdentity(), tipselector.New()) + messageFactory := tangle.NewMessageFactory(mapdb.NewMapDB(), []byte("sequenceKey"), identity.GenerateLocalIdentity(), tangle.NewMessageTipSelector()) // 1. test value message without signatures { @@ -84,14 +80,14 @@ func TestSignatureFilter(t *testing.T) { // 3. test message with an invalid value payload { // create a data payload - marshalUtil := marshalutil.New(messagePayload.NewData([]byte("test")).Bytes()) + marshalUtil := marshalutil.New(tangle.NewDataPayload([]byte("test")).Bytes()) // set the type to be a value payload marshalUtil.WriteSeek(4) marshalUtil.WriteUint32(valuePayload.Type) // parse modified bytes back into a payload object - dataPayload, _, err := messagePayload.DataFromBytes(marshalUtil.Bytes()) + dataPayload, _, err := tangle.DataPayloadFromBytes(marshalUtil.Bytes()) require.NoError(t, err) // parse message bytes @@ -108,9 +104,9 @@ func TestSignatureFilter(t *testing.T) { // newSyncMessageParser creates a wrapped MessageParser that works synchronously by using a WaitGroup to wait for the // parse result. -func newSyncMessageParser(messageFilters ...messageparser.MessageFilter) (tester *syncMessageParser) { +func newSyncMessageParser(messageFilters ...tangle.MessageFilter) (tester *syncMessageParser) { // initialize MessageParser - messageParser := messageparser.New() + messageParser := tangle.NewMessageParser() for _, messageFilter := range messageFilters { messageParser.AddMessageFilter(messageFilter) } @@ -121,7 +117,7 @@ func newSyncMessageParser(messageFilters ...messageparser.MessageFilter) (tester } // setup async behavior (store result + mark WaitGroup done) - messageParser.Events.BytesRejected.Attach(events.NewClosure(func(bytesRejectedEvent *messageparser.BytesRejectedEvent, err error) { + messageParser.Events.BytesRejected.Attach(events.NewClosure(func(bytesRejectedEvent *tangle.BytesRejectedEvent, err error) { tester.result = &messageParserResult{ accepted: false, message: nil, @@ -131,7 +127,7 @@ func newSyncMessageParser(messageFilters ...messageparser.MessageFilter) (tester tester.wg.Done() })) - messageParser.Events.MessageRejected.Attach(events.NewClosure(func(msgRejectedEvent *messageparser.MessageRejectedEvent, err error) { + messageParser.Events.MessageRejected.Attach(events.NewClosure(func(msgRejectedEvent *tangle.MessageRejectedEvent, err error) { tester.result = &messageParserResult{ accepted: false, message: msgRejectedEvent.Message, @@ -141,7 +137,7 @@ func newSyncMessageParser(messageFilters ...messageparser.MessageFilter) (tester tester.wg.Done() })) - messageParser.Events.MessageParsed.Attach(events.NewClosure(func(msgParsedEvent *messageparser.MessageParsedEvent) { + messageParser.Events.MessageParsed.Attach(events.NewClosure(func(msgParsedEvent *tangle.MessageParsedEvent) { tester.result = &messageParserResult{ accepted: true, message: msgParsedEvent.Message, @@ -157,13 +153,13 @@ func newSyncMessageParser(messageFilters ...messageparser.MessageFilter) (tester // syncMessageParser is a wrapper for the MessageParser that allows to parse Messages synchronously. type syncMessageParser struct { - messageParser *messageparser.MessageParser + messageParser *tangle.MessageParser result *messageParserResult wg sync.WaitGroup } // Parse parses the message bytes into a message. It either gets accepted or rejected. -func (tester *syncMessageParser) Parse(messageBytes []byte, peer *peer.Peer) (bool, *message.Message, *peer.Peer, error) { +func (tester *syncMessageParser) Parse(messageBytes []byte, peer *peer.Peer) (bool, *tangle.Message, *peer.Peer, error) { tester.wg.Add(1) tester.messageParser.Parse(messageBytes, peer) tester.wg.Wait() @@ -175,7 +171,7 @@ func (tester *syncMessageParser) Parse(messageBytes []byte, peer *peer.Peer) (bo // WaitGroup is done waiting. type messageParserResult struct { accepted bool - message *message.Message + message *tangle.Message peer *peer.Peer err error } diff --git a/packages/binary/drng/payload/payload.go b/packages/binary/drng/payload/payload.go index e3f1c0a6..bf679c27 100644 --- a/packages/binary/drng/payload/payload.go +++ b/packages/binary/drng/payload/payload.go @@ -5,7 +5,7 @@ import ( "sync" "github.com/iotaledger/goshimmer/packages/binary/drng/payload/header" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/hive.go/stringify" ) @@ -127,10 +127,10 @@ func (payload *Payload) String() string { // region Payload implementation /////////////////////////////////////////////////////////////////////////////////////// // Type defines the type of the drng payload. -var Type = payload.Type(111) +var Type = tangle.PayloadType(111) // Type returns the type of the drng payload. -func (payload *Payload) Type() payload.Type { +func (payload *Payload) Type() tangle.PayloadType { return Type } @@ -140,7 +140,7 @@ func (payload *Payload) Marshal() (bytes []byte, err error) { } func init() { - payload.RegisterType(Type, ObjectName, func(data []byte) (payload payload.Payload, err error) { + tangle.RegisterPayloadType(Type, ObjectName, func(data []byte) (payload tangle.Payload, err error) { payload, _, err = FromBytes(data) return diff --git a/packages/binary/drng/subtypes/collectivebeacon/payload/payload.go b/packages/binary/drng/subtypes/collectivebeacon/payload/payload.go index 46bed289..84808da4 100644 --- a/packages/binary/drng/subtypes/collectivebeacon/payload/payload.go +++ b/packages/binary/drng/subtypes/collectivebeacon/payload/payload.go @@ -8,7 +8,7 @@ import ( drngPayload "github.com/iotaledger/goshimmer/packages/binary/drng/payload" "github.com/iotaledger/goshimmer/packages/binary/drng/payload/header" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/hive.go/marshalutil" ) @@ -109,23 +109,23 @@ func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) { } // Bytes returns the collective beacon payload bytes. -func (payload *Payload) Bytes() (bytes []byte) { +func (p *Payload) Bytes() (bytes []byte) { // acquire lock for reading bytes - payload.bytesMutex.RLock() + p.bytesMutex.RLock() // return if bytes have been determined already - if bytes = payload.bytes; bytes != nil { - payload.bytesMutex.RUnlock() + if bytes = p.bytes; bytes != nil { + p.bytesMutex.RUnlock() return } // switch to write lock - payload.bytesMutex.RUnlock() - payload.bytesMutex.Lock() - defer payload.bytesMutex.Unlock() + p.bytesMutex.RUnlock() + p.bytesMutex.Lock() + defer p.bytesMutex.Unlock() // return if bytes have been determined in the mean time - if bytes = payload.bytes; bytes != nil { + if bytes = p.bytes; bytes != nil { return } @@ -134,41 +134,41 @@ func (payload *Payload) Bytes() (bytes []byte) { marshalUtil := marshalutil.New(marshalutil.UINT32_SIZE + marshalutil.UINT32_SIZE + payloadLength) marshalUtil.WriteUint32(uint32(payloadLength)) marshalUtil.WriteUint32(drngPayload.Type) - marshalUtil.WriteBytes(payload.Header.Bytes()) - marshalUtil.WriteUint64(payload.Round) - marshalUtil.WriteBytes(payload.PrevSignature) - marshalUtil.WriteBytes(payload.Signature) - marshalUtil.WriteBytes(payload.Dpk) + marshalUtil.WriteBytes(p.Header.Bytes()) + marshalUtil.WriteUint64(p.Round) + marshalUtil.WriteBytes(p.PrevSignature) + marshalUtil.WriteBytes(p.Signature) + marshalUtil.WriteBytes(p.Dpk) bytes = marshalUtil.Bytes() // store result - payload.bytes = bytes + p.bytes = bytes return } -func (payload *Payload) String() string { +func (p *Payload) String() string { return stringify.Struct("Payload", - stringify.StructField("type", uint64(payload.Header.PayloadType)), - stringify.StructField("instance", uint64(payload.Header.InstanceID)), - stringify.StructField("round", payload.Round), - stringify.StructField("prevSignature", payload.PrevSignature), - stringify.StructField("signature", payload.Signature), - stringify.StructField("distributedPK", payload.Dpk), + stringify.StructField("type", uint64(p.Header.PayloadType)), + stringify.StructField("instance", uint64(p.Header.InstanceID)), + stringify.StructField("round", p.Round), + stringify.StructField("prevSignature", p.PrevSignature), + stringify.StructField("signature", p.Signature), + stringify.StructField("distributedPK", p.Dpk), ) } // region Payload implementation /////////////////////////////////////////////////////////////////////////////////////// // Type returns the collective beacon payload type. -func (payload *Payload) Type() payload.Type { +func (p *Payload) Type() tangle.PayloadType { return drngPayload.Type } // Marshal marshals the collective beacon payload into bytes. -func (payload *Payload) Marshal() (bytes []byte, err error) { - return payload.Bytes(), nil +func (p *Payload) Marshal() (bytes []byte, err error) { + return p.Bytes(), nil } // // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/packages/binary/messagelayer/message/id.go b/packages/binary/messagelayer/message/id.go deleted file mode 100644 index 3ac24f93..00000000 --- a/packages/binary/messagelayer/message/id.go +++ /dev/null @@ -1,86 +0,0 @@ -package message - -import ( - "fmt" - - "github.com/iotaledger/hive.go/marshalutil" - "github.com/mr-tron/base58" -) - -// ContentID identifies the content of a message without its parent1/parent2 ids. -type ContentID = ID - -// ID identifies a message in its entirety. Unlike the sole content id, it also incorporates -// the parent1 and parent2 ids. -type ID [IDLength]byte - -// NewID creates a new message id. -func NewID(base58EncodedString string) (result ID, err error) { - bytes, err := base58.Decode(base58EncodedString) - if err != nil { - return - } - - if len(bytes) != IDLength { - err = fmt.Errorf("length of base58 formatted message id is wrong") - - return - } - - copy(result[:], bytes) - - return -} - -// IDFromBytes unmarshals a message id from a sequence of bytes. -func IDFromBytes(bytes []byte) (result ID, consumedBytes int, err error) { - // check arguments - if len(bytes) < IDLength { - err = fmt.Errorf("bytes not long enough to encode a valid message id") - } - - // calculate result - copy(result[:], bytes) - - // return the number of bytes we processed - consumedBytes = IDLength - - return -} - -// ParseID is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package. -func ParseID(marshalUtil *marshalutil.MarshalUtil) (ID, error) { - id, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return IDFromBytes(data) }) - if err != nil { - return ID{}, err - } - return id.(ID), nil -} - -// MarshalBinary marshals the ID into bytes. -func (id *ID) MarshalBinary() (result []byte, err error) { - return id.Bytes(), nil -} - -// UnmarshalBinary unmarshals the bytes into an ID. -func (id *ID) UnmarshalBinary(data []byte) (err error) { - copy(id[:], data) - - return -} - -// Bytes returns the bytes of the ID. -func (id ID) Bytes() []byte { - return id[:] -} - -// String returns the base58 encode of the ID. -func (id ID) String() string { - return base58.Encode(id[:]) -} - -// EmptyID is an empty id. -var EmptyID = ID{} - -// IDLength defines the length of an ID. -const IDLength = 64 diff --git a/packages/binary/messagelayer/message/message.go b/packages/binary/messagelayer/message/message.go deleted file mode 100644 index 0ea9d7a2..00000000 --- a/packages/binary/messagelayer/message/message.go +++ /dev/null @@ -1,342 +0,0 @@ -package message - -import ( - "fmt" - "sync" - "time" - - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/hive.go/marshalutil" - "github.com/iotaledger/hive.go/objectstorage" - "github.com/iotaledger/hive.go/stringify" - "golang.org/x/crypto/blake2b" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" -) - -// Message represents the core message for the base layer Tangle. -type Message struct { - // base functionality of StorableObject - objectstorage.StorableObjectFlags - - // core properties (get sent over the wire) - parent1ID ID - parent2ID ID - issuerPublicKey ed25519.PublicKey - issuingTime time.Time - sequenceNumber uint64 - payload payload.Payload - nonce uint64 - signature ed25519.Signature - - // derived properties - id *ID - idMutex sync.RWMutex - contentID *ContentID - contentIDMutex sync.RWMutex - bytes []byte - bytesMutex sync.RWMutex -} - -// New creates a new message with the details provided by the issuer. -func New(parent1ID ID, parent2ID ID, issuingTime time.Time, issuerPublicKey ed25519.PublicKey, sequenceNumber uint64, payload payload.Payload, nonce uint64, signature ed25519.Signature) (result *Message) { - return &Message{ - parent1ID: parent1ID, - parent2ID: parent2ID, - issuerPublicKey: issuerPublicKey, - issuingTime: issuingTime, - sequenceNumber: sequenceNumber, - payload: payload, - nonce: nonce, - signature: signature, - } -} - -// FromBytes parses the given bytes into a message. -func FromBytes(bytes []byte) (result *Message, consumedBytes int, err error) { - marshalUtil := marshalutil.New(bytes) - result, err = Parse(marshalUtil) - consumedBytes = marshalUtil.ReadOffset() - - return -} - -// Parse parses a Message using the given marshal util. -func Parse(marshalUtil *marshalutil.MarshalUtil) (result *Message, err error) { - // determine read offset before starting to parse - readOffsetStart := marshalUtil.ReadOffset() - - // parse information - result = &Message{} - if result.parent1ID, err = ParseID(marshalUtil); err != nil { - return - } - if result.parent2ID, err = ParseID(marshalUtil); err != nil { - return - } - if result.issuerPublicKey, err = ed25519.ParsePublicKey(marshalUtil); err != nil { - return - } - if result.issuingTime, err = marshalUtil.ReadTime(); err != nil { - return - } - if result.sequenceNumber, err = marshalUtil.ReadUint64(); err != nil { - return - } - if result.payload, err = payload.Parse(marshalUtil); err != nil { - return - } - if result.nonce, err = marshalUtil.ReadUint64(); err != nil { - return - } - if result.signature, err = ed25519.ParseSignature(marshalUtil); err != nil { - return - } - - // retrieve the number of bytes we processed - readOffsetEnd := marshalUtil.ReadOffset() - - // store marshaled version as a copy - result.bytes, err = marshalUtil.ReadBytes(readOffsetEnd-readOffsetStart, readOffsetStart) - if err != nil { - err = fmt.Errorf("error trying to copy raw source bytes: %w", err) - - return - } - - return -} - -// FromObjectStorage gets called when we restore a message from the ObjectStorage. -func FromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) { - // parse the message - message, err := Parse(marshalutil.New(data)) - if err != nil { - return - } - - // parse the ID from they key - id, err := ParseID(marshalutil.New(key)) - if err != nil { - return - } - message.id = &id - - // assign result - result = message - - return -} - -// VerifySignature verifies the signature of the message. -func (message *Message) VerifySignature() bool { - msgBytes := message.Bytes() - signature := message.Signature() - - contentLength := len(msgBytes) - len(signature) - content := msgBytes[:contentLength] - - return message.issuerPublicKey.VerifySignature(content, signature) -} - -// ID returns the id of the message which is made up of the content id and parent1/parent2 ids. -// This id can be used for merkle proofs. -func (message *Message) ID() (result ID) { - message.idMutex.RLock() - - if message.id == nil { - message.idMutex.RUnlock() - - message.idMutex.Lock() - defer message.idMutex.Unlock() - if message.id != nil { - result = *message.id - return - } - result = message.calculateID() - message.id = &result - return - } - - result = *message.id - message.idMutex.RUnlock() - return -} - -// Parent1ID returns the id of the parent1 message. -func (message *Message) Parent1ID() ID { - return message.parent1ID -} - -// Parent2ID returns the id of the parent2 message. -func (message *Message) Parent2ID() ID { - return message.parent2ID -} - -// IssuerPublicKey returns the public key of the message issuer. -func (message *Message) IssuerPublicKey() ed25519.PublicKey { - return message.issuerPublicKey -} - -// IssuingTime returns the time when this message was created. -func (message *Message) IssuingTime() time.Time { - return message.issuingTime -} - -// SequenceNumber returns the sequence number of this message. -func (message *Message) SequenceNumber() uint64 { - return message.sequenceNumber -} - -// Payload returns the payload of the message. -func (message *Message) Payload() payload.Payload { - return message.payload -} - -// Nonce returns the nonce of the message. -func (message *Message) Nonce() uint64 { - return message.nonce -} - -// Signature returns the signature of the message. -func (message *Message) Signature() ed25519.Signature { - return message.signature -} - -// ContentID returns the content id of the message which is made up of all the -// parts of the message minus the parent1 and parent2 ids. -func (message *Message) ContentID() (result ContentID) { - message.contentIDMutex.RLock() - if message.contentID == nil { - message.contentIDMutex.RUnlock() - - message.contentIDMutex.Lock() - defer message.contentIDMutex.Unlock() - if message.contentID != nil { - result = *message.contentID - return - } - result = message.calculateContentID() - message.contentID = &result - return - } - - result = *message.contentID - message.contentIDMutex.RUnlock() - return -} - -// calculates the message id. -func (message *Message) calculateID() ID { - return blake2b.Sum512( - marshalutil.New(IDLength + IDLength + payload.IDLength). - WriteBytes(message.parent1ID.Bytes()). - WriteBytes(message.parent2ID.Bytes()). - WriteBytes(message.ContentID().Bytes()). - Bytes(), - ) -} - -// calculates the content id of the message. -func (message *Message) calculateContentID() ContentID { - // compute content id from the message data (except parent1 and parent2 ids) - return blake2b.Sum512(message.Bytes()[2*IDLength:]) -} - -// Bytes returns the message in serialized byte form. -func (message *Message) Bytes() []byte { - message.bytesMutex.RLock() - if message.bytes != nil { - defer message.bytesMutex.RUnlock() - - return message.bytes - } - - message.bytesMutex.RUnlock() - message.bytesMutex.RLock() - defer message.bytesMutex.RUnlock() - - if message.bytes != nil { - return message.bytes - } - - // marshal result - marshalUtil := marshalutil.New() - marshalUtil.WriteBytes(message.parent1ID.Bytes()) - marshalUtil.WriteBytes(message.parent2ID.Bytes()) - marshalUtil.WriteBytes(message.issuerPublicKey.Bytes()) - marshalUtil.WriteTime(message.issuingTime) - marshalUtil.WriteUint64(message.sequenceNumber) - marshalUtil.WriteBytes(message.payload.Bytes()) - marshalUtil.WriteUint64(message.nonce) - marshalUtil.WriteBytes(message.signature.Bytes()) - - message.bytes = marshalUtil.Bytes() - - return message.bytes -} - -// ObjectStorageKey returns the key of the stored message object. -// This returns the bytes of the message ID. -func (message *Message) ObjectStorageKey() []byte { - return message.ID().Bytes() -} - -// ObjectStorageValue returns the value stored in object storage. -// This returns the bytes of message. -func (message *Message) ObjectStorageValue() []byte { - return message.Bytes() -} - -// Update updates the object with the values of another object. -// Since a Message is immutable, this function is not implemented and panics. -func (message *Message) Update(objectstorage.StorableObject) { - panic("messages should never be overwritten and only stored once to optimize IO") -} - -func (message *Message) String() string { - return stringify.Struct("Message", - stringify.StructField("id", message.ID()), - stringify.StructField("parent1Id", message.Parent1ID()), - stringify.StructField("parent2Id", message.Parent2ID()), - stringify.StructField("issuer", message.IssuerPublicKey()), - stringify.StructField("issuingTime", message.IssuingTime()), - stringify.StructField("sequenceNumber", message.SequenceNumber()), - stringify.StructField("payload", message.Payload()), - stringify.StructField("nonce", message.Nonce()), - stringify.StructField("signature", message.Signature()), - ) -} - -// CachedMessage defines a cached message. -// A wrapper for a cached object. -type CachedMessage struct { - objectstorage.CachedObject -} - -// Retain registers a new consumer for the cached message. -func (cachedMessage *CachedMessage) Retain() *CachedMessage { - return &CachedMessage{cachedMessage.CachedObject.Retain()} -} - -// Consume consumes the cached object and releases it when the callback is done. -// It returns true if the callback was called. -func (cachedMessage *CachedMessage) Consume(consumer func(msg *Message)) bool { - return cachedMessage.CachedObject.Consume(func(object objectstorage.StorableObject) { - consumer(object.(*Message)) - }) -} - -// Unwrap returns the message wrapped by the cached message. -// If the wrapped object cannot be cast to a Message or has been deleted, it returns nil. -func (cachedMessage *CachedMessage) Unwrap() *Message { - untypedMessage := cachedMessage.Get() - if untypedMessage == nil { - return nil - } - typeCastedMessage := untypedMessage.(*Message) - if typeCastedMessage == nil || typeCastedMessage.IsDeleted() { - return nil - } - return typeCastedMessage -} diff --git a/packages/binary/messagelayer/messagefactory/events.go b/packages/binary/messagelayer/messagefactory/events.go deleted file mode 100644 index 873b0aca..00000000 --- a/packages/binary/messagelayer/messagefactory/events.go +++ /dev/null @@ -1,26 +0,0 @@ -package messagefactory - -import ( - "github.com/iotaledger/hive.go/events" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" -) - -// Events represents events happening on a message factory. -type Events struct { - // Fired when a message is built including tips, sequence number and other metadata. - MessageConstructed *events.Event - // Fired when an error occurred. - Error *events.Event -} - -func newEvents() *Events { - return &Events{ - MessageConstructed: events.NewEvent(messageConstructedEvent), - Error: events.NewEvent(events.ErrorCaller), - } -} - -func messageConstructedEvent(handler interface{}, params ...interface{}) { - handler.(func(*message.Message))(params[0].(*message.Message)) -} diff --git a/packages/binary/messagelayer/messagefactory/messagefactory.go b/packages/binary/messagelayer/messagefactory/messagefactory.go deleted file mode 100644 index c1b01238..00000000 --- a/packages/binary/messagelayer/messagefactory/messagefactory.go +++ /dev/null @@ -1,155 +0,0 @@ -package messagefactory - -import ( - "fmt" - "sync" - "time" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/hive.go/identity" - "github.com/iotaledger/hive.go/kvstore" -) - -const storeSequenceInterval = 100 - -var ( - // ZeroWorker is a PoW worker that always returns 0 as the nonce. - ZeroWorker = WorkerFunc(func([]byte) (uint64, error) { return 0, nil }) -) - -// A TipSelector selects two tips, parent2 and parent1, for a new message to attach to. -type TipSelector interface { - Tips() (parent1 message.ID, parent2 message.ID) -} - -// A Worker performs the PoW for the provided message in serialized byte form. -type Worker interface { - DoPOW([]byte) (nonce uint64, err error) -} - -// MessageFactory acts as a factory to create new messages. -type MessageFactory struct { - Events *Events - sequence *kvstore.Sequence - localIdentity *identity.LocalIdentity - selector TipSelector - - worker Worker - workerMutex sync.RWMutex - issuanceMutex sync.Mutex -} - -// New creates a new message factory. -func New(store kvstore.KVStore, sequenceKey []byte, localIdentity *identity.LocalIdentity, selector TipSelector) *MessageFactory { - sequence, err := kvstore.NewSequence(store, sequenceKey, storeSequenceInterval) - if err != nil { - panic(fmt.Sprintf("could not create message sequence number: %v", err)) - } - - return &MessageFactory{ - Events: newEvents(), - sequence: sequence, - localIdentity: localIdentity, - selector: selector, - worker: ZeroWorker, - } -} - -// SetWorker sets the PoW worker to be used for the messages. -func (m *MessageFactory) SetWorker(worker Worker) { - m.workerMutex.Lock() - defer m.workerMutex.Unlock() - m.worker = worker -} - -// IssuePayload creates a new message including sequence number and tip selection and returns it. -// It also triggers the MessageConstructed event once it's done, which is for example used by the plugins to listen for -// messages that shall be attached to the tangle. -func (m *MessageFactory) IssuePayload(p payload.Payload) (*message.Message, error) { - payloadLen := len(p.Bytes()) - if payloadLen > payload.MaxPayloadSize { - err := fmt.Errorf("%w: %d bytes", payload.ErrMaxPayloadSizeExceeded, payloadLen) - m.Events.Error.Trigger(err) - return nil, err - } - - m.issuanceMutex.Lock() - defer m.issuanceMutex.Unlock() - sequenceNumber, err := m.sequence.Next() - if err != nil { - err = fmt.Errorf("could not create sequence number: %w", err) - m.Events.Error.Trigger(err) - return nil, err - } - - parent1ID, parent2ID := m.selector.Tips() - issuingTime := time.Now() - issuerPublicKey := m.localIdentity.PublicKey() - - // do the PoW - nonce, err := m.doPOW(parent1ID, parent2ID, issuingTime, issuerPublicKey, sequenceNumber, p) - if err != nil { - err = fmt.Errorf("pow failed: %w", err) - m.Events.Error.Trigger(err) - return nil, err - } - - // create the signature - signature := m.sign(parent1ID, parent2ID, issuingTime, issuerPublicKey, sequenceNumber, p, nonce) - - msg := message.New( - parent1ID, - parent2ID, - issuingTime, - issuerPublicKey, - sequenceNumber, - p, - nonce, - signature, - ) - m.Events.MessageConstructed.Trigger(msg) - return msg, nil -} - -// Shutdown closes the messageFactory and persists the sequence number. -func (m *MessageFactory) Shutdown() { - if err := m.sequence.Release(); err != nil { - m.Events.Error.Trigger(fmt.Errorf("could not release message sequence number: %w", err)) - } -} - -func (m *MessageFactory) doPOW(parent1ID message.ID, parent2ID message.ID, issuingTime time.Time, key ed25519.PublicKey, seq uint64, payload payload.Payload) (uint64, error) { - // create a dummy message to simplify marshaling - dummy := message.New(parent1ID, parent2ID, issuingTime, key, seq, payload, 0, ed25519.EmptySignature).Bytes() - - m.workerMutex.RLock() - defer m.workerMutex.RUnlock() - return m.worker.DoPOW(dummy) -} - -func (m *MessageFactory) sign(parent1ID message.ID, parent2ID message.ID, issuingTime time.Time, key ed25519.PublicKey, seq uint64, payload payload.Payload, nonce uint64) ed25519.Signature { - // create a dummy message to simplify marshaling - dummy := message.New(parent1ID, parent2ID, issuingTime, key, seq, payload, nonce, ed25519.EmptySignature) - dummyBytes := dummy.Bytes() - - contentLength := len(dummyBytes) - len(dummy.Signature()) - return m.localIdentity.Sign(dummyBytes[:contentLength]) -} - -// The TipSelectorFunc type is an adapter to allow the use of ordinary functions as tip selectors. -type TipSelectorFunc func() (message.ID, message.ID) - -// Tips calls f(). -func (f TipSelectorFunc) Tips() (message.ID, message.ID) { - return f() -} - -// The WorkerFunc type is an adapter to allow the use of ordinary functions as a PoW performer. -type WorkerFunc func([]byte) (uint64, error) - -// DoPOW calls f(msg). -func (f WorkerFunc) DoPOW(msg []byte) (uint64, error) { - return f(msg) -} diff --git a/packages/binary/messagelayer/messagefactory/messagefactory_test.go b/packages/binary/messagelayer/messagefactory/messagefactory_test.go deleted file mode 100644 index ff566d39..00000000 --- a/packages/binary/messagelayer/messagefactory/messagefactory_test.go +++ /dev/null @@ -1,163 +0,0 @@ -package messagefactory - -import ( - "context" - "crypto" - "crypto/ed25519" - "sync" - "sync/atomic" - "testing" - "time" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" - "github.com/iotaledger/goshimmer/packages/pow" - "github.com/iotaledger/hive.go/events" - "github.com/iotaledger/hive.go/identity" - "github.com/iotaledger/hive.go/kvstore/mapdb" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - _ "golang.org/x/crypto/blake2b" -) - -const ( - sequenceKey = "seq" - targetPOW = 10 - totalMessages = 2000 -) - -func TestMessageFactory_BuildMessage(t *testing.T) { - msgFactory := New( - mapdb.NewMapDB(), - []byte(sequenceKey), - identity.GenerateLocalIdentity(), - TipSelectorFunc(func() (message.ID, message.ID) { return message.EmptyID, message.EmptyID }), - ) - defer msgFactory.Shutdown() - - // keep track of sequence numbers - sequenceNumbers := sync.Map{} - - // attach to event and count - countEvents := uint64(0) - msgFactory.Events.MessageConstructed.Attach(events.NewClosure(func(msg *message.Message) { - atomic.AddUint64(&countEvents, 1) - })) - - t.Run("CheckProperties", func(t *testing.T) { - p := payload.NewData([]byte("TestCheckProperties")) - msg, err := msgFactory.IssuePayload(p) - require.NoError(t, err) - - assert.NotNil(t, msg.Parent1ID()) - assert.NotNil(t, msg.Parent2ID()) - - // time in range of 0.1 seconds - assert.InDelta(t, time.Now().UnixNano(), msg.IssuingTime().UnixNano(), 100000000) - - // check payload - assert.Equal(t, p, msg.Payload()) - - // check total events and sequence number - assert.EqualValues(t, 1, countEvents) - assert.EqualValues(t, 0, msg.SequenceNumber()) - - sequenceNumbers.Store(msg.SequenceNumber(), true) - }) - - // create messages in parallel - t.Run("ParallelCreation", func(t *testing.T) { - for i := 1; i < totalMessages; i++ { - t.Run("test", func(t *testing.T) { - t.Parallel() - - p := payload.NewData([]byte("TestParallelCreation")) - msg, err := msgFactory.IssuePayload(p) - require.NoError(t, err) - - assert.NotNil(t, msg.Parent1ID()) - assert.NotNil(t, msg.Parent2ID()) - - // time in range of 0.1 seconds - assert.InDelta(t, time.Now().UnixNano(), msg.IssuingTime().UnixNano(), 100000000) - - // check payload - assert.Equal(t, p, msg.Payload()) - - sequenceNumbers.Store(msg.SequenceNumber(), true) - }) - } - }) - - // check total events and sequence number - assert.EqualValues(t, totalMessages, countEvents) - - max := uint64(0) - countSequence := 0 - sequenceNumbers.Range(func(key, value interface{}) bool { - seq := key.(uint64) - val := value.(bool) - if val != true { - return false - } - - // check for max sequence number - if seq > max { - max = seq - } - countSequence++ - return true - }) - assert.EqualValues(t, totalMessages-1, max) - assert.EqualValues(t, totalMessages, countSequence) -} - -func TestMessageFactory_POW(t *testing.T) { - msgFactory := New( - mapdb.NewMapDB(), - []byte(sequenceKey), - identity.GenerateLocalIdentity(), - TipSelectorFunc(func() (message.ID, message.ID) { return message.EmptyID, message.EmptyID }), - ) - defer msgFactory.Shutdown() - - worker := pow.New(crypto.BLAKE2b_512, 1) - - msgFactory.SetWorker(WorkerFunc(func(msgBytes []byte) (uint64, error) { - content := msgBytes[:len(msgBytes)-ed25519.SignatureSize-8] - return worker.Mine(context.Background(), content, targetPOW) - })) - - msg, err := msgFactory.IssuePayload(payload.NewData([]byte("test"))) - require.NoError(t, err) - - msgBytes := msg.Bytes() - content := msgBytes[:len(msgBytes)-ed25519.SignatureSize-8] - - zeroes, err := worker.LeadingZerosWithNonce(content, msg.Nonce()) - assert.GreaterOrEqual(t, zeroes, targetPOW) - assert.NoError(t, err) -} - -func TestWorkerFunc_PayloadSize(t *testing.T) { - msgFactory := New( - mapdb.NewMapDB(), - []byte(sequenceKey), - identity.GenerateLocalIdentity(), - TipSelectorFunc(func() (message.ID, message.ID) { return message.EmptyID, message.EmptyID }), - ) - defer msgFactory.Shutdown() - - // issue message with max allowed payload size - // dataPayload headers: type|32bit + size|32bit - data := make([]byte, payload.MaxPayloadSize-4-4) - msg, err := msgFactory.IssuePayload(payload.NewData(data)) - require.NoError(t, err) - assert.Truef(t, payload.MaxMessageSize == len(msg.Bytes()), "message size should be exactly %d bytes but is %d", payload.MaxMessageSize, len(msg.Bytes())) - - // issue message bigger than max allowed payload size - data = make([]byte, payload.MaxPayloadSize) - msg, err = msgFactory.IssuePayload(payload.NewData(data)) - require.Error(t, err) - assert.Nil(t, msg) -} diff --git a/packages/binary/messagelayer/messageparser/builtinfilters/message_signature_filter.go b/packages/binary/messagelayer/messageparser/builtinfilters/message_signature_filter.go deleted file mode 100644 index 02ba960c..00000000 --- a/packages/binary/messagelayer/messageparser/builtinfilters/message_signature_filter.go +++ /dev/null @@ -1,64 +0,0 @@ -package builtinfilters - -import ( - "fmt" - "sync" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/hive.go/autopeering/peer" -) - -// ErrInvalidSignature is returned when a message contains an invalid signature. -var ErrInvalidSignature = fmt.Errorf("invalid signature") - -// MessageSignatureFilter filters messages based on whether their signatures are valid. -type MessageSignatureFilter struct { - onAcceptCallback func(msg *message.Message, peer *peer.Peer) - onRejectCallback func(msg *message.Message, err error, peer *peer.Peer) - - onAcceptCallbackMutex sync.RWMutex - onRejectCallbackMutex sync.RWMutex -} - -// NewMessageSignatureFilter creates a new message signature filter. -func NewMessageSignatureFilter() *MessageSignatureFilter { - return &MessageSignatureFilter{} -} - -// Filter filters up on the given bytes and peer and calls the acceptance callback -// if the input passes or the rejection callback if the input is rejected. -func (filter *MessageSignatureFilter) Filter(msg *message.Message, peer *peer.Peer) { - if msg.VerifySignature() { - filter.getAcceptCallback()(msg, peer) - return - } - filter.getRejectCallback()(msg, ErrInvalidSignature, peer) -} - -// OnAccept registers the given callback as the acceptance function of the filter. -func (filter *MessageSignatureFilter) OnAccept(callback func(msg *message.Message, peer *peer.Peer)) { - filter.onAcceptCallbackMutex.Lock() - filter.onAcceptCallback = callback - filter.onAcceptCallbackMutex.Unlock() -} - -// OnReject registers the given callback as the rejection function of the filter. -func (filter *MessageSignatureFilter) OnReject(callback func(msg *message.Message, err error, peer *peer.Peer)) { - filter.onRejectCallbackMutex.Lock() - filter.onRejectCallback = callback - filter.onRejectCallbackMutex.Unlock() -} - -func (filter *MessageSignatureFilter) getAcceptCallback() (result func(msg *message.Message, peer *peer.Peer)) { - filter.onAcceptCallbackMutex.RLock() - result = filter.onAcceptCallback - filter.onAcceptCallbackMutex.RUnlock() - return -} - -func (filter *MessageSignatureFilter) getRejectCallback() (result func(msg *message.Message, err error, peer *peer.Peer)) { - filter.onRejectCallbackMutex.RLock() - result = filter.onRejectCallback - filter.onRejectCallbackMutex.RUnlock() - return -} diff --git a/packages/binary/messagelayer/messageparser/builtinfilters/pow_filter.go b/packages/binary/messagelayer/messageparser/builtinfilters/pow_filter.go deleted file mode 100644 index 0147ec37..00000000 --- a/packages/binary/messagelayer/messageparser/builtinfilters/pow_filter.go +++ /dev/null @@ -1,99 +0,0 @@ -package builtinfilters - -import ( - "crypto/ed25519" - "errors" - "fmt" - "sync" - - "github.com/iotaledger/goshimmer/packages/pow" - "github.com/iotaledger/hive.go/autopeering/peer" -) - -var ( - // ErrInvalidPOWDifficultly is returned when the nonce of a message does not fulfill the PoW difficulty. - ErrInvalidPOWDifficultly = errors.New("invalid PoW") - // ErrMessageTooSmall is returned when the message does not contain enough data for the PoW. - ErrMessageTooSmall = errors.New("message too small") -) - -// PowFilter is a message bytes filter validating the PoW nonce. -type PowFilter struct { - worker *pow.Worker - difficulty int - - mu sync.Mutex - acceptCallback func([]byte, *peer.Peer) - rejectCallback func([]byte, error, *peer.Peer) -} - -// NewPowFilter creates a new PoW bytes filter. -func NewPowFilter(worker *pow.Worker, difficulty int) *PowFilter { - return &PowFilter{ - worker: worker, - difficulty: difficulty, - } -} - -// Filter checks whether the given bytes pass the PoW validation and calls the corresponding callback. -func (f *PowFilter) Filter(msgBytes []byte, p *peer.Peer) { - if err := f.validate(msgBytes); err != nil { - f.reject(msgBytes, err, p) - return - } - f.accept(msgBytes, p) -} - -// OnAccept registers the given callback as the acceptance function of the filter. -func (f *PowFilter) OnAccept(callback func([]byte, *peer.Peer)) { - f.mu.Lock() - defer f.mu.Unlock() - f.acceptCallback = callback -} - -// OnReject registers the given callback as the rejection function of the filter. -func (f *PowFilter) OnReject(callback func([]byte, error, *peer.Peer)) { - f.mu.Lock() - defer f.mu.Unlock() - f.rejectCallback = callback -} - -func (f *PowFilter) accept(msgBytes []byte, p *peer.Peer) { - f.mu.Lock() - defer f.mu.Unlock() - if f.acceptCallback != nil { - f.acceptCallback(msgBytes, p) - } -} - -func (f *PowFilter) reject(msgBytes []byte, err error, p *peer.Peer) { - f.mu.Lock() - defer f.mu.Unlock() - if f.rejectCallback != nil { - f.rejectCallback(msgBytes, err, p) - } -} - -func (f *PowFilter) validate(msgBytes []byte) error { - content, err := powData(msgBytes) - if err != nil { - return err - } - zeros, err := f.worker.LeadingZeros(content) - if err != nil { - return err - } - if zeros < f.difficulty { - return fmt.Errorf("%w: leading zeros %d for difficulty %d", ErrInvalidPOWDifficultly, zeros, f.difficulty) - } - return nil -} - -// powData returns the bytes over which PoW should be computed. -func powData(msgBytes []byte) ([]byte, error) { - contentLength := len(msgBytes) - ed25519.SignatureSize - if contentLength < pow.NonceBytes { - return nil, ErrMessageTooSmall - } - return msgBytes[:contentLength], nil -} diff --git a/packages/binary/messagelayer/messageparser/builtinfilters/pow_filter_test.go b/packages/binary/messagelayer/messageparser/builtinfilters/pow_filter_test.go deleted file mode 100644 index aec79fdd..00000000 --- a/packages/binary/messagelayer/messageparser/builtinfilters/pow_filter_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package builtinfilters - -import ( - "context" - "crypto" - "errors" - "testing" - "time" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" - "github.com/iotaledger/goshimmer/packages/pow" - "github.com/iotaledger/hive.go/autopeering/peer" - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - _ "golang.org/x/crypto/blake2b" // required by crypto.BLAKE2b_512 -) - -var ( - testPayload = payload.NewData([]byte("test")) - testPeer *peer.Peer - testWorker = pow.New(crypto.BLAKE2b_512, 1) - testDifficulty = 10 -) - -func TestPowFilter_Filter(t *testing.T) { - filter := NewPowFilter(testWorker, testDifficulty) - - // set callbacks - m := &callbackMock{} - filter.OnAccept(m.Accept) - filter.OnReject(m.Reject) - - t.Run("reject small message", func(t *testing.T) { - m.On("Reject", mock.Anything, mock.MatchedBy(func(err error) bool { return errors.Is(err, ErrMessageTooSmall) }), testPeer) - filter.Filter(nil, testPeer) - }) - - msg := newTestMessage(0) - msgBytes := msg.Bytes() - - t.Run("reject invalid nonce", func(t *testing.T) { - m.On("Reject", msgBytes, mock.MatchedBy(func(err error) bool { return errors.Is(err, ErrInvalidPOWDifficultly) }), testPeer) - filter.Filter(msgBytes, testPeer) - }) - - nonce, err := testWorker.Mine(context.Background(), msgBytes[:len(msgBytes)-len(msg.Signature())-pow.NonceBytes], testDifficulty) - require.NoError(t, err) - - msgPOW := newTestMessage(nonce) - msgPOWBytes := msgPOW.Bytes() - - t.Run("accept valid nonce", func(t *testing.T) { - zeroes, err := testWorker.LeadingZeros(msgPOWBytes[:len(msgPOWBytes)-len(msgPOW.Signature())]) - require.NoError(t, err) - require.GreaterOrEqual(t, zeroes, testDifficulty) - - m.On("Accept", msgPOWBytes, testPeer) - filter.Filter(msgPOWBytes, testPeer) - }) - - m.AssertExpectations(t) -} - -type callbackMock struct{ mock.Mock } - -func (m *callbackMock) Accept(msg []byte, p *peer.Peer) { m.Called(msg, p) } -func (m *callbackMock) Reject(msg []byte, err error, p *peer.Peer) { m.Called(msg, err, p) } - -func newTestMessage(nonce uint64) *message.Message { - return message.New(message.EmptyID, message.EmptyID, time.Time{}, ed25519.PublicKey{}, 0, testPayload, nonce, ed25519.Signature{}) -} diff --git a/packages/binary/messagelayer/messageparser/builtinfilters/recently_seen_bytes_filter.go b/packages/binary/messagelayer/messageparser/builtinfilters/recently_seen_bytes_filter.go deleted file mode 100644 index 855d7942..00000000 --- a/packages/binary/messagelayer/messageparser/builtinfilters/recently_seen_bytes_filter.go +++ /dev/null @@ -1,67 +0,0 @@ -package builtinfilters - -import ( - "fmt" - "sync" - - "github.com/iotaledger/hive.go/autopeering/peer" - "github.com/iotaledger/hive.go/bytesfilter" -) - -// ErrReceivedDuplicateBytes is returned when duplicated bytes are rejected. -var ErrReceivedDuplicateBytes = fmt.Errorf("received duplicate bytes") - -// RecentlySeenBytesFilter filters so that bytes which were recently seen don't pass the filter. -type RecentlySeenBytesFilter struct { - bytesFilter *bytesfilter.BytesFilter - onAcceptCallback func(bytes []byte, peer *peer.Peer) - onRejectCallback func(bytes []byte, err error, peer *peer.Peer) - - onAcceptCallbackMutex sync.RWMutex - onRejectCallbackMutex sync.RWMutex -} - -// NewRecentlySeenBytesFilter creates a new recently seen bytes filter. -func NewRecentlySeenBytesFilter() *RecentlySeenBytesFilter { - return &RecentlySeenBytesFilter{ - bytesFilter: bytesfilter.New(100000), - } -} - -// Filter filters up on the given bytes and peer and calls the acceptance callback -// if the input passes or the rejection callback if the input is rejected. -func (filter *RecentlySeenBytesFilter) Filter(bytes []byte, peer *peer.Peer) { - if filter.bytesFilter.Add(bytes) { - filter.getAcceptCallback()(bytes, peer) - return - } - filter.getRejectCallback()(bytes, ErrReceivedDuplicateBytes, peer) -} - -// OnAccept registers the given callback as the acceptance function of the filter. -func (filter *RecentlySeenBytesFilter) OnAccept(callback func(bytes []byte, peer *peer.Peer)) { - filter.onAcceptCallbackMutex.Lock() - filter.onAcceptCallback = callback - filter.onAcceptCallbackMutex.Unlock() -} - -// OnReject registers the given callback as the rejection function of the filter. -func (filter *RecentlySeenBytesFilter) OnReject(callback func(bytes []byte, err error, peer *peer.Peer)) { - filter.onRejectCallbackMutex.Lock() - filter.onRejectCallback = callback - filter.onRejectCallbackMutex.Unlock() -} - -func (filter *RecentlySeenBytesFilter) getAcceptCallback() (result func(bytes []byte, peer *peer.Peer)) { - filter.onAcceptCallbackMutex.Lock() - result = filter.onAcceptCallback - filter.onAcceptCallbackMutex.Unlock() - return -} - -func (filter *RecentlySeenBytesFilter) getRejectCallback() (result func(bytes []byte, err error, peer *peer.Peer)) { - filter.onRejectCallbackMutex.Lock() - result = filter.onRejectCallback - filter.onRejectCallbackMutex.Unlock() - return -} diff --git a/packages/binary/messagelayer/messageparser/bytes_filter.go b/packages/binary/messagelayer/messageparser/bytes_filter.go deleted file mode 100644 index 7c62a459..00000000 --- a/packages/binary/messagelayer/messageparser/bytes_filter.go +++ /dev/null @@ -1,16 +0,0 @@ -package messageparser - -import ( - "github.com/iotaledger/hive.go/autopeering/peer" -) - -// BytesFilter filters based on byte slices and peers. -type BytesFilter interface { - // Filter filters up on the given bytes and peer and calls the acceptance callback - // if the input passes or the rejection callback if the input is rejected. - Filter(bytes []byte, peer *peer.Peer) - // OnAccept registers the given callback as the acceptance function of the filter. - OnAccept(callback func(bytes []byte, peer *peer.Peer)) - // OnReject registers the given callback as the rejection function of the filter. - OnReject(callback func(bytes []byte, err error, peer *peer.Peer)) -} diff --git a/packages/binary/messagelayer/messageparser/events.go b/packages/binary/messagelayer/messageparser/events.go deleted file mode 100644 index b10316d0..00000000 --- a/packages/binary/messagelayer/messageparser/events.go +++ /dev/null @@ -1,55 +0,0 @@ -package messageparser - -import ( - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/hive.go/autopeering/peer" - "github.com/iotaledger/hive.go/events" -) - -// Events represents events happening on a message parser. -type Events struct { - // Fired when a message was parsed. - MessageParsed *events.Event - // Fired when submitted bytes are rejected by a filter. - BytesRejected *events.Event - // Fired when a message got rejected by a filter. - MessageRejected *events.Event -} - -// MessageParsedEvent represents the parameters of messageParsedEvent -type MessageParsedEvent struct { - Message *message.Message - Peer *peer.Peer -} - -// BytesRejectedEvent represents the parameters of bytesRejectedEvent -type BytesRejectedEvent struct { - Bytes []byte - Peer *peer.Peer -} - -// MessageRejectedEvent represents the parameters of messageRejectedEvent -type MessageRejectedEvent struct { - Message *message.Message - Peer *peer.Peer -} - -func newEvents() *Events { - return &Events{ - MessageParsed: events.NewEvent(messageParsedEvent), - BytesRejected: events.NewEvent(bytesRejectedEvent), - MessageRejected: events.NewEvent(messageRejectedEvent), - } -} - -func messageParsedEvent(handler interface{}, params ...interface{}) { - handler.(func(*MessageParsedEvent))(params[0].(*MessageParsedEvent)) -} - -func bytesRejectedEvent(handler interface{}, params ...interface{}) { - handler.(func(*BytesRejectedEvent, error))(params[0].(*BytesRejectedEvent), params[1].(error)) -} - -func messageRejectedEvent(handler interface{}, params ...interface{}) { - handler.(func(*MessageRejectedEvent, error))(params[0].(*MessageRejectedEvent), params[1].(error)) -} diff --git a/packages/binary/messagelayer/messageparser/message_filter.go b/packages/binary/messagelayer/messageparser/message_filter.go deleted file mode 100644 index b883f3d1..00000000 --- a/packages/binary/messagelayer/messageparser/message_filter.go +++ /dev/null @@ -1,18 +0,0 @@ -package messageparser - -import ( - "github.com/iotaledger/hive.go/autopeering/peer" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" -) - -// MessageFilter filters based on messages and peers. -type MessageFilter interface { - // Filter filters up on the given message and peer and calls the acceptance callback - // if the input passes or the rejection callback if the input is rejected. - Filter(msg *message.Message, peer *peer.Peer) - // OnAccept registers the given callback as the acceptance function of the filter. - OnAccept(callback func(msg *message.Message, peer *peer.Peer)) - // OnAccept registers the given callback as the rejection function of the filter. - OnReject(callback func(msg *message.Message, err error, peer *peer.Peer)) -} diff --git a/packages/binary/messagelayer/messageparser/message_parser.go b/packages/binary/messagelayer/messageparser/message_parser.go deleted file mode 100644 index 05c4f5c0..00000000 --- a/packages/binary/messagelayer/messageparser/message_parser.go +++ /dev/null @@ -1,129 +0,0 @@ -package messageparser - -import ( - "sync" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messageparser/builtinfilters" - - "github.com/iotaledger/hive.go/autopeering/peer" - "github.com/iotaledger/hive.go/typeutils" -) - -// MessageParser parses messages and bytes and emits corresponding events for parsed and rejected messages. -type MessageParser struct { - bytesFilters []BytesFilter - messageFilters []MessageFilter - Events *Events - - byteFiltersModified typeutils.AtomicBool - messageFiltersModified typeutils.AtomicBool - bytesFiltersMutex sync.Mutex - messageFiltersMutex sync.Mutex -} - -// New creates a new message parser. -func New() (result *MessageParser) { - result = &MessageParser{ - bytesFilters: make([]BytesFilter, 0), - messageFilters: make([]MessageFilter, 0), - Events: newEvents(), - } - - // add builtin filters - result.AddBytesFilter(builtinfilters.NewRecentlySeenBytesFilter()) - result.AddMessageFilter(builtinfilters.NewMessageSignatureFilter()) - return -} - -// Parse parses the given message bytes. -func (messageParser *MessageParser) Parse(messageBytes []byte, peer *peer.Peer) { - messageParser.setupBytesFilterDataFlow() - messageParser.setupMessageFilterDataFlow() - messageParser.bytesFilters[0].Filter(messageBytes, peer) -} - -// AddBytesFilter adds the given bytes filter to the parser. -func (messageParser *MessageParser) AddBytesFilter(filter BytesFilter) { - messageParser.bytesFiltersMutex.Lock() - messageParser.bytesFilters = append(messageParser.bytesFilters, filter) - messageParser.bytesFiltersMutex.Unlock() - messageParser.byteFiltersModified.Set() -} - -// AddMessageFilter adds a new message filter to the parser. -func (messageParser *MessageParser) AddMessageFilter(filter MessageFilter) { - messageParser.messageFiltersMutex.Lock() - messageParser.messageFilters = append(messageParser.messageFilters, filter) - messageParser.messageFiltersMutex.Unlock() - messageParser.messageFiltersModified.Set() -} - -// sets up the byte filter data flow chain. -func (messageParser *MessageParser) setupBytesFilterDataFlow() { - if !messageParser.byteFiltersModified.IsSet() { - return - } - - messageParser.bytesFiltersMutex.Lock() - if messageParser.byteFiltersModified.IsSet() { - messageParser.byteFiltersModified.SetTo(false) - - numberOfBytesFilters := len(messageParser.bytesFilters) - for i := 0; i < numberOfBytesFilters; i++ { - if i == numberOfBytesFilters-1 { - messageParser.bytesFilters[i].OnAccept(messageParser.parseMessage) - } else { - messageParser.bytesFilters[i].OnAccept(messageParser.bytesFilters[i+1].Filter) - } - messageParser.bytesFilters[i].OnReject(func(bytes []byte, err error, peer *peer.Peer) { - messageParser.Events.BytesRejected.Trigger(&BytesRejectedEvent{ - Bytes: bytes, - Peer: peer}, err) - }) - } - } - messageParser.bytesFiltersMutex.Unlock() -} - -// sets up the message filter data flow chain. -func (messageParser *MessageParser) setupMessageFilterDataFlow() { - if !messageParser.messageFiltersModified.IsSet() { - return - } - - messageParser.messageFiltersMutex.Lock() - if messageParser.messageFiltersModified.IsSet() { - messageParser.messageFiltersModified.SetTo(false) - - numberOfMessageFilters := len(messageParser.messageFilters) - for i := 0; i < numberOfMessageFilters; i++ { - if i == numberOfMessageFilters-1 { - messageParser.messageFilters[i].OnAccept(func(msg *message.Message, peer *peer.Peer) { - messageParser.Events.MessageParsed.Trigger(&MessageParsedEvent{ - Message: msg, - Peer: peer}) - }) - } else { - messageParser.messageFilters[i].OnAccept(messageParser.messageFilters[i+1].Filter) - } - messageParser.messageFilters[i].OnReject(func(msg *message.Message, err error, peer *peer.Peer) { - messageParser.Events.MessageRejected.Trigger(&MessageRejectedEvent{ - Message: msg, - Peer: peer}, err) - }) - } - } - messageParser.messageFiltersMutex.Unlock() -} - -// parses the given message and emits -func (messageParser *MessageParser) parseMessage(bytes []byte, peer *peer.Peer) { - if parsedMessage, _, err := message.FromBytes(bytes); err != nil { - messageParser.Events.BytesRejected.Trigger(&BytesRejectedEvent{ - Bytes: bytes, - Peer: peer}, err) - } else { - messageParser.messageFilters[0].Filter(parsedMessage, peer) - } -} diff --git a/packages/binary/messagelayer/messageparser/message_parser_test.go b/packages/binary/messagelayer/messageparser/message_parser_test.go deleted file mode 100644 index fe0ab7fb..00000000 --- a/packages/binary/messagelayer/messageparser/message_parser_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package messageparser - -import ( - "strconv" - "testing" - "time" - - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/hive.go/events" - "github.com/labstack/gommon/log" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" -) - -func BenchmarkMessageParser_ParseBytesSame(b *testing.B) { - msgBytes := newTestMessage("Test").Bytes() - msgParser := New() - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - msgParser.Parse(msgBytes, nil) - } -} - -func BenchmarkMessageParser_ParseBytesDifferent(b *testing.B) { - messageBytes := make([][]byte, b.N) - for i := 0; i < b.N; i++ { - messageBytes[i] = newTestMessage("Test" + strconv.Itoa(i)).Bytes() - } - - msgParser := New() - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - msgParser.Parse(messageBytes[i], nil) - } -} - -func TestMessageParser_ParseMessage(t *testing.T) { - msg := newTestMessage("Test") - - msgParser := New() - msgParser.Parse(msg.Bytes(), nil) - - msgParser.Events.MessageParsed.Attach(events.NewClosure(func(msgParsedEvent *MessageParsedEvent) { - log.Infof("parsed message") - })) -} - -func newTestMessage(payloadString string) *message.Message { - return message.New(message.EmptyID, message.EmptyID, time.Now(), ed25519.PublicKey{}, 0, payload.NewData([]byte(payloadString)), 0, ed25519.Signature{}) -} diff --git a/packages/binary/messagelayer/messagerequester/constants.go b/packages/binary/messagelayer/messagerequester/constants.go deleted file mode 100644 index 7d26d3e9..00000000 --- a/packages/binary/messagelayer/messagerequester/constants.go +++ /dev/null @@ -1,10 +0,0 @@ -package messagerequester - -import ( - "time" -) - -const ( - // DefaultRetryInterval defines the Default Retry Interval of the message requester. - DefaultRetryInterval = 10 * time.Second -) diff --git a/packages/binary/messagelayer/messagerequester/events.go b/packages/binary/messagelayer/messagerequester/events.go deleted file mode 100644 index 74465a1b..00000000 --- a/packages/binary/messagelayer/messagerequester/events.go +++ /dev/null @@ -1,39 +0,0 @@ -package messagerequester - -import ( - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/hive.go/events" -) - -// Events represents events happening on a message requester. -type Events struct { - // Fired when a request for a given message should be sent. - SendRequest *events.Event - // MissingMessageAppeared is triggered when a message is actually present in the node's db although it was still being requested. - MissingMessageAppeared *events.Event -} - -// SendRequestEvent represents the parameters of sendRequestEvent -type SendRequestEvent struct { - ID message.ID -} - -// MissingMessageAppearedEvent represents the parameters of missingMessageAppearedEvent -type MissingMessageAppearedEvent struct { - ID message.ID -} - -func newEvents() *Events { - return &Events{ - SendRequest: events.NewEvent(sendRequestEvent), - MissingMessageAppeared: events.NewEvent(missingMessageAppearedEvent), - } -} - -func sendRequestEvent(handler interface{}, params ...interface{}) { - handler.(func(*SendRequestEvent))(params[0].(*SendRequestEvent)) -} - -func missingMessageAppearedEvent(handler interface{}, params ...interface{}) { - handler.(func(*MissingMessageAppearedEvent))(params[0].(*MissingMessageAppearedEvent)) -} diff --git a/packages/binary/messagelayer/messagerequester/messagerequester.go b/packages/binary/messagelayer/messagerequester/messagerequester.go deleted file mode 100644 index a6ba7312..00000000 --- a/packages/binary/messagelayer/messagerequester/messagerequester.go +++ /dev/null @@ -1,104 +0,0 @@ -package messagerequester - -import ( - "sync" - "time" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" -) - -// the maximum amount of requests before we abort -const maxRequestThreshold = 500 - -// MessageRequester takes care of requesting messages. -type MessageRequester struct { - scheduledRequests map[message.ID]*time.Timer - options *Options - Events *Events - - scheduledRequestsMutex sync.RWMutex -} - -// MessageExistsFunc is a function that tells if a message exists. -type MessageExistsFunc func(messageId message.ID) bool - -// New creates a new message requester. -func New(missingMessages []message.ID, optionalOptions ...Option) *MessageRequester { - requester := &MessageRequester{ - scheduledRequests: make(map[message.ID]*time.Timer), - options: newOptions(optionalOptions), - Events: newEvents(), - } - - // add requests for all missing messages - requester.scheduledRequestsMutex.Lock() - defer requester.scheduledRequestsMutex.Unlock() - - for _, id := range missingMessages { - requester.scheduledRequests[id] = time.AfterFunc(requester.options.retryInterval, requester.createReRequest(id, 0)) - } - - return requester -} - -// StartRequest initiates a regular triggering of the StartRequest event until it has been stopped using StopRequest. -func (requester *MessageRequester) StartRequest(id message.ID) { - requester.scheduledRequestsMutex.Lock() - - // ignore already scheduled requests - if _, exists := requester.scheduledRequests[id]; exists { - requester.scheduledRequestsMutex.Unlock() - return - } - - // schedule the next request and trigger the event - requester.scheduledRequests[id] = time.AfterFunc(requester.options.retryInterval, requester.createReRequest(id, 0)) - requester.scheduledRequestsMutex.Unlock() - requester.Events.SendRequest.Trigger(&SendRequestEvent{ID: id}) -} - -// StopRequest stops requests for the given message to further happen. -func (requester *MessageRequester) StopRequest(id message.ID) { - requester.scheduledRequestsMutex.Lock() - defer requester.scheduledRequestsMutex.Unlock() - - if timer, ok := requester.scheduledRequests[id]; ok { - timer.Stop() - delete(requester.scheduledRequests, id) - } -} - -func (requester *MessageRequester) reRequest(id message.ID, count int) { - requester.Events.SendRequest.Trigger(&SendRequestEvent{ID: id}) - - // as we schedule a request at most once per id we do not need to make the trigger and the re-schedule atomic - requester.scheduledRequestsMutex.Lock() - defer requester.scheduledRequestsMutex.Unlock() - - // reschedule, if the request has not been stopped in the meantime - if _, exists := requester.scheduledRequests[id]; exists { - // increase the request counter - count++ - - // if we have requested too often => stop the requests - if count > maxRequestThreshold { - delete(requester.scheduledRequests, id) - - return - } - - requester.scheduledRequests[id] = time.AfterFunc(requester.options.retryInterval, requester.createReRequest(id, count)) - return - } -} - -// RequestQueueSize returns the number of scheduled message requests. -func (requester *MessageRequester) RequestQueueSize() int { - requester.scheduledRequestsMutex.RLock() - defer requester.scheduledRequestsMutex.RUnlock() - return len(requester.scheduledRequests) -} - -func (requester *MessageRequester) createReRequest(msgID message.ID, count int) func() { - return func() { requester.reRequest(msgID, count) } -} diff --git a/packages/binary/messagelayer/messagerequester/options.go b/packages/binary/messagelayer/messagerequester/options.go deleted file mode 100644 index 81611814..00000000 --- a/packages/binary/messagelayer/messagerequester/options.go +++ /dev/null @@ -1,32 +0,0 @@ -package messagerequester - -import ( - "time" -) - -// Options holds options for a message requester. -type Options struct { - retryInterval time.Duration -} - -func newOptions(optionalOptions []Option) *Options { - result := &Options{ - retryInterval: 10 * time.Second, - } - - for _, optionalOption := range optionalOptions { - optionalOption(result) - } - - return result -} - -// Option is a function which inits an option. -type Option func(*Options) - -// RetryInterval creates an option which sets the retry interval to the given value. -func RetryInterval(interval time.Duration) Option { - return func(args *Options) { - args.retryInterval = interval - } -} diff --git a/packages/binary/messagelayer/payload/data.go b/packages/binary/messagelayer/payload/data.go deleted file mode 100644 index 6623a7f5..00000000 --- a/packages/binary/messagelayer/payload/data.go +++ /dev/null @@ -1,90 +0,0 @@ -package payload - -import ( - "github.com/iotaledger/hive.go/marshalutil" - "github.com/iotaledger/hive.go/stringify" -) - -// DataType is the message type of a data payload. -var DataType = Type(0) - -// Data represents a payload which just contains a blob of data. -type Data struct { - payloadType Type - data []byte -} - -// NewData creates new data payload. -func NewData(data []byte) *Data { - return &Data{ - payloadType: DataType, - data: data, - } -} - -// DataFromBytes creates a new data payload from the given bytes. -func DataFromBytes(bytes []byte) (result *Data, consumedBytes int, err error) { - marshalUtil := marshalutil.New(bytes) - result, err = ParseData(marshalUtil) - consumedBytes = marshalUtil.ReadOffset() - - return -} - -// ParseData parses a new data payload out of the given marshal util. -func ParseData(marshalUtil *marshalutil.MarshalUtil) (result *Data, err error) { - // parse information - result = &Data{} - payloadBytes, err := marshalUtil.ReadUint32() - if err != nil { - return - } - result.payloadType, err = marshalUtil.ReadUint32() - if err != nil { - return - } - result.data, err = marshalUtil.ReadBytes(int(payloadBytes)) - if err != nil { - return - } - - return -} - -// Type returns the payload type. -func (dataPayload *Data) Type() Type { - return dataPayload.payloadType -} - -// Data returns the data of the data payload. -func (dataPayload *Data) Data() []byte { - return dataPayload.data -} - -// Bytes marshals the data payload into a sequence of bytes. -func (dataPayload *Data) Bytes() []byte { - // initialize helper - marshalUtil := marshalutil.New() - - // marshal the payload specific information - marshalUtil.WriteUint32(uint32(len(dataPayload.data))) - marshalUtil.WriteUint32(dataPayload.Type()) - marshalUtil.WriteBytes(dataPayload.data[:]) - - // return result - return marshalUtil.Bytes() -} - -func (dataPayload *Data) String() string { - return stringify.Struct("Data", - stringify.StructField("type", int(dataPayload.Type())), - stringify.StructField("data", string(dataPayload.Data())), - ) -} - -// GenericPayloadUnmarshaler is an unmarshaler for the generic data payload type. -func GenericPayloadUnmarshaler(data []byte) (payload Payload, err error) { - payload, _, err = DataFromBytes(data) - - return -} diff --git a/packages/binary/messagelayer/payload/id.go b/packages/binary/messagelayer/payload/id.go deleted file mode 100644 index ca5bc407..00000000 --- a/packages/binary/messagelayer/payload/id.go +++ /dev/null @@ -1,19 +0,0 @@ -package payload - -import "github.com/mr-tron/base58" - -// ID represents the id of a data payload. -type ID [IDLength]byte - -// Bytes returns the id as a byte slice backed by the original array, -// therefore it should not be modified. -func (id ID) Bytes() []byte { - return id[:] -} - -func (id ID) String() string { - return base58.Encode(id[:]) -} - -// IDLength is the length of a data payload id. -const IDLength = 64 diff --git a/packages/binary/messagelayer/payload/payload.go b/packages/binary/messagelayer/payload/payload.go deleted file mode 100644 index bdf235ec..00000000 --- a/packages/binary/messagelayer/payload/payload.go +++ /dev/null @@ -1,97 +0,0 @@ -package payload - -import ( - "fmt" - - "github.com/iotaledger/hive.go/marshalutil" -) - -const ( - // ObjectName defines the name of the data object. - ObjectName = "data" - - // MaxMessageSize defines the maximum size of a message. - MaxMessageSize = 64 * 1024 - - // MaxPayloadSize defines the maximum size of a payload. - // parent1ID + parent2ID + issuerPublicKey + issuingTime + sequenceNumber + nonce + signature - MaxPayloadSize = MaxMessageSize - 64 - 64 - 32 - 8 - 8 - 8 - 64 -) - -var ( - // ErrMaxPayloadSizeExceeded is returned if the maximum payload size is exceeded. - ErrMaxPayloadSizeExceeded = fmt.Errorf("maximum payload size of %d bytes exceeded", MaxPayloadSize) -) - -func init() { - // register the generic unmarshaler - SetGenericUnmarshaler(GenericPayloadUnmarshaler) - - // register the generic data payload type - RegisterType(DataType, ObjectName, GenericPayloadUnmarshaler) -} - -// Payload represents some kind of payload of data which only gains meaning by having -// corresponding node logic processing payloads of a given type. -type Payload interface { - // Type returns the type of the payload. - Type() Type - - // Bytes returns the payload bytes. - Bytes() []byte - - // String returns a human-friendly representation of the payload. - String() string -} - -// FromBytes unmarshals bytes into a payload. -func FromBytes(bytes []byte) (result Payload, consumedBytes int, err error) { - // initialize helper - marshalUtil := marshalutil.New(bytes) - - // calculate result - payloadSize, err := marshalUtil.ReadUint32() - if err != nil { - return - } - - if payloadSize > MaxPayloadSize { - err = fmt.Errorf("%w: %d", ErrMaxPayloadSizeExceeded, payloadSize) - return - } - - payloadType, err := marshalUtil.ReadUint32() - if err != nil { - return - } - - marshalUtil.ReadSeek(marshalUtil.ReadOffset() - marshalutil.UINT32_SIZE*2) - payloadBytes, err := marshalUtil.ReadBytes(int(payloadSize) + 8) - if err != nil { - return - } - - readOffset := marshalUtil.ReadOffset() - result, err = GetUnmarshaler(payloadType)(payloadBytes) - if err != nil { - // fallback to the generic unmarshaler if registered type fails to unmarshal - marshalUtil.ReadSeek(readOffset) - result, err = genericUnmarshaler(payloadBytes) - if err != nil { - return - } - } - - // return the number of bytes we processed - consumedBytes = marshalUtil.ReadOffset() - return -} - -// Parse parses a payload by using the given marshal util. -func Parse(marshalUtil *marshalutil.MarshalUtil) (Payload, error) { - payload, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return FromBytes(data) }) - if err != nil { - return nil, err - } - return payload.(Payload), nil -} diff --git a/packages/binary/messagelayer/payload/type.go b/packages/binary/messagelayer/payload/type.go deleted file mode 100644 index 4f2241bd..00000000 --- a/packages/binary/messagelayer/payload/type.go +++ /dev/null @@ -1,4 +0,0 @@ -package payload - -// Type represents the type id of a payload. -type Type = uint32 diff --git a/packages/binary/messagelayer/payload/type_register.go b/packages/binary/messagelayer/payload/type_register.go deleted file mode 100644 index 728119f2..00000000 --- a/packages/binary/messagelayer/payload/type_register.go +++ /dev/null @@ -1,58 +0,0 @@ -package payload - -import ( - "sync" -) - -// Unmarshaler takes some data and unmarshals it into a payload. -type Unmarshaler func(data []byte) (Payload, error) - -// Definition defines the properties of a payload type. -type Definition struct { - Name string - Unmarshaler -} - -var ( - typeRegister = make(map[Type]Definition) - typeRegisterMutex sync.RWMutex - genericUnmarshaler Unmarshaler -) - -// RegisterType registers a payload type with the given unmarshaler. -func RegisterType(payloadType Type, payloadName string, unmarshaler Unmarshaler) { - typeRegisterMutex.Lock() - typeRegister[payloadType] = Definition{ - Name: payloadName, - Unmarshaler: unmarshaler, - } - typeRegisterMutex.Unlock() -} - -// GetUnmarshaler returns the unmarshaler for the given type if known or -// the generic unmarshaler if the given payload type has no associated unmarshaler. -func GetUnmarshaler(payloadType Type) Unmarshaler { - typeRegisterMutex.RLock() - defer typeRegisterMutex.RUnlock() - - if definition, exists := typeRegister[payloadType]; exists { - return definition.Unmarshaler - } - - return genericUnmarshaler -} - -// SetGenericUnmarshaler sets the generic unmarshaler. -func SetGenericUnmarshaler(unmarshaler Unmarshaler) { - genericUnmarshaler = unmarshaler -} - -// Name returns the name of a given payload type. -func Name(payloadType Type) string { - typeRegisterMutex.RLock() - defer typeRegisterMutex.RUnlock() - if definition, exists := typeRegister[payloadType]; exists { - return definition.Name - } - return ObjectName -} diff --git a/packages/binary/messagelayer/tangle/approver.go b/packages/binary/messagelayer/tangle/approver.go deleted file mode 100644 index e5d162de..00000000 --- a/packages/binary/messagelayer/tangle/approver.go +++ /dev/null @@ -1,147 +0,0 @@ -package tangle - -import ( - "github.com/iotaledger/hive.go/marshalutil" - "github.com/iotaledger/hive.go/objectstorage" - "github.com/iotaledger/hive.go/stringify" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" -) - -// Approver is an approver of a given referenced message. -type Approver struct { - objectstorage.StorableObjectFlags - // the message which got referenced by the approver message. - referencedMessageID message.ID - // the message which approved/referenced the given referenced message. - approverMessageID message.ID -} - -// NewApprover creates a new approver relation to the given approved/referenced message. -func NewApprover(referencedMessageID message.ID, approverMessageID message.ID) *Approver { - approver := &Approver{ - referencedMessageID: referencedMessageID, - approverMessageID: approverMessageID, - } - return approver -} - -// ApproverFromBytes parses the given bytes into an approver. -func ApproverFromBytes(bytes []byte) (result *Approver, consumedBytes int, err error) { - marshalUtil := marshalutil.New(bytes) - result, err = ParseApprover(marshalUtil) - consumedBytes = marshalUtil.ReadOffset() - return -} - -// ParseApprover parses a new approver from the given marshal util. -func ParseApprover(marshalUtil *marshalutil.MarshalUtil) (result *Approver, err error) { - result = &Approver{} - - if result.referencedMessageID, err = message.ParseID(marshalUtil); err != nil { - return - } - if result.approverMessageID, err = message.ParseID(marshalUtil); err != nil { - return - } - - return -} - -// ApproverFromObjectStorage returns an approver for the given key. -func ApproverFromObjectStorage(key []byte, _ []byte) (result objectstorage.StorableObject, err error) { - result, _, err = ApproverFromBytes(key) - - return -} - -// ReferencedMessageID returns the ID of the message which is referenced by the approver. -func (approver *Approver) ReferencedMessageID() message.ID { - return approver.referencedMessageID -} - -// ApproverMessageID returns the ID of the message which referenced the given approved message. -func (approver *Approver) ApproverMessageID() message.ID { - return approver.approverMessageID -} - -// Bytes returns the bytes of the approver. -func (approver *Approver) Bytes() []byte { - return approver.ObjectStorageKey() -} - -// String returns the string representation of the approver. -func (approver *Approver) String() string { - return stringify.Struct("Approver", - stringify.StructField("referencedMessageID", approver.ReferencedMessageID()), - stringify.StructField("approverMessageID", approver.ApproverMessageID()), - ) -} - -// ObjectStorageKey marshals the keys of the stored approver into a byte array. -// This includes the referencedMessageID and the approverMessageID. -func (approver *Approver) ObjectStorageKey() []byte { - return marshalutil.New(). - WriteBytes(approver.referencedMessageID.Bytes()). - WriteBytes(approver.approverMessageID.Bytes()). - Bytes() -} - -// ObjectStorageValue returns the value of the stored approver object. -func (approver *Approver) ObjectStorageValue() (result []byte) { - return -} - -// Update updates the approver. -// This should should never happen and will panic if attempted. -func (approver *Approver) Update(other objectstorage.StorableObject) { - panic("approvers should never be overwritten and only stored once to optimize IO") -} - -// interface contract (allow the compiler to check if the implementation has all of the required methods). -var _ objectstorage.StorableObject = &Approver{} - -// CachedApprover is a wrapper for a stored cached object representing an approver. -type CachedApprover struct { - objectstorage.CachedObject -} - -// Unwrap unwraps the cached approver into the underlying approver. -// If stored object cannot be cast into an approver or has been deleted, it returns nil. -func (cachedApprover *CachedApprover) Unwrap() *Approver { - untypedObject := cachedApprover.Get() - if untypedObject == nil { - return nil - } - - typedObject := untypedObject.(*Approver) - if typedObject == nil || typedObject.IsDeleted() { - return nil - } - - return typedObject - -} - -// Consume consumes the cachedApprover. -// It releases the object when the callback is done. -// It returns true if the callback was called. -func (cachedApprover *CachedApprover) Consume(consumer func(approver *Approver)) (consumed bool) { - return cachedApprover.CachedObject.Consume(func(object objectstorage.StorableObject) { - consumer(object.(*Approver)) - }) -} - -// CachedApprovers defines a slice of *CachedApprover. -type CachedApprovers []*CachedApprover - -// Consume calls *CachedApprover.Consume on element in the list. -func (cachedApprovers CachedApprovers) Consume(consumer func(approver *Approver)) (consumed bool) { - for _, cachedApprover := range cachedApprovers { - consumed = cachedApprover.Consume(func(approver *Approver) { - consumer(approver) - }) || consumed - } - - return -} diff --git a/packages/binary/messagelayer/tangle/events.go b/packages/binary/messagelayer/tangle/events.go deleted file mode 100644 index 4799082b..00000000 --- a/packages/binary/messagelayer/tangle/events.go +++ /dev/null @@ -1,57 +0,0 @@ -package tangle - -import ( - "github.com/iotaledger/hive.go/events" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" -) - -// Events represents events happening on the base layer Tangle. -type Events struct { - // Fired when a message has been attached. - MessageAttached *events.Event - // Fired when a message has been solid, i.e. its past cone - // is known and in the database. - MessageSolid *events.Event - // Fired when a message which was previously marked as missing was received. - MissingMessageReceived *events.Event - // Fired when a message is missing which is needed to solidify a given approver message. - MessageMissing *events.Event - // Fired when a message was missing for too long and is - // therefore considered to be unsolidifiable. - MessageUnsolidifiable *events.Event - // Fired when a message was removed from storage. - MessageRemoved *events.Event -} - -// CachedMessageEvent represents the parameters of cachedMessageEvent -type CachedMessageEvent struct { - Message *message.CachedMessage - MessageMetadata *CachedMessageMetadata -} - -func newEvents() *Events { - return &Events{ - MessageAttached: events.NewEvent(cachedMessageEvent), - MessageSolid: events.NewEvent(cachedMessageEvent), - MissingMessageReceived: events.NewEvent(cachedMessageEvent), - MessageMissing: events.NewEvent(messageIDEvent), - MessageUnsolidifiable: events.NewEvent(messageIDEvent), - MessageRemoved: events.NewEvent(messageIDEvent), - } -} - -func messageIDEvent(handler interface{}, params ...interface{}) { - handler.(func(message.ID))(params[0].(message.ID)) -} - -func cachedMessageEvent(handler interface{}, params ...interface{}) { - handler.(func(*CachedMessageEvent))(cachedMessageRetain(params[0].(*CachedMessageEvent))) -} - -func cachedMessageRetain(object *CachedMessageEvent) *CachedMessageEvent { - return &CachedMessageEvent{ - Message: object.Message.Retain(), - MessageMetadata: object.MessageMetadata.Retain(), - } -} diff --git a/packages/binary/messagelayer/tangle/messagemetadata.go b/packages/binary/messagelayer/tangle/messagemetadata.go deleted file mode 100644 index 840d1837..00000000 --- a/packages/binary/messagelayer/tangle/messagemetadata.go +++ /dev/null @@ -1,177 +0,0 @@ -package tangle - -import ( - "sync" - "time" - - "github.com/iotaledger/hive.go/byteutils" - "github.com/iotaledger/hive.go/marshalutil" - "github.com/iotaledger/hive.go/objectstorage" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" -) - -// MessageMetadata defines the metadata for a message. -type MessageMetadata struct { - objectstorage.StorableObjectFlags - - messageID message.ID - receivedTime time.Time - solid bool - solidificationTime time.Time - - solidMutex sync.RWMutex - solidificationTimeMutex sync.RWMutex -} - -// NewMessageMetadata creates a new MessageMetadata from the specified messageID. -func NewMessageMetadata(messageID message.ID) *MessageMetadata { - return &MessageMetadata{ - messageID: messageID, - receivedTime: time.Now(), - } -} - -// MessageMetadataFromBytes unmarshals the given bytes into a MessageMetadata. -func MessageMetadataFromBytes(bytes []byte) (result *MessageMetadata, consumedBytes int, err error) { - marshalUtil := marshalutil.New(bytes) - result, err = ParseMessageMetadata(marshalUtil) - consumedBytes = marshalUtil.ReadOffset() - - return -} - -// ParseMessageMetadata parses the marshalUtil into a MessageMetadata. -// If it successfully parses the marshalUtil, it delegates to MessageMetadataFromObjectStorage. -// Else, delegates to UnmarshalObjectStorageValue. -func ParseMessageMetadata(marshalUtil *marshalutil.MarshalUtil) (result *MessageMetadata, err error) { - result = &MessageMetadata{} - - if result.messageID, err = message.ParseID(marshalUtil); err != nil { - return - } - if result.receivedTime, err = marshalUtil.ReadTime(); err != nil { - return - } - if result.solidificationTime, err = marshalUtil.ReadTime(); err != nil { - return - } - if result.solid, err = marshalUtil.ReadBool(); err != nil { - return - } - - return -} - -// MessageMetadataFromObjectStorage unmarshals the stored bytes into a MessageMetadata. -func MessageMetadataFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) { - if result, _, err = MessageMetadataFromBytes(byteutils.ConcatBytes(key, data)); err != nil { - return - } - - return -} - -// ReceivedTime returns the time when the message was received. -func (messageMetadata *MessageMetadata) ReceivedTime() time.Time { - return messageMetadata.receivedTime -} - -// IsSolid returns true if the message represented by this metadata is solid. False otherwise. -func (messageMetadata *MessageMetadata) IsSolid() (result bool) { - messageMetadata.solidMutex.RLock() - result = messageMetadata.solid - messageMetadata.solidMutex.RUnlock() - - return -} - -// SetSolid sets the message associated with this metadata as solid. -// It returns true if the solid status is modified. False otherwise. -func (messageMetadata *MessageMetadata) SetSolid(solid bool) (modified bool) { - messageMetadata.solidMutex.RLock() - if messageMetadata.solid != solid { - messageMetadata.solidMutex.RUnlock() - - messageMetadata.solidMutex.Lock() - if messageMetadata.solid != solid { - messageMetadata.solid = solid - if solid { - messageMetadata.solidificationTimeMutex.Lock() - messageMetadata.solidificationTime = time.Now() - messageMetadata.solidificationTimeMutex.Unlock() - } - - messageMetadata.SetModified() - - modified = true - } - messageMetadata.solidMutex.Unlock() - - } else { - messageMetadata.solidMutex.RUnlock() - } - - return -} - -// SolidificationTime returns the time when the message was marked to be solid. -func (messageMetadata *MessageMetadata) SolidificationTime() time.Time { - messageMetadata.solidificationTimeMutex.RLock() - defer messageMetadata.solidificationTimeMutex.RUnlock() - - return messageMetadata.solidificationTime -} - -// Bytes returns a marshaled version of the whole MessageMetadata object. -func (messageMetadata *MessageMetadata) Bytes() []byte { - return byteutils.ConcatBytes(messageMetadata.ObjectStorageKey(), messageMetadata.ObjectStorageValue()) -} - -// ObjectStorageKey returns the key of the stored message metadata object. -// This returns the bytes of the messageID. -func (messageMetadata *MessageMetadata) ObjectStorageKey() []byte { - return messageMetadata.messageID.Bytes() -} - -// ObjectStorageValue returns the value of the stored message metadata object. -// This includes the receivedTime, solidificationTime and solid status. -func (messageMetadata *MessageMetadata) ObjectStorageValue() []byte { - return marshalutil.New(). - WriteTime(messageMetadata.ReceivedTime()). - WriteTime(messageMetadata.SolidificationTime()). - WriteBool(messageMetadata.IsSolid()). - Bytes() -} - -// Update updates the message metadata. -// This should never happen and will panic if attempted. -func (messageMetadata *MessageMetadata) Update(other objectstorage.StorableObject) { - panic("updates disabled") -} - -var _ objectstorage.StorableObject = &MessageMetadata{} - -// CachedMessageMetadata is a wrapper for stored cached object that represents a message metadata. -type CachedMessageMetadata struct { - objectstorage.CachedObject -} - -// Retain registers a new consumer for the cached message metadata. -func (cachedMessageMetadata *CachedMessageMetadata) Retain() *CachedMessageMetadata { - return &CachedMessageMetadata{cachedMessageMetadata.CachedObject.Retain()} -} - -// Unwrap returns the underlying stored message metadata wrapped by the CachedMessageMetadata. -// If the stored object cannot be cast to MessageMetadata or is deleted, it returns nil. -func (cachedMessageMetadata *CachedMessageMetadata) Unwrap() *MessageMetadata { - untypedObject := cachedMessageMetadata.Get() - if untypedObject == nil { - return nil - } - typedObject := untypedObject.(*MessageMetadata) - if typedObject == nil || typedObject.IsDeleted() { - return nil - } - return typedObject -} diff --git a/packages/binary/messagelayer/tangle/missingmessage.go b/packages/binary/messagelayer/tangle/missingmessage.go deleted file mode 100644 index 5d691576..00000000 --- a/packages/binary/messagelayer/tangle/missingmessage.go +++ /dev/null @@ -1,93 +0,0 @@ -package tangle - -import ( - "time" - - "github.com/iotaledger/hive.go/byteutils" - "github.com/iotaledger/hive.go/marshalutil" - "github.com/iotaledger/hive.go/objectstorage" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" -) - -// MissingMessage represents a missing message. -type MissingMessage struct { - objectstorage.StorableObjectFlags - - messageID message.ID - missingSince time.Time -} - -// NewMissingMessage creates new missing message with the specified messageID. -func NewMissingMessage(messageID message.ID) *MissingMessage { - return &MissingMessage{ - messageID: messageID, - missingSince: time.Now(), - } -} - -// MissingMessageFromBytes parses the given bytes into a MissingMessage. -func MissingMessageFromBytes(bytes []byte) (result *MissingMessage, consumedBytes int, err error) { - marshalUtil := marshalutil.New(bytes) - result, err = ParseMissingMessage(marshalUtil) - consumedBytes = marshalUtil.ReadOffset() - return -} - -// MissingMessageFromObjectStorage creates a MissingMessage from the ObjectStorage. -func MissingMessageFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) { - result, _, err = MissingMessageFromBytes(byteutils.ConcatBytes(key, data)) - - return -} - -// ParseMissingMessage parses a MissingMessage from the given marshal util. -func ParseMissingMessage(marshalUtil *marshalutil.MarshalUtil) (result *MissingMessage, err error) { - result = &MissingMessage{} - - if result.messageID, err = message.ParseID(marshalUtil); err != nil { - return - } - if result.missingSince, err = marshalUtil.ReadTime(); err != nil { - return - } - - return -} - -// MessageID returns the id of the message. -func (missingMessage *MissingMessage) MessageID() message.ID { - return missingMessage.messageID -} - -// MissingSince returns the time since when this message is missing. -func (missingMessage *MissingMessage) MissingSince() time.Time { - return missingMessage.missingSince -} - -// Bytes returns a marshaled version of this MissingMessage. -func (missingMessage *MissingMessage) Bytes() []byte { - return byteutils.ConcatBytes(missingMessage.ObjectStorageKey(), missingMessage.ObjectStorageValue()) -} - -// Update update the missing message. -// It should never happen and will panic if called. -func (missingMessage *MissingMessage) Update(other objectstorage.StorableObject) { - panic("missing messages should never be overwritten and only stored once to optimize IO") -} - -// ObjectStorageKey returns the key of the stored missing message. -// This returns the bytes of the messageID of the missing message. -func (missingMessage *MissingMessage) ObjectStorageKey() []byte { - return missingMessage.messageID[:] -} - -// ObjectStorageValue returns the value of the stored missing message. -func (missingMessage *MissingMessage) ObjectStorageValue() (result []byte) { - result, err := missingMessage.missingSince.MarshalBinary() - if err != nil { - panic(err) - } - - return -} diff --git a/packages/binary/messagelayer/tangle/storageprefixes.go b/packages/binary/messagelayer/tangle/storageprefixes.go deleted file mode 100644 index 1e3e0ff5..00000000 --- a/packages/binary/messagelayer/tangle/storageprefixes.go +++ /dev/null @@ -1,12 +0,0 @@ -package tangle - -const ( - // PrefixMessage defines the storage prefix for message. - PrefixMessage byte = iota - // PrefixMessageMetadata defines the storage prefix for message metadata. - PrefixMessageMetadata - // PrefixApprovers defines the storage prefix for approvers. - PrefixApprovers - // PrefixMissingMessage defines the storage prefix for missing message. - PrefixMissingMessage -) diff --git a/packages/binary/messagelayer/tangle/tangle.go b/packages/binary/messagelayer/tangle/tangle.go deleted file mode 100644 index 95e21f08..00000000 --- a/packages/binary/messagelayer/tangle/tangle.go +++ /dev/null @@ -1,375 +0,0 @@ -package tangle - -import ( - "container/list" - "time" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/storageprefix" - "github.com/iotaledger/hive.go/async" - "github.com/iotaledger/hive.go/kvstore" - "github.com/iotaledger/hive.go/objectstorage" - "github.com/iotaledger/hive.go/types" -) - -const ( - cacheTime = 20 * time.Second -) - -// Tangle represents the base layer of messages. -type Tangle struct { - messageStorage *objectstorage.ObjectStorage - messageMetadataStorage *objectstorage.ObjectStorage - approverStorage *objectstorage.ObjectStorage - missingMessageStorage *objectstorage.ObjectStorage - - Events *Events - - storeMessageWorkerPool async.WorkerPool - solidifierWorkerPool async.WorkerPool - shutdown chan struct{} -} - -// New creates a new Tangle. -func New(store kvstore.KVStore) (result *Tangle) { - osFactory := objectstorage.NewFactory(store, storageprefix.MessageLayer) - - result = &Tangle{ - shutdown: make(chan struct{}), - messageStorage: osFactory.New(PrefixMessage, message.FromObjectStorage, objectstorage.CacheTime(cacheTime), objectstorage.LeakDetectionEnabled(false)), - messageMetadataStorage: osFactory.New(PrefixMessageMetadata, MessageMetadataFromObjectStorage, objectstorage.CacheTime(cacheTime), objectstorage.LeakDetectionEnabled(false)), - approverStorage: osFactory.New(PrefixApprovers, ApproverFromObjectStorage, objectstorage.CacheTime(cacheTime), objectstorage.PartitionKey(message.IDLength, message.IDLength), objectstorage.LeakDetectionEnabled(false)), - missingMessageStorage: osFactory.New(PrefixMissingMessage, MissingMessageFromObjectStorage, objectstorage.CacheTime(cacheTime), objectstorage.LeakDetectionEnabled(false)), - - Events: newEvents(), - } - - result.solidifierWorkerPool.Tune(1024) - result.storeMessageWorkerPool.Tune(1024) - return -} - -// AttachMessage attaches a new message to the tangle. -func (tangle *Tangle) AttachMessage(msg *message.Message) { - tangle.storeMessageWorkerPool.Submit(func() { tangle.storeMessageWorker(msg) }) -} - -// Message retrieves a message from the tangle. -func (tangle *Tangle) Message(messageID message.ID) *message.CachedMessage { - return &message.CachedMessage{CachedObject: tangle.messageStorage.Load(messageID[:])} -} - -// MessageMetadata retrieves the metadata of a message from the tangle. -func (tangle *Tangle) MessageMetadata(messageID message.ID) *CachedMessageMetadata { - return &CachedMessageMetadata{CachedObject: tangle.messageMetadataStorage.Load(messageID[:])} -} - -// Approvers retrieves the approvers of a message from the tangle. -func (tangle *Tangle) Approvers(messageID message.ID) CachedApprovers { - approvers := make(CachedApprovers, 0) - tangle.approverStorage.ForEach(func(key []byte, cachedObject objectstorage.CachedObject) bool { - approvers = append(approvers, &CachedApprover{CachedObject: cachedObject}) - return true - }, messageID[:]) - return approvers -} - -// DeleteMessage deletes a message and its association to approvees by un-marking the given -// message as an approver. -func (tangle *Tangle) DeleteMessage(messageID message.ID) { - tangle.Message(messageID).Consume(func(currentMsg *message.Message) { - parent1MsgID := currentMsg.Parent1ID() - tangle.deleteApprover(parent1MsgID, messageID) - - parent2MsgID := currentMsg.Parent2ID() - if parent2MsgID != parent1MsgID { - tangle.deleteApprover(parent2MsgID, messageID) - } - - tangle.messageMetadataStorage.Delete(messageID[:]) - tangle.messageStorage.Delete(messageID[:]) - - tangle.Events.MessageRemoved.Trigger(messageID) - }) -} - -// DeleteMissingMessage deletes a message from the missingMessageStorage. -func (tangle *Tangle) DeleteMissingMessage(messageID message.ID) { - tangle.missingMessageStorage.Delete(messageID[:]) -} - -// Shutdown marks the tangle as stopped, so it will not accept any new messages (waits for all backgroundTasks to finish). -func (tangle *Tangle) Shutdown() *Tangle { - tangle.storeMessageWorkerPool.ShutdownGracefully() - tangle.solidifierWorkerPool.ShutdownGracefully() - - tangle.messageStorage.Shutdown() - tangle.messageMetadataStorage.Shutdown() - tangle.approverStorage.Shutdown() - tangle.missingMessageStorage.Shutdown() - close(tangle.shutdown) - - return tangle -} - -// Prune resets the database and deletes all objects (good for testing or "node resets"). -func (tangle *Tangle) Prune() error { - for _, storage := range []*objectstorage.ObjectStorage{ - tangle.messageStorage, - tangle.messageMetadataStorage, - tangle.approverStorage, - tangle.missingMessageStorage, - } { - if err := storage.Prune(); err != nil { - return err - } - } - - return nil -} - -// DBStats returns the number of solid messages and total number of messages in the database (messageMetadataStorage, -// that should contain the messages as messageStorage), the number of messages in missingMessageStorage, furthermore -// the average time it takes to solidify messages. -func (tangle *Tangle) DBStats() (solidCount int, messageCount int, avgSolidificationTime float64, missingMessageCount int) { - var sumSolidificationTime time.Duration - tangle.messageMetadataStorage.ForEach(func(key []byte, cachedObject objectstorage.CachedObject) bool { - cachedObject.Consume(func(object objectstorage.StorableObject) { - msgMetaData := object.(*MessageMetadata) - messageCount++ - received := msgMetaData.ReceivedTime() - if msgMetaData.IsSolid() { - solidCount++ - sumSolidificationTime += msgMetaData.solidificationTime.Sub(received) - } - }) - return true - }) - if solidCount > 0 { - avgSolidificationTime = float64(sumSolidificationTime.Milliseconds()) / float64(solidCount) - } - tangle.missingMessageStorage.ForEach(func(key []byte, cachedObject objectstorage.CachedObject) bool { - cachedObject.Consume(func(object objectstorage.StorableObject) { - missingMessageCount++ - }) - return true - }) - return -} - -// MissingMessages return the ids of messages in missingMessageStorage -func (tangle *Tangle) MissingMessages() (ids []message.ID) { - tangle.missingMessageStorage.ForEach(func(key []byte, cachedObject objectstorage.CachedObject) bool { - cachedObject.Consume(func(object objectstorage.StorableObject) { - ids = append(ids, object.(*MissingMessage).messageID) - }) - - return true - }) - return -} - -// worker that stores the message and calls the corresponding storage events. -func (tangle *Tangle) storeMessageWorker(msg *message.Message) { - // store message - var cachedMessage *message.CachedMessage - _tmp, msgIsNew := tangle.messageStorage.StoreIfAbsent(msg) - if !msgIsNew { - return - } - cachedMessage = &message.CachedMessage{CachedObject: _tmp} - - // store message metadata - messageID := msg.ID() - cachedMsgMetadata := &CachedMessageMetadata{CachedObject: tangle.messageMetadataStorage.Store(NewMessageMetadata(messageID))} - - // store parent1 approver - parent1MsgID := msg.Parent1ID() - tangle.approverStorage.Store(NewApprover(parent1MsgID, messageID)).Release() - - // store parent2 approver - if parent2MsgID := msg.Parent2ID(); parent2MsgID != parent1MsgID { - tangle.approverStorage.Store(NewApprover(parent2MsgID, messageID)).Release() - } - - // trigger events - if tangle.missingMessageStorage.DeleteIfPresent(messageID[:]) { - tangle.Events.MissingMessageReceived.Trigger(&CachedMessageEvent{ - Message: cachedMessage, - MessageMetadata: cachedMsgMetadata}) - } - - tangle.Events.MessageAttached.Trigger(&CachedMessageEvent{ - Message: cachedMessage, - MessageMetadata: cachedMsgMetadata}) - - // check message solidity - tangle.solidifierWorkerPool.Submit(func() { - tangle.checkMessageSolidityAndPropagate(cachedMessage, cachedMsgMetadata) - }) -} - -// checks whether the given message is solid and marks it as missing if it isn't known. -func (tangle *Tangle) isMessageMarkedAsSolid(messageID message.ID) bool { - // return true if the message is the Genesis - if messageID == message.EmptyID { - return true - } - - // retrieve the CachedMessageMetadata and mark it as missing if it doesn't exist - msgMetadataCached := &CachedMessageMetadata{tangle.messageMetadataStorage.ComputeIfAbsent(messageID.Bytes(), func(key []byte) objectstorage.StorableObject { - // store the missing message and trigger events - if cachedMissingMessage, stored := tangle.missingMessageStorage.StoreIfAbsent(NewMissingMessage(messageID)); stored { - cachedMissingMessage.Consume(func(object objectstorage.StorableObject) { - tangle.Events.MessageMissing.Trigger(messageID) - }) - } - - // do not initialize the metadata here, we execute this in ComputeIfAbsent to be secure from race conditions - return nil - })} - defer msgMetadataCached.Release() - - // return false if the metadata does not exist - msgMetadata := msgMetadataCached.Unwrap() - if msgMetadata == nil { - return false - } - - // return the solid flag of the metadata object - return msgMetadata.IsSolid() -} - -// checks whether the given message is solid by examining whether its parent1 and -// parent2 messages are solid. -func (tangle *Tangle) isMessageSolid(msg *message.Message, msgMetadata *MessageMetadata) bool { - if msg == nil || msg.IsDeleted() { - return false - } - - if msgMetadata == nil || msgMetadata.IsDeleted() { - return false - } - - if msgMetadata.IsSolid() { - return true - } - - // as missing messages are requested in isMessageMarkedAsSolid, we want to prevent short-circuit evaluation - parent1Solid := tangle.isMessageMarkedAsSolid(msg.Parent1ID()) - parent2Solid := tangle.isMessageMarkedAsSolid(msg.Parent2ID()) - return parent1Solid && parent2Solid -} - -// builds up a stack from the given message and tries to solidify into the present. -// missing messages which are needed for a message to become solid are marked as missing. -func (tangle *Tangle) checkMessageSolidityAndPropagate(cachedMessage *message.CachedMessage, cachedMsgMetadata *CachedMessageMetadata) { - - popElementsFromStack := func(stack *list.List) (*message.CachedMessage, *CachedMessageMetadata) { - currentSolidificationEntry := stack.Front() - currentCachedMsg := currentSolidificationEntry.Value.([2]interface{})[0] - currentCachedMsgMetadata := currentSolidificationEntry.Value.([2]interface{})[1] - stack.Remove(currentSolidificationEntry) - return currentCachedMsg.(*message.CachedMessage), currentCachedMsgMetadata.(*CachedMessageMetadata) - } - - // initialize the stack - solidificationStack := list.New() - solidificationStack.PushBack([2]interface{}{cachedMessage, cachedMsgMetadata}) - - // processed messages that are supposed to be checked for solidity recursively - for solidificationStack.Len() > 0 { - currentCachedMessage, currentCachedMsgMetadata := popElementsFromStack(solidificationStack) - - currentMessage := currentCachedMessage.Unwrap() - currentMsgMetadata := currentCachedMsgMetadata.Unwrap() - if currentMessage == nil || currentMsgMetadata == nil { - currentCachedMessage.Release() - currentCachedMsgMetadata.Release() - continue - } - - // mark the message as solid if it has become solid - if tangle.isMessageSolid(currentMessage, currentMsgMetadata) && currentMsgMetadata.SetSolid(true) { - tangle.Events.MessageSolid.Trigger(&CachedMessageEvent{ - Message: currentCachedMessage, - MessageMetadata: currentCachedMsgMetadata}) - - // auto. push approvers of the newly solid message to propagate solidification - tangle.Approvers(currentMessage.ID()).Consume(func(approver *Approver) { - approverMessageID := approver.ApproverMessageID() - solidificationStack.PushBack([2]interface{}{ - tangle.Message(approverMessageID), - tangle.MessageMetadata(approverMessageID), - }) - }) - } - - currentCachedMessage.Release() - currentCachedMsgMetadata.Release() - } -} - -// deletes the given approver association for the given approvee to its approver. -func (tangle *Tangle) deleteApprover(approvedMessageID message.ID, approvingMessage message.ID) { - idToDelete := make([]byte, message.IDLength+message.IDLength) - copy(idToDelete[:message.IDLength], approvedMessageID[:]) - copy(idToDelete[message.IDLength:], approvingMessage[:]) - tangle.approverStorage.Delete(idToDelete) -} - -// deletes a message and its future cone of messages/approvers. -// nolint -func (tangle *Tangle) deleteFutureCone(messageID message.ID) { - cleanupStack := list.New() - cleanupStack.PushBack(messageID) - - processedMessages := make(map[message.ID]types.Empty) - processedMessages[messageID] = types.Void - - for cleanupStack.Len() >= 1 { - currentStackEntry := cleanupStack.Front() - currentMessageID := currentStackEntry.Value.(message.ID) - cleanupStack.Remove(currentStackEntry) - - tangle.DeleteMessage(currentMessageID) - - tangle.Approvers(currentMessageID).Consume(func(approver *Approver) { - approverID := approver.ApproverMessageID() - if _, messageProcessed := processedMessages[approverID]; !messageProcessed { - cleanupStack.PushBack(approverID) - processedMessages[approverID] = types.Void - } - }) - } -} - -// SolidifierWorkerPoolStatus returns the name and the load of the workerpool. -func (tangle *Tangle) SolidifierWorkerPoolStatus() (name string, load int) { - return "Solidifier", tangle.solidifierWorkerPool.RunningWorkers() -} - -// StoreMessageWorkerPoolStatus returns the name and the load of the workerpool. -func (tangle *Tangle) StoreMessageWorkerPoolStatus() (name string, load int) { - return "StoreMessage", tangle.storeMessageWorkerPool.RunningWorkers() -} - -// RetrieveAllTips returns the tips (i.e., solid messages that are not part of the approvers list). -// It iterates over the messageMetadataStorage, thus only use this method if necessary. -// TODO: improve this function. -func (tangle *Tangle) RetrieveAllTips() (tips []message.ID) { - tangle.messageMetadataStorage.ForEach(func(key []byte, cachedMessage objectstorage.CachedObject) bool { - cachedMessage.Consume(func(object objectstorage.StorableObject) { - messageMetadata := object.(*MessageMetadata) - if messageMetadata != nil && messageMetadata.IsSolid() { - cachedApprovers := tangle.Approvers(messageMetadata.messageID) - if len(cachedApprovers) == 0 { - tips = append(tips, messageMetadata.messageID) - } - cachedApprovers.Consume(func(approver *Approver) {}) - } - }) - return true - }) - return tips -} diff --git a/packages/binary/messagelayer/tangle/tangle_test.go b/packages/binary/messagelayer/tangle/tangle_test.go deleted file mode 100644 index ce3b1fdd..00000000 --- a/packages/binary/messagelayer/tangle/tangle_test.go +++ /dev/null @@ -1,240 +0,0 @@ -package tangle - -import ( - "fmt" - "math/rand" - "sync" - "sync/atomic" - "testing" - "time" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messagefactory" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/hive.go/datastructure/randommap" - "github.com/iotaledger/hive.go/events" - "github.com/iotaledger/hive.go/identity" - "github.com/iotaledger/hive.go/kvstore/mapdb" - "github.com/iotaledger/hive.go/testutil" - "github.com/magiconair/properties/assert" - "github.com/stretchr/testify/require" -) - -func BenchmarkTangle_AttachMessage(b *testing.B) { - tangle := New(mapdb.NewMapDB()) - if err := tangle.Prune(); err != nil { - b.Error(err) - - return - } - - messageBytes := make([]*message.Message, b.N) - for i := 0; i < b.N; i++ { - messageBytes[i] = newTestMessage("some data") - messageBytes[i].Bytes() - } - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - tangle.AttachMessage(messageBytes[i]) - } - - tangle.Shutdown() -} - -func TestTangle_AttachMessage(t *testing.T) { - messageTangle := New(mapdb.NewMapDB()) - if err := messageTangle.Prune(); err != nil { - t.Error(err) - - return - } - - messageTangle.Events.MessageAttached.Attach(events.NewClosure(func(cachedMsgEvent *CachedMessageEvent) { - cachedMsgEvent.MessageMetadata.Release() - - cachedMsgEvent.Message.Consume(func(msg *message.Message) { - fmt.Println("ATTACHED:", msg.ID()) - }) - })) - - messageTangle.Events.MessageSolid.Attach(events.NewClosure(func(cachedMsgEvent *CachedMessageEvent) { - cachedMsgEvent.MessageMetadata.Release() - - cachedMsgEvent.Message.Consume(func(msg *message.Message) { - fmt.Println("SOLID:", msg.ID()) - }) - })) - - messageTangle.Events.MessageUnsolidifiable.Attach(events.NewClosure(func(messageId message.ID) { - fmt.Println("UNSOLIDIFIABLE:", messageId) - })) - - messageTangle.Events.MessageMissing.Attach(events.NewClosure(func(messageId message.ID) { - fmt.Println("MISSING:", messageId) - })) - - messageTangle.Events.MessageRemoved.Attach(events.NewClosure(func(messageId message.ID) { - fmt.Println("REMOVED:", messageId) - })) - - newMessageOne := newTestMessage("some data") - newMessageTwo := newTestMessage("some other data") - - messageTangle.AttachMessage(newMessageTwo) - - time.Sleep(7 * time.Second) - - messageTangle.AttachMessage(newMessageOne) - - messageTangle.Shutdown() -} - -func TestTangle_MissingMessages(t *testing.T) { - // test parameters - messageCount := 2000 - widthOfTheTangle := 2500 - - // variables required for the test - missingMessagesMap := make(map[message.ID]bool) - var missingMessagesMapMutex sync.Mutex - wg := sync.WaitGroup{} - - // create badger store - badgerDB, err := testutil.BadgerDB(t) - require.NoError(t, err) - - // map to keep track of the tips - tips := randommap.New() - tips.Set(message.EmptyID, message.EmptyID) - - // setup the message factory - msgFactory := messagefactory.New( - badgerDB, - []byte("sequenceKey"), - identity.GenerateLocalIdentity(), - messagefactory.TipSelectorFunc(func() (message.ID, message.ID) { - return tips.RandomEntry().(message.ID), tips.RandomEntry().(message.ID) - }), - ) - defer msgFactory.Shutdown() - - // create a helper function that creates the messages - createNewMessage := func() *message.Message { - // issue the payload - msg, err := msgFactory.IssuePayload(payload.NewData([]byte("0"))) - require.NoError(t, err) - - // remove a tip if the width of the tangle is reached - if tips.Size() >= widthOfTheTangle { - if rand.Intn(1000) < 500 { - tips.Delete(msg.Parent2ID()) - } else { - tips.Delete(msg.Parent1ID()) - } - } - - // add current message as a tip - tips.Set(msg.ID(), msg.ID()) - - // return the constructed message - return msg - } - - // create the tangle - tangle := New(badgerDB) - if err := tangle.Prune(); err != nil { - t.Error(err) - - return - } - - // generate the messages we want to solidify - preGeneratedMessages := make(map[message.ID]*message.Message) - for i := 0; i < messageCount; i++ { - msg := createNewMessage() - - preGeneratedMessages[msg.ID()] = msg - } - - fmt.Println("PRE-GENERATING MESSAGES: DONE") - - var receivedTransactionsCounter int32 - tangle.Events.MessageAttached.Attach(events.NewClosure(func(cachedMsgEvent *CachedMessageEvent) { - defer cachedMsgEvent.Message.Release() - defer cachedMsgEvent.MessageMetadata.Release() - - newReceivedTransactionsCounterValue := atomic.AddInt32(&receivedTransactionsCounter, 1) - if newReceivedTransactionsCounterValue%1000 == 0 { - fmt.Println("RECEIVED MESSAGES: ", newReceivedTransactionsCounterValue) - go fmt.Println("MISSING MESSAGES:", len(tangle.MissingMessages())) - } - })) - - // increase the counter when a missing message was detected - tangle.Events.MessageMissing.Attach(events.NewClosure(func(messageId message.ID) { - // attach the message after it has been requested - go func() { - time.Sleep(50 * time.Millisecond) - - tangle.AttachMessage(preGeneratedMessages[messageId]) - }() - - missingMessagesMapMutex.Lock() - missingMessagesMap[messageId] = true - missingMessagesMapMutex.Unlock() - })) - - // decrease the counter when a missing message was received - tangle.Events.MissingMessageReceived.Attach(events.NewClosure(func(cachedMsgEvent *CachedMessageEvent) { - cachedMsgEvent.MessageMetadata.Release() - cachedMsgEvent.Message.Consume(func(msg *message.Message) { - missingMessagesMapMutex.Lock() - delete(missingMessagesMap, msg.ID()) - missingMessagesMapMutex.Unlock() - }) - })) - - // mark the WaitGroup as done if all messages are solid - solidMessageCounter := int32(0) - tangle.Events.MessageSolid.Attach(events.NewClosure(func(cachedMsgEvent *CachedMessageEvent) { - defer cachedMsgEvent.MessageMetadata.Release() - defer cachedMsgEvent.Message.Release() - - // print progress status message - newSolidCounterValue := atomic.AddInt32(&solidMessageCounter, 1) - if newSolidCounterValue%1000 == 0 { - fmt.Println("SOLID MESSAGES: ", newSolidCounterValue) - go fmt.Println("MISSING MESSAGES:", len(tangle.MissingMessages())) - } - - // mark WaitGroup as done when we are done solidifying everything - if newSolidCounterValue == int32(messageCount) { - fmt.Println("ALL MESSAGES SOLID") - - wg.Done() - } - })) - - // issue tips to start solidification - wg.Add(1) - tips.ForEach(func(key interface{}, value interface{}) { - tangle.AttachMessage(preGeneratedMessages[key.(message.ID)]) - }) - - // wait for all transactions to become solid - wg.Wait() - - // make sure that all MessageMissing events also had a corresponding MissingMessageReceived event - assert.Equal(t, len(missingMessagesMap), 0) - assert.Equal(t, len(tangle.MissingMessages()), 0) - - // shutdown the tangle - tangle.Shutdown() -} - -func newTestMessage(payloadString string) *message.Message { - return message.New(message.EmptyID, message.EmptyID, time.Now(), ed25519.PublicKey{}, 0, payload.NewData([]byte(payloadString)), 0, ed25519.Signature{}) -} diff --git a/packages/binary/messagelayer/test/data_payload_test.go b/packages/binary/messagelayer/test/data_payload_test.go deleted file mode 100644 index b4497fd1..00000000 --- a/packages/binary/messagelayer/test/data_payload_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package test - -import ( - "runtime" - "sync" - "testing" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messagefactory" - "github.com/iotaledger/goshimmer/plugins/messagelayer" - "github.com/iotaledger/hive.go/async" - "github.com/iotaledger/hive.go/identity" - "github.com/iotaledger/hive.go/kvstore/mapdb" - "github.com/stretchr/testify/require" - - "github.com/panjf2000/ants/v2" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" -) - -func BenchmarkVerifyDataMessages(b *testing.B) { - var pool async.WorkerPool - pool.Tune(runtime.GOMAXPROCS(0)) - - factory := messagefactory.New(mapdb.NewMapDB(), []byte(messagelayer.DBSequenceNumber), identity.GenerateLocalIdentity(), messagefactory.TipSelectorFunc(func() (message.ID, message.ID) { return message.EmptyID, message.EmptyID })) - - messages := make([][]byte, b.N) - for i := 0; i < b.N; i++ { - msg, err := factory.IssuePayload(payload.NewData([]byte("some data"))) - require.NoError(b, err) - messages[i] = msg.Bytes() - } - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - currentIndex := i - pool.Submit(func() { - if msg, _, err := message.FromBytes(messages[currentIndex]); err != nil { - b.Error(err) - } else { - msg.VerifySignature() - } - }) - } - - pool.Shutdown() -} - -func BenchmarkVerifySignature(b *testing.B) { - pool, _ := ants.NewPool(80, ants.WithNonblocking(false)) - - factory := messagefactory.New(mapdb.NewMapDB(), []byte(messagelayer.DBSequenceNumber), identity.GenerateLocalIdentity(), messagefactory.TipSelectorFunc(func() (message.ID, message.ID) { return message.EmptyID, message.EmptyID })) - - messages := make([]*message.Message, b.N) - for i := 0; i < b.N; i++ { - msg, err := factory.IssuePayload(payload.NewData([]byte("some data"))) - require.NoError(b, err) - messages[i] = msg - messages[i].Bytes() - } - b.ResetTimer() - - var wg sync.WaitGroup - for i := 0; i < b.N; i++ { - wg.Add(1) - - currentIndex := i - if err := pool.Submit(func() { - messages[currentIndex].VerifySignature() - wg.Done() - }); err != nil { - b.Error(err) - return - } - } - - wg.Wait() -} diff --git a/packages/binary/messagelayer/test/message_test.go b/packages/binary/messagelayer/test/message_test.go deleted file mode 100644 index 8fd3551f..00000000 --- a/packages/binary/messagelayer/test/message_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package test - -import ( - "testing" - "time" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messagefactory" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tipselector" - "github.com/iotaledger/goshimmer/plugins/messagelayer" - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/hive.go/identity" - "github.com/iotaledger/hive.go/kvstore/mapdb" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" -) - -func TestMessage_VerifySignature(t *testing.T) { - keyPair := ed25519.GenerateKeyPair() - pl := payload.NewData([]byte("test")) - - unsigned := message.New(message.EmptyID, message.EmptyID, time.Time{}, keyPair.PublicKey, 0, pl, 0, ed25519.Signature{}) - assert.False(t, unsigned.VerifySignature()) - - unsignedBytes := unsigned.Bytes() - signature := keyPair.PrivateKey.Sign(unsignedBytes[:len(unsignedBytes)-ed25519.SignatureSize]) - - signed := message.New(message.EmptyID, message.EmptyID, time.Time{}, keyPair.PublicKey, 0, pl, 0, signature) - assert.True(t, signed.VerifySignature()) -} - -func TestMessage_MarshalUnmarshal(t *testing.T) { - msgFactory := messagefactory.New(mapdb.NewMapDB(), []byte(messagelayer.DBSequenceNumber), identity.GenerateLocalIdentity(), tipselector.New()) - defer msgFactory.Shutdown() - - testMessage, err := msgFactory.IssuePayload(payload.NewData([]byte("test"))) - require.NoError(t, err) - assert.Equal(t, true, testMessage.VerifySignature()) - - t.Log(testMessage) - - restoredMessage, _, err := message.FromBytes(testMessage.Bytes()) - - if assert.NoError(t, err, err) { - assert.Equal(t, testMessage.ID(), restoredMessage.ID()) - assert.Equal(t, testMessage.Parent1ID(), restoredMessage.Parent1ID()) - assert.Equal(t, testMessage.Parent2ID(), restoredMessage.Parent2ID()) - assert.Equal(t, testMessage.IssuerPublicKey(), restoredMessage.IssuerPublicKey()) - assert.Equal(t, testMessage.IssuingTime().Round(time.Second), restoredMessage.IssuingTime().Round(time.Second)) - assert.Equal(t, testMessage.SequenceNumber(), restoredMessage.SequenceNumber()) - assert.Equal(t, testMessage.Nonce(), restoredMessage.Nonce()) - assert.Equal(t, testMessage.Signature(), restoredMessage.Signature()) - assert.Equal(t, true, restoredMessage.VerifySignature()) - } -} diff --git a/packages/binary/messagelayer/test/retrievealltips_test.go b/packages/binary/messagelayer/test/retrievealltips_test.go deleted file mode 100644 index dc6b4f1c..00000000 --- a/packages/binary/messagelayer/test/retrievealltips_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package test - -import ( - "sync" - "testing" - "time" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle" - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/hive.go/events" - "github.com/iotaledger/hive.go/kvstore/mapdb" - "github.com/stretchr/testify/assert" -) - -func TestRetrieveAllTips(t *testing.T) { - messageTangle := tangle.New(mapdb.NewMapDB()) - - messageA := newTestMessage("A", message.EmptyID, message.EmptyID) - messageB := newTestMessage("B", messageA.ID(), message.EmptyID) - messageC := newTestMessage("C", messageA.ID(), message.EmptyID) - - var wg sync.WaitGroup - - messageTangle.Events.MessageSolid.Attach(events.NewClosure(func(cachedMsgEvent *tangle.CachedMessageEvent) { - cachedMsgEvent.Message.Release() - cachedMsgEvent.MessageMetadata.Release() - wg.Done() - })) - - wg.Add(3) - messageTangle.AttachMessage(messageA) - messageTangle.AttachMessage(messageB) - messageTangle.AttachMessage(messageC) - - wg.Wait() - - allTips := messageTangle.RetrieveAllTips() - - assert.Equal(t, 2, len(allTips)) - - messageTangle.Shutdown() -} - -func newTestMessage(payloadString string, parent1, parent2 message.ID) *message.Message { - return message.New(parent1, parent2, time.Now(), ed25519.PublicKey{}, 0, payload.NewData([]byte(payloadString)), 0, ed25519.Signature{}) -} diff --git a/packages/binary/messagelayer/tipselector/events.go b/packages/binary/messagelayer/tipselector/events.go deleted file mode 100644 index 6107ed5c..00000000 --- a/packages/binary/messagelayer/tipselector/events.go +++ /dev/null @@ -1,26 +0,0 @@ -package tipselector - -import ( - "github.com/iotaledger/hive.go/events" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" -) - -// Events represents event happening on the tip-selector. -type Events struct { - // Fired when a tip is added. - TipAdded *events.Event - // Fired when a tip is removed. - TipRemoved *events.Event -} - -func newEvents() *Events { - return &Events{ - TipAdded: events.NewEvent(messageIDEvent), - TipRemoved: events.NewEvent(messageIDEvent), - } -} - -func messageIDEvent(handler interface{}, params ...interface{}) { - handler.(func(message.ID))(params[0].(message.ID)) -} diff --git a/packages/binary/messagelayer/tipselector/tipselector.go b/packages/binary/messagelayer/tipselector/tipselector.go deleted file mode 100644 index 04d11300..00000000 --- a/packages/binary/messagelayer/tipselector/tipselector.go +++ /dev/null @@ -1,81 +0,0 @@ -package tipselector - -import ( - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/hive.go/datastructure/randommap" -) - -// TipSelector manages a map of tips and emits events for their removal and addition. -type TipSelector struct { - tips *randommap.RandomMap - Events *Events -} - -// New creates a new tip-selector. -func New(tips ...message.ID) *TipSelector { - tipSelector := &TipSelector{ - tips: randommap.New(), - Events: newEvents(), - } - - if tips != nil { - tipSelector.Set(tips...) - } - - return tipSelector -} - -// Set adds the given messageIDs as tips. -func (tipSelector *TipSelector) Set(tips ...message.ID) { - for _, messageID := range tips { - tipSelector.tips.Set(messageID, messageID) - } -} - -// AddTip adds the given message as a tip. -func (tipSelector *TipSelector) AddTip(msg *message.Message) { - messageID := msg.ID() - if tipSelector.tips.Set(messageID, messageID) { - tipSelector.Events.TipAdded.Trigger(messageID) - } - - parent1MessageID := msg.Parent1ID() - if _, deleted := tipSelector.tips.Delete(parent1MessageID); deleted { - tipSelector.Events.TipRemoved.Trigger(parent1MessageID) - } - - parent2MessageID := msg.Parent2ID() - if _, deleted := tipSelector.tips.Delete(parent2MessageID); deleted { - tipSelector.Events.TipRemoved.Trigger(parent2MessageID) - } -} - -// Tips returns two tips. -func (tipSelector *TipSelector) Tips() (parent1MessageID, parent2MessageID message.ID) { - tip := tipSelector.tips.RandomEntry() - if tip == nil { - parent1MessageID = message.EmptyID - parent2MessageID = message.EmptyID - - return - } - - parent2MessageID = tip.(message.ID) - - if tipSelector.tips.Size() == 1 { - parent1MessageID = parent2MessageID - return - } - - parent1MessageID = tipSelector.tips.RandomEntry().(message.ID) - for parent1MessageID == parent2MessageID && tipSelector.tips.Size() > 1 { - parent1MessageID = tipSelector.tips.RandomEntry().(message.ID) - } - - return -} - -// TipCount the amount of current tips. -func (tipSelector *TipSelector) TipCount() int { - return tipSelector.tips.Size() -} diff --git a/packages/binary/messagelayer/tipselector/tipselector_test.go b/packages/binary/messagelayer/tipselector/tipselector_test.go deleted file mode 100644 index 64c8e85b..00000000 --- a/packages/binary/messagelayer/tipselector/tipselector_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package tipselector - -import ( - "testing" - "time" - - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/stretchr/testify/assert" - - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" -) - -func Test(t *testing.T) { - // create tip selector - tipSelector := New() - - // check if first tips point to genesis - parent11, parent21 := tipSelector.Tips() - assert.Equal(t, message.EmptyID, parent11) - assert.Equal(t, message.EmptyID, parent21) - - // create a message and attach it - message1 := newTestMessage(parent11, parent21, "testmessage1") - tipSelector.AddTip(message1) - - // check if the tip shows up in the tip count - assert.Equal(t, 1, tipSelector.TipCount()) - - // check if next tips point to our first message - parent12, parent22 := tipSelector.Tips() - assert.Equal(t, message1.ID(), parent12) - assert.Equal(t, message1.ID(), parent22) - - // create a 2nd message and attach it - message2 := newTestMessage(message.EmptyID, message.EmptyID, "testmessage2") - tipSelector.AddTip(message2) - - // check if the tip shows up in the tip count - assert.Equal(t, 2, tipSelector.TipCount()) - - // attach a message to our two tips - parent13, parent23 := tipSelector.Tips() - message3 := newTestMessage(parent13, parent23, "testmessage3") - tipSelector.AddTip(message3) - - // check if the tip shows replaces the current tips - parent14, parent24 := tipSelector.Tips() - assert.Equal(t, 1, tipSelector.TipCount()) - assert.Equal(t, message3.ID(), parent14) - assert.Equal(t, message3.ID(), parent24) -} - -func newTestMessage(parent1, parent2 message.ID, payloadString string) *message.Message { - return message.New(parent1, parent2, time.Now(), ed25519.PublicKey{}, 0, payload.NewData([]byte(payloadString)), 0, ed25519.Signature{}) -} diff --git a/packages/binary/spammer/spammer.go b/packages/binary/spammer/spammer.go index 259ba8fe..42f333e3 100644 --- a/packages/binary/spammer/spammer.go +++ b/packages/binary/spammer/spammer.go @@ -6,12 +6,11 @@ import ( "github.com/iotaledger/hive.go/types" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" ) // IssuePayloadFunc is a function which issues a payload. -type IssuePayloadFunc = func(payload payload.Payload) (*message.Message, error) +type IssuePayloadFunc = func(payload tangle.Payload) (*tangle.Message, error) // Spammer spams messages with a static data payload. type Spammer struct { @@ -49,7 +48,7 @@ func (spammer *Spammer) run(rate int, timeUnit time.Duration, processID int64) { } // we don't care about errors or the actual issued message - _, _ = spammer.issuePayloadFunc(payload.NewData([]byte("SPAM"))) + _, _ = spammer.issuePayloadFunc(tangle.NewDataPayload([]byte("SPAM"))) currentSentCounter++ diff --git a/packages/gossip/manager.go b/packages/gossip/manager.go index 2e4e8436..4244ccd3 100644 --- a/packages/gossip/manager.go +++ b/packages/gossip/manager.go @@ -6,9 +6,9 @@ import ( "runtime" "sync" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" pb "github.com/iotaledger/goshimmer/packages/gossip/proto" "github.com/iotaledger/goshimmer/packages/gossip/server" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/hive.go/autopeering/peer" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/identity" @@ -31,7 +31,7 @@ var ( ) // LoadMessageFunc defines a function that returns the message for the given id. -type LoadMessageFunc func(messageId message.ID) ([]byte, error) +type LoadMessageFunc func(messageId tangle.MessageID) ([]byte, error) // The Manager handles the connected neighbors. type Manager struct { @@ -317,7 +317,7 @@ func (m *Manager) processMessageRequest(data []byte, nbr *Neighbor) { m.log.Debugw("invalid packet", "err", err) } - msgID, _, err := message.IDFromBytes(packet.GetId()) + msgID, _, err := tangle.MessageIDFromBytes(packet.GetId()) if err != nil { m.log.Debugw("invalid message id:", "err", err) } diff --git a/packages/gossip/manager_test.go b/packages/gossip/manager_test.go index be3b1828..4af118d4 100644 --- a/packages/gossip/manager_test.go +++ b/packages/gossip/manager_test.go @@ -6,9 +6,9 @@ import ( "testing" "time" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" pb "github.com/iotaledger/goshimmer/packages/gossip/proto" "github.com/iotaledger/goshimmer/packages/gossip/server" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/hive.go/autopeering/peer" "github.com/iotaledger/hive.go/autopeering/peer/service" "github.com/iotaledger/hive.go/events" @@ -27,7 +27,7 @@ var ( testMessageData = []byte("testMsg") ) -func loadTestMessage(message.ID) ([]byte, error) { return testMessageData, nil } +func loadTestMessage(tangle.MessageID) ([]byte, error) { return testMessageData, nil } func TestClose(t *testing.T) { _, teardown, _ := newMockedManager(t, "A") @@ -336,7 +336,7 @@ func TestMessageRequest(t *testing.T) { // wait for the connections to establish wg.Wait() - id := message.ID{} + id := tangle.MessageID{} // mgrA should eventually receive the message mgrA.On("messageReceived", &MessageReceivedEvent{Data: testMessageData, Peer: peerB}).Once() diff --git a/packages/tangle/message_test.go b/packages/tangle/message_test.go index afb737e8..c7f5e08a 100644 --- a/packages/tangle/message_test.go +++ b/packages/tangle/message_test.go @@ -4,7 +4,6 @@ import ( "testing" "time" - "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/identity" "github.com/iotaledger/hive.go/kvstore/mapdb" @@ -27,7 +26,7 @@ func TestMessage_VerifySignature(t *testing.T) { } func TestMessage_MarshalUnmarshal(t *testing.T) { - msgFactory := NewMessageFactory(mapdb.NewMapDB(), []byte(messagelayer.DBSequenceNumber), identity.GenerateLocalIdentity(), NewMessageTipSelector()) + msgFactory := NewMessageFactory(mapdb.NewMapDB(), []byte(DBSequenceNumber), identity.GenerateLocalIdentity(), NewMessageTipSelector()) defer msgFactory.Shutdown() testMessage, err := msgFactory.IssuePayload(NewDataPayload([]byte("test"))) diff --git a/packages/tangle/payload_test.go b/packages/tangle/payload_test.go index 67c5fa55..92512835 100644 --- a/packages/tangle/payload_test.go +++ b/packages/tangle/payload_test.go @@ -5,7 +5,6 @@ import ( "sync" "testing" - "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/async" "github.com/iotaledger/hive.go/identity" "github.com/iotaledger/hive.go/kvstore/mapdb" @@ -18,7 +17,7 @@ func BenchmarkVerifyDataMessages(b *testing.B) { var pool async.WorkerPool pool.Tune(runtime.GOMAXPROCS(0)) - factory := NewMessageFactory(mapdb.NewMapDB(), []byte(messagelayer.DBSequenceNumber), identity.GenerateLocalIdentity(), TipSelectorFunc(func() (MessageID, MessageID) { return EmptyMessageID, EmptyMessageID })) + factory := NewMessageFactory(mapdb.NewMapDB(), []byte(DBSequenceNumber), identity.GenerateLocalIdentity(), TipSelectorFunc(func() (MessageID, MessageID) { return EmptyMessageID, EmptyMessageID })) messages := make([][]byte, b.N) for i := 0; i < b.N; i++ { @@ -46,7 +45,7 @@ func BenchmarkVerifyDataMessages(b *testing.B) { func BenchmarkVerifySignature(b *testing.B) { pool, _ := ants.NewPool(80, ants.WithNonblocking(false)) - factory := NewMessageFactory(mapdb.NewMapDB(), []byte(messagelayer.DBSequenceNumber), identity.GenerateLocalIdentity(), TipSelectorFunc(func() (MessageID, MessageID) { return EmptyMessageID, EmptyMessageID })) + factory := NewMessageFactory(mapdb.NewMapDB(), []byte(DBSequenceNumber), identity.GenerateLocalIdentity(), TipSelectorFunc(func() (MessageID, MessageID) { return EmptyMessageID, EmptyMessageID })) messages := make([]*Message, b.N) for i := 0; i < b.N; i++ { diff --git a/packages/tangle/tangle.go b/packages/tangle/tangle.go index 3d8d3329..20543e0a 100644 --- a/packages/tangle/tangle.go +++ b/packages/tangle/tangle.go @@ -23,6 +23,9 @@ const ( PrefixMissingMessage cacheTime = 20 * time.Second + + // DBSequenceNumber defines the db sequence number. + DBSequenceNumber = "seq" ) // Tangle represents the base layer of messages. diff --git a/plugins/dashboard/explorer_routes.go b/plugins/dashboard/explorer_routes.go index 5664dd87..6e0887a5 100644 --- a/plugins/dashboard/explorer_routes.go +++ b/plugins/dashboard/explorer_routes.go @@ -6,8 +6,8 @@ import ( "github.com/iotaledger/goshimmer/dapps/valuetransfers" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address" - "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/tangle" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" + valuetangle "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/goshimmer/plugins/webapi/value/utils" "github.com/labstack/echo" @@ -40,7 +40,7 @@ type ExplorerMessage struct { Payload interface{} `json:"payload"` } -func createExplorerMessage(msg *message.Message) (*ExplorerMessage, error) { +func createExplorerMessage(msg *tangle.Message) (*ExplorerMessage, error) { messageID := msg.ID() cachedMessageMetadata := messagelayer.Tangle().MessageMetadata(messageID) defer cachedMessageMetadata.Release() @@ -87,7 +87,7 @@ type SearchResult struct { func setupExplorerRoutes(routeGroup *echo.Group) { routeGroup.GET("/message/:id", func(c echo.Context) (err error) { - messageID, err := message.NewID(c.Param("id")) + messageID, err := tangle.NewMessageID(c.Param("id")) if err != nil { return } @@ -125,8 +125,8 @@ func setupExplorerRoutes(routeGroup *echo.Group) { result.Address = addr } - case message.IDLength: - messageID, err := message.NewID(search) + case tangle.MessageIDLength: + messageID, err := tangle.NewMessageID(search) if err != nil { return fmt.Errorf("%w: search ID %s", ErrInvalidParameter, search) } @@ -144,8 +144,8 @@ func setupExplorerRoutes(routeGroup *echo.Group) { }) } -func findMessage(messageID message.ID) (explorerMsg *ExplorerMessage, err error) { - if !messagelayer.Tangle().Message(messageID).Consume(func(msg *message.Message) { +func findMessage(messageID tangle.MessageID) (explorerMsg *ExplorerMessage, err error) { + if !messagelayer.Tangle().Message(messageID).Consume(func(msg *tangle.Message) { explorerMsg, err = createExplorerMessage(msg) }) { err = fmt.Errorf("%w: message %s", ErrNotFound, messageID.String()) @@ -167,7 +167,7 @@ func findAddress(strAddress string) (*ExplorerAddress, error) { // get outputids by address for id, cachedOutput := range valuetransfers.Tangle().OutputsOnAddress(address) { - cachedOutput.Consume(func(output *tangle.Output) { + cachedOutput.Consume(func(output *valuetangle.Output) { // iterate balances var b []utils.Balance @@ -178,7 +178,7 @@ func findAddress(strAddress string) (*ExplorerAddress, error) { }) } var solidificationTime int64 - if !valuetransfers.Tangle().TransactionMetadata(output.TransactionID()).Consume(func(txMeta *tangle.TransactionMetadata) { + if !valuetransfers.Tangle().TransactionMetadata(output.TransactionID()).Consume(func(txMeta *valuetangle.TransactionMetadata) { inclusionState.Confirmed = txMeta.Confirmed() inclusionState.Liked = txMeta.Liked() inclusionState.Rejected = txMeta.Rejected() diff --git a/plugins/dashboard/livefeed.go b/plugins/dashboard/livefeed.go index 95bf6c54..b7b0ea30 100644 --- a/plugins/dashboard/livefeed.go +++ b/plugins/dashboard/livefeed.go @@ -3,9 +3,8 @@ package dashboard import ( "time" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle" "github.com/iotaledger/goshimmer/packages/shutdown" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/daemon" "github.com/iotaledger/hive.go/events" @@ -18,7 +17,7 @@ var liveFeedWorkerPool *workerpool.WorkerPool func configureLiveFeed() { liveFeedWorkerPool = workerpool.New(func(task workerpool.Task) { - task.Param(0).(*message.CachedMessage).Consume(func(message *message.Message) { + task.Param(0).(*tangle.CachedMessage).Consume(func(message *tangle.Message) { broadcastWsMessage(&wsmsg{MsgTypeMessage, &msg{message.ID().String(), 0}}) }) diff --git a/plugins/dashboard/payload_handler.go b/plugins/dashboard/payload_handler.go index e7808408..ca69d6bc 100644 --- a/plugins/dashboard/payload_handler.go +++ b/plugins/dashboard/payload_handler.go @@ -8,7 +8,7 @@ import ( drngpayload "github.com/iotaledger/goshimmer/packages/binary/drng/payload" drngheader "github.com/iotaledger/goshimmer/packages/binary/drng/payload/header" cb "github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectivebeacon/payload" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" syncbeaconpayload "github.com/iotaledger/goshimmer/plugins/syncbeacon/payload" "github.com/iotaledger/hive.go/marshalutil" ) @@ -77,13 +77,13 @@ type Balance struct { // ProcessPayload returns different structs regarding to the // payload type. -func ProcessPayload(p payload.Payload) interface{} { +func ProcessPayload(p tangle.Payload) interface{} { switch p.Type() { - case payload.DataType: + case tangle.DataType: // data payload return BasicPayload{ ContentTitle: "Data", - Content: p.(*payload.Data).Data(), + Content: p.(*tangle.DataPayload).Data(), } case faucetpayload.Type: // faucet payload @@ -109,7 +109,7 @@ func ProcessPayload(p payload.Payload) interface{} { } // processDrngPayload handles the subtypes of Drng payload -func processDrngPayload(p payload.Payload) (dp DrngPayload) { +func processDrngPayload(p tangle.Payload) (dp DrngPayload) { var subpayload interface{} marshalUtil := marshalutil.New(p.Bytes()) drngPayload, _ := drngpayload.Parse(marshalUtil) @@ -139,7 +139,7 @@ func processDrngPayload(p payload.Payload) (dp DrngPayload) { } // processDrngPayload handles the subtypes of Drng payload -func processSyncBeaconPayload(p payload.Payload) (dp SyncBeaconPayload) { +func processSyncBeaconPayload(p tangle.Payload) (dp SyncBeaconPayload) { syncBeaconPayload, ok := p.(*syncbeaconpayload.Payload) if !ok { log.Info("could not cast payload to sync beacon object") @@ -152,7 +152,7 @@ func processSyncBeaconPayload(p payload.Payload) (dp SyncBeaconPayload) { } // processValuePayload handles Value payload -func processValuePayload(p payload.Payload) (vp ValuePayload) { +func processValuePayload(p tangle.Payload) (vp ValuePayload) { marshalUtil := marshalutil.New(p.Bytes()) v, _ := valuepayload.Parse(marshalUtil) diff --git a/plugins/dashboard/visualizer.go b/plugins/dashboard/visualizer.go index 271e8020..d33e669c 100644 --- a/plugins/dashboard/visualizer.go +++ b/plugins/dashboard/visualizer.go @@ -1,9 +1,8 @@ package dashboard import ( - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle" "github.com/iotaledger/goshimmer/packages/shutdown" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/daemon" "github.com/iotaledger/hive.go/events" @@ -34,9 +33,9 @@ func configureVisualizer() { visualizerWorkerPool = workerpool.New(func(task workerpool.Task) { switch x := task.Param(0).(type) { - case *message.CachedMessage: + case *tangle.CachedMessage: sendVertex(x, task.Param(1).(*tangle.CachedMessageMetadata)) - case message.ID: + case tangle.MessageID: sendTipInfo(x, task.Param(1).(bool)) } @@ -44,7 +43,7 @@ func configureVisualizer() { }, workerpool.WorkerCount(visualizerWorkerCount), workerpool.QueueSize(visualizerWorkerQueueSize)) } -func sendVertex(cachedMessage *message.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) { +func sendVertex(cachedMessage *tangle.CachedMessage, cachedMessageMetadata *tangle.CachedMessageMetadata) { defer cachedMessage.Release() defer cachedMessageMetadata.Release() @@ -60,7 +59,7 @@ func sendVertex(cachedMessage *message.CachedMessage, cachedMessageMetadata *tan }}, true) } -func sendTipInfo(messageID message.ID, isTip bool) { +func sendTipInfo(messageID tangle.MessageID, isTip bool) { broadcastWsMessage(&wsmsg{MsgTypeTipInfo, &tipinfo{ ID: messageID.String(), IsTip: isTip, @@ -78,11 +77,11 @@ func runVisualizer() { } }) - notifyNewTip := events.NewClosure(func(messageId message.ID) { + notifyNewTip := events.NewClosure(func(messageId tangle.MessageID) { visualizerWorkerPool.TrySubmit(messageId, true) }) - notifyDeletedTip := events.NewClosure(func(messageId message.ID) { + notifyDeletedTip := events.NewClosure(func(messageId tangle.MessageID) { visualizerWorkerPool.TrySubmit(messageId, false) }) diff --git a/plugins/drng/plugin.go b/plugins/drng/plugin.go index add3f358..f23131db 100644 --- a/plugins/drng/plugin.go +++ b/plugins/drng/plugin.go @@ -6,8 +6,7 @@ import ( "github.com/iotaledger/goshimmer/packages/binary/drng" "github.com/iotaledger/goshimmer/packages/binary/drng/payload" "github.com/iotaledger/goshimmer/packages/binary/drng/payload/header" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/logger" @@ -46,7 +45,7 @@ func configureEvents() { messagelayer.Tangle().Events.MessageSolid.Attach(events.NewClosure(func(cachedMsgEvent *tangle.CachedMessageEvent) { cachedMsgEvent.MessageMetadata.Release() - cachedMsgEvent.Message.Consume(func(msg *message.Message) { + cachedMsgEvent.Message.Consume(func(msg *tangle.Message) { if msg.Payload().Type() != payload.Type { return } diff --git a/plugins/gossip/gossip.go b/plugins/gossip/gossip.go index 416acde3..300efc99 100644 --- a/plugins/gossip/gossip.go +++ b/plugins/gossip/gossip.go @@ -6,9 +6,9 @@ import ( "strconv" "sync" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" "github.com/iotaledger/goshimmer/packages/gossip" "github.com/iotaledger/goshimmer/packages/gossip/server" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/autopeering" "github.com/iotaledger/goshimmer/plugins/autopeering/local" "github.com/iotaledger/goshimmer/plugins/config" @@ -91,7 +91,7 @@ func start(shutdownSignal <-chan struct{}) { } // loads the given message from the message layer and returns it or an error if not found. -func loadMessage(msgID message.ID) ([]byte, error) { +func loadMessage(msgID tangle.MessageID) ([]byte, error) { cachedMessage := messagelayer.Tangle().Message(msgID) defer cachedMessage.Release() if !cachedMessage.Exists() { diff --git a/plugins/gossip/plugin.go b/plugins/gossip/plugin.go index dff27785..2bd6423d 100644 --- a/plugins/gossip/plugin.go +++ b/plugins/gossip/plugin.go @@ -4,10 +4,9 @@ import ( "sync" "time" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messagerequester" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle" "github.com/iotaledger/goshimmer/packages/gossip" "github.com/iotaledger/goshimmer/packages/shutdown" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/autopeering" "github.com/iotaledger/goshimmer/plugins/config" "github.com/iotaledger/goshimmer/plugins/messagelayer" @@ -143,7 +142,7 @@ func configureMessageLayer() { })) // request missing messages - messagelayer.MessageRequester().Events.SendRequest.Attach(events.NewClosure(func(sendRequest *messagerequester.SendRequestEvent) { + messagelayer.MessageRequester().Events.SendRequest.Attach(events.NewClosure(func(sendRequest *tangle.SendRequestEvent) { mgr.RequestMessage(sendRequest.ID[:]) })) } diff --git a/plugins/gossip/tips_broadcaster.go b/plugins/gossip/tips_broadcaster.go index fb930998..529662fc 100644 --- a/plugins/gossip/tips_broadcaster.go +++ b/plugins/gossip/tips_broadcaster.go @@ -4,7 +4,7 @@ import ( "container/list" "sync" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/timeutil" @@ -15,17 +15,17 @@ const ( tipsBroadcasterName = PluginName + "[TipsBroadcaster]" ) -var tips = tiplist{dict: make(map[message.ID]*list.Element)} +var tips = tiplist{dict: make(map[tangle.MessageID]*list.Element)} type tiplist struct { mu sync.Mutex - dict map[message.ID]*list.Element + dict map[tangle.MessageID]*list.Element list list.List iterator *list.Element } -func (s *tiplist) AddTip(id message.ID) { +func (s *tiplist) AddTip(id tangle.MessageID) { s.mu.Lock() defer s.mu.Unlock() @@ -39,7 +39,7 @@ func (s *tiplist) AddTip(id message.ID) { } } -func (s *tiplist) RemoveTip(id message.ID) { +func (s *tiplist) RemoveTip(id tangle.MessageID) { s.mu.Lock() defer s.mu.Unlock() @@ -54,14 +54,14 @@ func (s *tiplist) RemoveTip(id message.ID) { } } -func (s *tiplist) Next() message.ID { +func (s *tiplist) Next() tangle.MessageID { s.mu.Lock() defer s.mu.Unlock() if s.iterator == nil { - return message.EmptyID + return tangle.EmptyMessageID } - id := s.iterator.Value.(message.ID) + id := s.iterator.Value.(tangle.MessageID) s.next(s.iterator) return id } @@ -94,14 +94,14 @@ func startTipBroadcaster(shutdownSignal <-chan struct{}) { // broadcasts the next oldest tip from the tip pool to all connected neighbors. func broadcastNextOldestTip() { msgID := tips.Next() - if msgID == message.EmptyID { + if msgID == tangle.EmptyMessageID { return } broadcastMessage(msgID) } // broadcasts the given message to all neighbors if it exists. -func broadcastMessage(msgID message.ID) { +func broadcastMessage(msgID tangle.MessageID) { msgBytes, err := loadMessage(msgID) if err != nil { return diff --git a/plugins/issuer/plugin.go b/plugins/issuer/plugin.go index 11c01ec6..2d75f13b 100644 --- a/plugins/issuer/plugin.go +++ b/plugins/issuer/plugin.go @@ -4,8 +4,7 @@ import ( "fmt" goSync "sync" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/goshimmer/plugins/syncbeaconfollower" "github.com/iotaledger/hive.go/node" @@ -32,7 +31,7 @@ func configure(_ *node.Plugin) {} // IssuePayload issues a payload to the message layer. // If the node is not synchronized an error is returned. -func IssuePayload(payload payload.Payload) (*message.Message, error) { +func IssuePayload(payload tangle.Payload) (*tangle.Message, error) { if !syncbeaconfollower.Synced() { return nil, fmt.Errorf("can't issue payload: %w", syncbeaconfollower.ErrNodeNotSynchronized) } diff --git a/plugins/messagelayer/plugin.go b/plugins/messagelayer/plugin.go index 571836bc..b7972915 100644 --- a/plugins/messagelayer/plugin.go +++ b/plugins/messagelayer/plugin.go @@ -3,13 +3,8 @@ package messagelayer import ( "sync" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messagefactory" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messageparser" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messagerequester" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tipselector" "github.com/iotaledger/goshimmer/packages/shutdown" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/autopeering/local" "github.com/iotaledger/goshimmer/plugins/database" "github.com/iotaledger/hive.go/daemon" @@ -21,23 +16,21 @@ import ( const ( // PluginName defines the plugin name. PluginName = "MessageLayer" - // DBSequenceNumber defines the db sequence number. - DBSequenceNumber = "seq" ) var ( // plugin is the plugin instance of the message layer plugin. plugin *node.Plugin pluginOnce sync.Once - messageParser *messageparser.MessageParser + messageParser *tangle.MessageParser msgParserOnce sync.Once - messageRequester *messagerequester.MessageRequester + messageRequester *tangle.MessageRequester msgReqOnce sync.Once - tipSelector *tipselector.TipSelector + tipSelector *tangle.MessageTipSelector tipSelectorOnce sync.Once _tangle *tangle.Tangle tangleOnce sync.Once - messageFactory *messagefactory.MessageFactory + messageFactory *tangle.MessageFactory msgFactoryOnce sync.Once log *logger.Logger ) @@ -51,17 +44,17 @@ func Plugin() *node.Plugin { } // MessageParser gets the messageParser instance. -func MessageParser() *messageparser.MessageParser { +func MessageParser() *tangle.MessageParser { msgParserOnce.Do(func() { - messageParser = messageparser.New() + messageParser = tangle.NewMessageParser() }) return messageParser } // TipSelector gets the tipSelector instance. -func TipSelector() *tipselector.TipSelector { +func TipSelector() *tangle.MessageTipSelector { tipSelectorOnce.Do(func() { - tipSelector = tipselector.New() + tipSelector = tangle.NewMessageTipSelector() }) return tipSelector } @@ -76,18 +69,18 @@ func Tangle() *tangle.Tangle { } // MessageFactory gets the messageFactory instance. -func MessageFactory() *messagefactory.MessageFactory { +func MessageFactory() *tangle.MessageFactory { msgFactoryOnce.Do(func() { - messageFactory = messagefactory.New(database.Store(), []byte(DBSequenceNumber), local.GetInstance().LocalIdentity(), TipSelector()) + messageFactory = tangle.NewMessageFactory(database.Store(), []byte(tangle.DBSequenceNumber), local.GetInstance().LocalIdentity(), TipSelector()) }) return messageFactory } // MessageRequester gets the messageRequester instance. -func MessageRequester() *messagerequester.MessageRequester { +func MessageRequester() *tangle.MessageRequester { msgReqOnce.Do(func() { // load all missing messages on start up - messageRequester = messagerequester.New(Tangle().MissingMessages()) + messageRequester = tangle.NewMessageRequester(Tangle().MissingMessages()) }) return messageRequester } @@ -109,7 +102,7 @@ func configure(*node.Plugin) { })) // setup messageParser - messageParser.Events.MessageParsed.Attach(events.NewClosure(func(msgParsedEvent *messageparser.MessageParsedEvent) { + messageParser.Events.MessageParsed.Attach(events.NewClosure(func(msgParsedEvent *tangle.MessageParsedEvent) { // TODO: ADD PEER _tangle.AttachMessage(msgParsedEvent.Message) })) @@ -118,7 +111,7 @@ func configure(*node.Plugin) { _tangle.Events.MessageMissing.Attach(events.NewClosure(messageRequester.StartRequest)) _tangle.Events.MissingMessageReceived.Attach(events.NewClosure(func(cachedMsgEvent *tangle.CachedMessageEvent) { cachedMsgEvent.MessageMetadata.Release() - cachedMsgEvent.Message.Consume(func(msg *message.Message) { + cachedMsgEvent.Message.Consume(func(msg *tangle.Message) { messageRequester.StopRequest(msg.ID()) }) })) @@ -129,7 +122,7 @@ func configure(*node.Plugin) { cachedMsgEvent.Message.Consume(tipSelector.AddTip) })) - MessageRequester().Events.MissingMessageAppeared.Attach(events.NewClosure(func(missingMessageAppeared *messagerequester.MissingMessageAppearedEvent) { + MessageRequester().Events.MissingMessageAppeared.Attach(events.NewClosure(func(missingMessageAppeared *tangle.MissingMessageAppearedEvent) { _tangle.DeleteMissingMessage(missingMessageAppeared.ID) })) } diff --git a/plugins/metrics/message.go b/plugins/metrics/message.go index e9041728..c32fc9cf 100644 --- a/plugins/metrics/message.go +++ b/plugins/metrics/message.go @@ -3,8 +3,8 @@ package metrics import ( "time" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" "github.com/iotaledger/goshimmer/packages/metrics" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/syncutils" "go.uber.org/atomic" @@ -49,7 +49,7 @@ var ( measuredReceivedMPS atomic.Uint64 // Number of messages per payload type since start of the node. - messageCountPerPayload = make(map[payload.Type]uint64) + messageCountPerPayload = make(map[tangle.PayloadType]uint64) // protect map from concurrent read/write. messageCountPerPayloadMutex syncutils.RWMutex @@ -66,12 +66,12 @@ func MessageTotalCountSinceStart() uint64 { } // MessageCountSinceStartPerPayload returns a map of message payload types and their count since the start of the node. -func MessageCountSinceStartPerPayload() map[payload.Type]uint64 { +func MessageCountSinceStartPerPayload() map[tangle.PayloadType]uint64 { messageCountPerPayloadMutex.RLock() defer messageCountPerPayloadMutex.RUnlock() // copy the original map - copy := make(map[payload.Type]uint64) + copy := make(map[tangle.PayloadType]uint64) for key, element := range messageCountPerPayload { copy[key] = element } @@ -122,7 +122,7 @@ func ReceivedMessagesPerSecond() uint64 { ////// Handling data updates and measuring ////// -func increasePerPayloadCounter(p payload.Type) { +func increasePerPayloadCounter(p tangle.PayloadType) { messageCountPerPayloadMutex.Lock() defer messageCountPerPayloadMutex.Unlock() diff --git a/plugins/metrics/message_test.go b/plugins/metrics/message_test.go index 500322be..54467da5 100644 --- a/plugins/metrics/message_test.go +++ b/plugins/metrics/message_test.go @@ -6,8 +6,8 @@ import ( valuepayload "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload" drngpayload "github.com/iotaledger/goshimmer/packages/binary/drng/payload" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" "github.com/iotaledger/goshimmer/packages/metrics" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/events" "github.com/magiconair/properties/assert" @@ -21,13 +21,13 @@ func TestMessageCountPerPayload(t *testing.T) { increasePerPayloadCounter(valuepayload.Type) } assert.Equal(t, MessageTotalCountSinceStart(), (uint64)(10)) - assert.Equal(t, MessageCountSinceStartPerPayload(), map[payload.Type]uint64{valuepayload.Type: 10}) + assert.Equal(t, MessageCountSinceStartPerPayload(), map[tangle.PayloadType]uint64{valuepayload.Type: 10}) // simulate attaching 5 drng payloads for i := 0; i < 5; i++ { increasePerPayloadCounter(drngpayload.Type) } assert.Equal(t, MessageTotalCountSinceStart(), (uint64)(15)) - assert.Equal(t, MessageCountSinceStartPerPayload(), map[payload.Type]uint64{valuepayload.Type: 10, drngpayload.Type: 5}) + assert.Equal(t, MessageCountSinceStartPerPayload(), map[tangle.PayloadType]uint64{valuepayload.Type: 10, drngpayload.Type: 5}) } func TestMessageTips(t *testing.T) { diff --git a/plugins/metrics/plugin.go b/plugins/metrics/plugin.go index f9ad4e2d..5fdd58da 100644 --- a/plugins/metrics/plugin.go +++ b/plugins/metrics/plugin.go @@ -6,10 +6,9 @@ import ( "github.com/iotaledger/goshimmer/dapps/valuetransfers" valuetangle "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/tangle" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle" "github.com/iotaledger/goshimmer/packages/metrics" "github.com/iotaledger/goshimmer/packages/shutdown" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/packages/vote" "github.com/iotaledger/goshimmer/plugins/analysis/server" "github.com/iotaledger/goshimmer/plugins/autopeering" @@ -102,7 +101,7 @@ func registerLocalMetrics() { })) - messagelayer.Tangle().Events.MessageRemoved.Attach(events.NewClosure(func(messageId message.ID) { + messagelayer.Tangle().Events.MessageRemoved.Attach(events.NewClosure(func(messageId tangle.MessageID) { // MessageRemoved triggered when the message gets removed from database. messageTotalCountDB.Dec() })) @@ -123,7 +122,7 @@ func registerLocalMetrics() { })) // fired when a message gets added to missing message storage - messagelayer.Tangle().Events.MessageMissing.Attach(events.NewClosure(func(messageId message.ID) { + messagelayer.Tangle().Events.MessageMissing.Attach(events.NewClosure(func(messageId tangle.MessageID) { missingMessageCountDB.Inc() })) diff --git a/plugins/pow/plugin.go b/plugins/pow/plugin.go index d8056d6d..5b4f04d0 100644 --- a/plugins/pow/plugin.go +++ b/plugins/pow/plugin.go @@ -1,8 +1,7 @@ package pow import ( - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messagefactory" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/messageparser/builtinfilters" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/node" @@ -30,6 +29,6 @@ func run(*node.Plugin) { log.Infof("%s started: difficult=%d", PluginName, difficulty) - messagelayer.MessageParser().AddBytesFilter(builtinfilters.NewPowFilter(worker, difficulty)) - messagelayer.MessageFactory().SetWorker(messagefactory.WorkerFunc(DoPOW)) + messagelayer.MessageParser().AddBytesFilter(tangle.NewPowFilter(worker, difficulty)) + messagelayer.MessageFactory().SetWorker(tangle.WorkerFunc(DoPOW)) } diff --git a/plugins/prometheus/tangle.go b/plugins/prometheus/tangle.go index 71061179..da20c98a 100644 --- a/plugins/prometheus/tangle.go +++ b/plugins/prometheus/tangle.go @@ -1,7 +1,7 @@ package prometheus import ( - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/metrics" "github.com/prometheus/client_golang/prometheus" ) @@ -92,7 +92,7 @@ func collectTangleMetrics() { messageTips.Set(float64(metrics.MessageTips())) msgCountPerPayload := metrics.MessageCountSinceStartPerPayload() for payloadType, count := range msgCountPerPayload { - messagePerTypeCount.WithLabelValues(payload.Name(payloadType)).Set(float64(count)) + messagePerTypeCount.WithLabelValues(tangle.Name(payloadType)).Set(float64(count)) } messageTotalCount.Set(float64(metrics.MessageTotalCountSinceStart())) messageTotalCountDB.Set(float64(metrics.MessageTotalCountDB())) diff --git a/plugins/syncbeacon/payload/payload.go b/plugins/syncbeacon/payload/payload.go index aaa422dd..59f4d547 100644 --- a/plugins/syncbeacon/payload/payload.go +++ b/plugins/syncbeacon/payload/payload.go @@ -3,7 +3,8 @@ package payload import ( "fmt" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/hive.go/stringify" ) @@ -14,11 +15,11 @@ const ( ) // Type is the type of the syncbeacon payload. -var Type = payload.Type(200) +var Type = tangle.PayloadType(200) // Payload represents the syncbeacon payload type Payload struct { - payloadType payload.Type + payloadType tangle.PayloadType sentTime int64 } @@ -61,7 +62,7 @@ func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) { } // Type returns the type of the Payload. -func (p *Payload) Type() payload.Type { +func (p *Payload) Type() tangle.PayloadType { return p.payloadType } @@ -97,7 +98,7 @@ func IsSyncBeaconPayload(p *Payload) bool { } func init() { - payload.RegisterType(Type, ObjectName, func(data []byte) (payload payload.Payload, err error) { + tangle.RegisterPayloadType(Type, ObjectName, func(data []byte) (payload tangle.Payload, err error) { payload, _, err = FromBytes(data) return diff --git a/plugins/syncbeaconfollower/plugin.go b/plugins/syncbeaconfollower/plugin.go index bbe4a996..4e103fae 100644 --- a/plugins/syncbeaconfollower/plugin.go +++ b/plugins/syncbeaconfollower/plugin.go @@ -5,9 +5,8 @@ import ( "sync" "time" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/tangle" "github.com/iotaledger/goshimmer/packages/shutdown" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/config" "github.com/iotaledger/goshimmer/plugins/messagelayer" syncbeacon_payload "github.com/iotaledger/goshimmer/plugins/syncbeacon/payload" @@ -43,7 +42,7 @@ const ( // Status represents the status of a beacon node consisting of latest messageID, sentTime and sync status. type Status struct { - MsgID message.ID + MsgID tangle.MessageID SentTime int64 Synced bool } @@ -156,7 +155,7 @@ func configure(_ *node.Plugin) { continue } currentBeacons[pubKey] = &Status{ - MsgID: message.EmptyID, + MsgID: tangle.EmptyMessageID, Synced: false, SentTime: 0, } @@ -168,7 +167,7 @@ func configure(_ *node.Plugin) { messagelayer.Tangle().Events.MessageSolid.Attach(events.NewClosure(func(cachedMsgEvent *tangle.CachedMessageEvent) { cachedMsgEvent.MessageMetadata.Release() - cachedMsgEvent.Message.Consume(func(msg *message.Message) { + cachedMsgEvent.Message.Consume(func(msg *tangle.Message) { messagePayload := msg.Payload() if messagePayload.Type() != syncbeacon_payload.Type { return @@ -201,7 +200,7 @@ func configure(_ *node.Plugin) { // handlePayload handles the received payload. It does the following checks: // The time that payload was sent is not greater than CfgSyncBeaconMaxTimeWindowSec. If the duration is longer than CfgSyncBeaconMaxTimeWindowSec, we consider that beacon to be out of sync till we receive a newer payload. // More than syncPercentage of followed nodes are also synced, the node is set to synced. Otherwise, its set as desynced. -func handlePayload(syncBeaconPayload *syncbeacon_payload.Payload, issuerPublicKey ed25519.PublicKey, msgID message.ID) { +func handlePayload(syncBeaconPayload *syncbeacon_payload.Payload, issuerPublicKey ed25519.PublicKey, msgID tangle.MessageID) { synced := true dur := time.Since(time.Unix(0, syncBeaconPayload.SentTime())) if dur.Seconds() > beaconMaxTimeWindowSec { @@ -240,7 +239,7 @@ func cleanupFollowNodes() { mutex.Lock() defer mutex.Unlock() for publicKey, status := range currentBeacons { - if status.MsgID != message.EmptyID { + if status.MsgID != tangle.EmptyMessageID { dur := time.Since(time.Unix(0, status.SentTime)) if dur.Seconds() > beaconMaxTimeOfflineSec { currentBeacons[publicKey].Synced = false diff --git a/plugins/webapi/data/plugin.go b/plugins/webapi/data/plugin.go index 07696d65..96a31141 100644 --- a/plugins/webapi/data/plugin.go +++ b/plugins/webapi/data/plugin.go @@ -4,7 +4,7 @@ import ( "net/http" "sync" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/issuer" "github.com/iotaledger/goshimmer/plugins/webapi" "github.com/iotaledger/hive.go/logger" @@ -44,7 +44,7 @@ func broadcastData(c echo.Context) error { return c.JSON(http.StatusBadRequest, Response{Error: err.Error()}) } - msg, err := issuer.IssuePayload(payload.NewData(request.Data)) + msg, err := issuer.IssuePayload(tangle.NewDataPayload(request.Data)) if err != nil { return c.JSON(http.StatusBadRequest, Response{Error: err.Error()}) } diff --git a/plugins/webapi/message/plugin.go b/plugins/webapi/message/plugin.go index 0c8c581d..2d00e345 100644 --- a/plugins/webapi/message/plugin.go +++ b/plugins/webapi/message/plugin.go @@ -4,7 +4,7 @@ import ( "net/http" "sync" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/goshimmer/plugins/webapi" "github.com/iotaledger/hive.go/logger" @@ -52,7 +52,7 @@ func findMessageByID(c echo.Context) error { for _, id := range request.IDs { log.Info("Received:", id) - msgID, err := message.NewID(id) + msgID, err := tangle.NewMessageID(id) if err != nil { log.Info(err) return c.JSON(http.StatusBadRequest, Response{Error: err.Error()}) diff --git a/plugins/webapi/message/sendPayload.go b/plugins/webapi/message/sendPayload.go index 6dd31009..769239e8 100644 --- a/plugins/webapi/message/sendPayload.go +++ b/plugins/webapi/message/sendPayload.go @@ -3,7 +3,7 @@ package message import ( "net/http" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/issuer" "github.com/labstack/echo" ) @@ -17,7 +17,7 @@ func sendPayload(c echo.Context) error { return c.JSON(http.StatusBadRequest, MsgResponse{Error: err.Error()}) } - parsedPayload, _, err := payload.FromBytes(request.Payload) + parsedPayload, _, err := tangle.PayloadFromBytes(request.Payload) if err != nil { return c.JSON(http.StatusBadRequest, MsgResponse{Error: err.Error()}) } diff --git a/plugins/webapi/tools/message/pastcone/handler.go b/plugins/webapi/tools/message/pastcone/handler.go index 404d716b..b82fe48d 100644 --- a/plugins/webapi/tools/message/pastcone/handler.go +++ b/plugins/webapi/tools/message/pastcone/handler.go @@ -5,7 +5,7 @@ import ( "fmt" "net/http" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/labstack/echo" ) @@ -18,7 +18,7 @@ func Handler(c echo.Context) error { return c.JSON(http.StatusBadRequest, Response{Error: err.Error()}) } - msgID, err := message.NewID(request.ID) + msgID, err := tangle.NewMessageID(request.ID) if err != nil { return c.JSON(http.StatusBadRequest, Response{Error: err.Error()}) } @@ -28,14 +28,14 @@ func Handler(c echo.Context) error { stack.PushBack(msgID) // keep track of submitted checks (to not re-add something to the stack that is already in it) // searching in double-linked list is quite expensive, but not in a map - submitted := make(map[message.ID]bool) + submitted := make(map[tangle.MessageID]bool) // process messages in stack, try to request parents until we end up at the genesis for stack.Len() > 0 { checkedMessageCount++ // pop the first element from stack currentMsgElement := stack.Front() - currentMsgID := currentMsgElement.Value.(message.ID) + currentMsgID := currentMsgElement.Value.(tangle.MessageID) stack.Remove(currentMsgElement) // ask node if it has it @@ -55,15 +55,15 @@ func Handler(c echo.Context) error { msgObject.Release() msgMetadataObject.Release() - if parent2ID == message.EmptyID && msg.Parent1ID() == message.EmptyID { + if parent2ID == tangle.EmptyMessageID && msg.Parent1ID() == tangle.EmptyMessageID { // msg only attaches to genesis continue } else { - if !submitted[parent2ID] && parent2ID != message.EmptyID { + if !submitted[parent2ID] && parent2ID != tangle.EmptyMessageID { stack.PushBack(parent2ID) submitted[parent2ID] = true } - if !submitted[parent1ID] && parent1ID != message.EmptyID { + if !submitted[parent1ID] && parent1ID != tangle.EmptyMessageID { stack.PushBack(parent1ID) submitted[parent1ID] = true } diff --git a/tools/integration-tests/tester/tests/testutil.go b/tools/integration-tests/tester/tests/testutil.go index d6b8c98b..53d6b4a4 100644 --- a/tools/integration-tests/tester/tests/testutil.go +++ b/tools/integration-tests/tester/tests/testutil.go @@ -13,7 +13,7 @@ import ( "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address/signaturescheme" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction" - "github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload" + "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/webapi/value/utils" "github.com/iotaledger/goshimmer/tools/integration-tests/tester/framework" "github.com/iotaledger/hive.go/types" @@ -70,7 +70,7 @@ func SendDataMessage(t *testing.T, peer *framework.Peer, data []byte, number int number: number, id: id, // save payload to be able to compare API response - data: payload.NewData(data).Bytes(), + data: tangle.NewDataPayload(data).Bytes(), issuerPublicKey: peer.Identity.PublicKey().String(), } return id, sent -- GitLab