From 3ff90451786799cab1a71b4099fa293fa1d8cff8 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 26 Jun 2020 11:49:14 +0300 Subject: [PATCH 01/11] gomod: import go-libp2p-pubsub-tracer@feat/traced-lib and go-libp2p --- lotus-soup/go.mod | 3 ++- lotus-soup/go.sum | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lotus-soup/go.mod b/lotus-soup/go.mod index 91704679b..183ee495c 100644 --- a/lotus-soup/go.mod +++ b/lotus-soup/go.mod @@ -3,7 +3,6 @@ module github.com/filecoin-project/oni/lotus-soup go 1.14 require ( - github.com/davecgh/go-spew v1.1.1 github.com/drand/drand v0.9.2-0.20200616080806-a94e9c1636a4 github.com/filecoin-project/go-address v0.0.2-0.20200504173055-8b6f2fb2b3ef github.com/filecoin-project/go-fil-markets v0.3.0 @@ -18,7 +17,9 @@ require ( github.com/ipfs/go-merkledag v0.3.1 github.com/ipfs/go-unixfs v0.2.4 github.com/ipld/go-car v0.1.1-0.20200526133713-1c7508d55aae + github.com/libp2p/go-libp2p v0.10.0 github.com/libp2p/go-libp2p-core v0.6.0 + github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626081338-a4828eefb15e github.com/multiformats/go-multiaddr v0.2.2 github.com/testground/sdk-go v0.2.3-0.20200617132925-2e4d69f9ba38 ) diff --git a/lotus-soup/go.sum b/lotus-soup/go.sum index 433b3cb64..b10bef3b9 100644 --- a/lotus-soup/go.sum +++ b/lotus-soup/go.sum @@ -861,6 +861,8 @@ github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uz github.com/libp2p/go-libp2p-pubsub v0.3.2-0.20200527132641-c0712c6e92cf/go.mod h1:TxPOBuo1FPdsTjFnv+FGZbNbWYsp74Culx+4ViQpato= github.com/libp2p/go-libp2p-pubsub v0.3.2 h1:k3cJm5JW5mjaWZkobS50sJLJWaB2mBi0HW4eRlE8mSo= github.com/libp2p/go-libp2p-pubsub v0.3.2/go.mod h1:Uss7/Cfz872KggNb+doCVPHeCDmXB7z500m/R8DaAUk= +github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626081338-a4828eefb15e h1:FCNPEyaLEWlatmmVqccs/dfxOGJVHMCCEb0Sku1lTck= +github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626081338-a4828eefb15e/go.mod h1:8ZodgKS4qRLayfw9FDKDd9DX4C16/GMofDxSldG8QPI= github.com/libp2p/go-libp2p-quic-transport v0.1.1 h1:MFMJzvsxIEDEVKzO89BnB/FgvMj9WI4GDGUW2ArDPUA= github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= github.com/libp2p/go-libp2p-quic-transport v0.5.0 h1:BUN1lgYNUrtv4WLLQ5rQmC9MCJ6uEXusezGvYRNoJXE= From 1c2af85b20b6b4d90fd9c0ffdeb616fc9853b2bf Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 26 Jun 2020 11:49:24 +0300 Subject: [PATCH 02/11] pubsub tracer role --- lotus-soup/tracer.go | 90 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 lotus-soup/tracer.go diff --git a/lotus-soup/tracer.go b/lotus-soup/tracer.go new file mode 100644 index 000000000..414a1b8da --- /dev/null +++ b/lotus-soup/tracer.go @@ -0,0 +1,90 @@ +package main + +import ( + "context" + "crypto/rand" + "fmt" + "log" + + "github.com/testground/sdk-go/sync" + + "github.com/libp2p/go-libp2p" + "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/host" + "github.com/libp2p/go-libp2p-pubsub-tracer/traced" + + ma "github.com/multiformats/go-multiaddr" +) + +var ( + pubsubTracerTopic = sync.NewTopic("pubsubTracer", &PubsubTracerMsg{}) +) + +type PubsubTracer struct { + host host.Host + traced *traced.TraceCollector +} + +type PubsubTracerMsg struct { + Tracer []byte +} + +func (tr *PubsubTracer) Stop() { + tr.traced.Stop() + err := tr.host.Close() + if err != nil { + log.Printf("error closing host: %s", err) + } +} + +func preparePubsubTracer(t *TestEnvironment) (*PubsubTracer, error) { + ctx := context.Background() + + privk, _, err := crypto.GenerateEd25519Key(rand.Reader) + if err != nil { + return nil, err + } + + tracedIP := t.NetClient.MustGetDataNetworkIP().String() + tracedAddr := fmt.Sprintf("/ip4/%s/tcp/4001", tracedIP) + + host, err := libp2p.New(ctx, + libp2p.Identity(privk), + libp2p.ListenAddrStrings(tracedAddr), + ) + if err != nil { + return nil, err + } + + traced, err := traced.NewTraceCollector(host, "traced.logs") + if err != nil { + host.Close() + return nil, err + } + + tracedMultiaddrStr := fmt.Sprintf("%s/p2p/%s", tracedAddr, host.ID()) + t.RecordMessage("I am %s", tracedMultiaddrStr) + + tracedMultiaddr := ma.StringCast(tracedMultiaddrStr) + tracedMsg := &PubsubTracerMsg{Tracer: tracedMultiaddr.Bytes()} + t.SyncClient.MustPublish(ctx, pubsubTracerTopic, tracedMsg) + + t.RecordMessage("waiting for all nodes to be ready") + t.SyncClient.MustSignalAndWait(ctx, stateReady, t.TestInstanceCount) + + return &PubsubTracer{host: host, traced: traced}, nil +} + +func runPubsubTracer(t *TestEnvironment) error { + t.RecordMessage("running pubsub tracer") + tracer, err := preparePubsubTracer(t) + if err != nil { + return err + } + + defer tracer.Stop() + + ctx := context.Background() + t.SyncClient.MustSignalAndWait(ctx, stateDone, t.TestInstanceCount) + return nil +} From 71503cce8b8c0612f343d17834b28403fe60ed77 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 26 Jun 2020 11:58:56 +0300 Subject: [PATCH 03/11] add pubsub tracer config to scaffolding --- lotus-soup/node.go | 43 +++++++++++++++++++++++++++++++++++++------ lotus-soup/tracer.go | 4 ++-- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/lotus-soup/node.go b/lotus-soup/node.go index a57fb5f82..57d47d8f5 100644 --- a/lotus-soup/node.go +++ b/lotus-soup/node.go @@ -127,6 +127,11 @@ func prepareBootstrapper(t *TestEnvironment) (*Node, error) { ctx, cancel := context.WithTimeout(context.Background(), PrepareNodeTimeout) defer cancel() + pubsubTracer, err := getPubsubTracerConfig(ctx, t) + if err != nil { + return nil, err + } + clients := t.IntParam("clients") miners := t.IntParam("miners") nodes := clients + miners @@ -196,7 +201,7 @@ func prepareBootstrapper(t *TestEnvironment) (*Node, error) { node.Override(new(modules.Genesis), modtest.MakeGenesisMem(&genesisBuffer, genesisTemplate)), withListenAddress(bootstrapperIP), withBootstrapper(nil), - withPubsubConfig(true), + withPubsubConfig(true, pubsubTracer), drandOpt, ) if err != nil { @@ -250,6 +255,11 @@ func prepareMiner(t *TestEnvironment) (*Node, error) { ctx, cancel := context.WithTimeout(context.Background(), PrepareNodeTimeout) defer cancel() + pubsubTracer, err := getPubsubTracerConfig(ctx, t) + if err != nil { + return nil, err + } + drandOpt, err := getDrandConfig(ctx, t) if err != nil { return nil, err @@ -367,7 +377,7 @@ func prepareMiner(t *TestEnvironment) (*Node, error) { withGenesis(genesisMsg.Genesis), withListenAddress(minerIP), withBootstrapper(genesisMsg.Bootstrapper), - withPubsubConfig(false), + withPubsubConfig(false, pubsubTracer), drandOpt, ) if err != nil { @@ -473,6 +483,11 @@ func prepareClient(t *TestEnvironment) (*Node, error) { ctx, cancel := context.WithTimeout(context.Background(), PrepareNodeTimeout) defer cancel() + pubsubTracer, err := getPubsubTracerConfig(ctx, t) + if err != nil { + return nil, err + } + drandOpt, err := getDrandConfig(ctx, t) if err != nil { return nil, err @@ -506,7 +521,7 @@ func prepareClient(t *TestEnvironment) (*Node, error) { withGenesis(genesisMsg.Genesis), withListenAddress(clientIP), withBootstrapper(genesisMsg.Bootstrapper), - withPubsubConfig(false), + withPubsubConfig(false, pubsubTracer), drandOpt, ) if err != nil { @@ -571,11 +586,11 @@ func withBootstrapper(ab []byte) node.Option { }) } -func withPubsubConfig(bootstrapper bool) node.Option { +func withPubsubConfig(bootstrapper bool, pubsubTracer string) node.Option { return node.Override(new(*config.Pubsub), func() *config.Pubsub { return &config.Pubsub{ Bootstrapper: bootstrapper, - RemoteTracer: "", + RemoteTracer: pubsubTracer, } }) } @@ -670,6 +685,22 @@ func collectClientAddrs(t *TestEnvironment, ctx context.Context, clients int) ([ return addrs, nil } +func getPubsubTracerConfig(ctx context.Context, t *TestEnvironment) (string, error) { + if !t.BooleanParam("enable_pubsub_tracer") { + return "", nil + } + + ch := make(chan *PubsubTracerMsg) + sub := t.SyncClient.MustSubscribe(ctx, pubsubTracerTopic, ch) + + select { + case m := <-ch: + return m.Tracer, nil + case err := <-sub.Done(): + return "", fmt.Errorf("got error while waiting for clients addrs: %w", err) + } +} + func getDrandConfig(ctx context.Context, t *TestEnvironment) (node.Option, error) { beaconType := t.StringParam("random_beacon_type") switch beaconType { @@ -684,7 +715,7 @@ func getDrandConfig(ctx context.Context, t *TestEnvironment) (node.Option, error if err != nil { t.RecordMessage("error getting drand config: %w", err) return nil, err - + } t.RecordMessage("setting drand config: %v", cfg) return node.Options( diff --git a/lotus-soup/tracer.go b/lotus-soup/tracer.go index 414a1b8da..6a812bfa2 100644 --- a/lotus-soup/tracer.go +++ b/lotus-soup/tracer.go @@ -26,7 +26,7 @@ type PubsubTracer struct { } type PubsubTracerMsg struct { - Tracer []byte + Tracer string } func (tr *PubsubTracer) Stop() { @@ -66,7 +66,7 @@ func preparePubsubTracer(t *TestEnvironment) (*PubsubTracer, error) { t.RecordMessage("I am %s", tracedMultiaddrStr) tracedMultiaddr := ma.StringCast(tracedMultiaddrStr) - tracedMsg := &PubsubTracerMsg{Tracer: tracedMultiaddr.Bytes()} + tracedMsg := &PubsubTracerMsg{Tracer: tracedMultiaddr.String()} t.SyncClient.MustPublish(ctx, pubsubTracerTopic, tracedMsg) t.RecordMessage("waiting for all nodes to be ready") From 00f137ba3e5d07ddb14d0e955fec44879c283272 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 26 Jun 2020 12:04:20 +0300 Subject: [PATCH 04/11] add pubsub-tracer role to baseline --- lotus-soup/baseline.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lotus-soup/baseline.go b/lotus-soup/baseline.go index 6f5cf9678..df0e195b2 100644 --- a/lotus-soup/baseline.go +++ b/lotus-soup/baseline.go @@ -43,10 +43,11 @@ import ( // The we create a genesis block that allocates some funds to each node and collects // the presealed sectors. var baselineRoles = map[string]func(*TestEnvironment) error{ - "bootstrapper": runBootstrapper, - "miner": runMiner, - "client": runBaselineClient, - "drand": runDrandNode, + "bootstrapper": runBootstrapper, + "miner": runMiner, + "client": runBaselineClient, + "drand": runDrandNode, + "pubsub-tracer": runPubsubTracer, } func runBaselineClient(t *TestEnvironment) error { @@ -237,4 +238,3 @@ func extractCarData(ctx context.Context, rdata []byte, rpath string) []byte { } return rdata } - From 16149b919811314f4d362ea226684e685f2a5cc8 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 26 Jun 2020 12:05:08 +0300 Subject: [PATCH 05/11] add composition with pubsub tracing --- .../compositions/composition-tracer.toml | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 lotus-soup/compositions/composition-tracer.toml diff --git a/lotus-soup/compositions/composition-tracer.toml b/lotus-soup/compositions/composition-tracer.toml new file mode 100644 index 000000000..ec3e5dc5e --- /dev/null +++ b/lotus-soup/compositions/composition-tracer.toml @@ -0,0 +1,68 @@ +[metadata] + name = "lotus-soup" + author = "" + +[global] + plan = "lotus-soup" + case = "lotus-baseline" + total_instances = 7 + builder = "docker:go" + runner = "local:docker" + +[global.build_config] + enable_go_build_cache = true + +[[groups]] + id = "pubsub-tracer" + [groups.instances] + count = 1 + percentage = 0.0 + [groups.run] + [groups.run.test_params] + role = "pubsub-tracer" + +[[groups]] + id = "bootstrapper" + [groups.instances] + count = 1 + percentage = 0.0 + [groups.run] + [groups.run.test_params] + role = "bootstrapper" + clients = "3" + miners = "2" + balance = "2000000000" + sectors = "10" + random_beacon_type = "mock" + enable_pubsub_tracer = "true" + +[[groups]] + id = "miners" + [groups.instances] + count = 2 + percentage = 0.0 + [groups.run] + [groups.run.test_params] + role = "miner" + clients = "3" + miners = "2" + balance = "2000000000" + sectors = "10" + random_beacon_type = "mock" + enable_pubsub_tracer = "true" + + +[[groups]] + id = "clients" + [groups.instances] + count = 3 + percentage = 0.0 + [groups.run] + [groups.run.test_params] + role = "client" + clients = "3" + miners = "2" + balance = "2000000000" + sectors = "10" + random_beacon_type = "mock" + enable_pubsub_tracer = "true" From a612b77cee3ac717be85e2015be46341aa90b1c8 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 26 Jun 2020 12:16:36 +0300 Subject: [PATCH 06/11] simplify code by removing extraneous conversion to multiaddr just Cast to verify correctness and panic if something is wrong --- lotus-soup/tracer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lotus-soup/tracer.go b/lotus-soup/tracer.go index 6a812bfa2..9995bcd42 100644 --- a/lotus-soup/tracer.go +++ b/lotus-soup/tracer.go @@ -65,8 +65,8 @@ func preparePubsubTracer(t *TestEnvironment) (*PubsubTracer, error) { tracedMultiaddrStr := fmt.Sprintf("%s/p2p/%s", tracedAddr, host.ID()) t.RecordMessage("I am %s", tracedMultiaddrStr) - tracedMultiaddr := ma.StringCast(tracedMultiaddrStr) - tracedMsg := &PubsubTracerMsg{Tracer: tracedMultiaddr.String()} + _ = ma.StringCast(tracedMultiaddrStr) + tracedMsg := &PubsubTracerMsg{Tracer: tracedMultiaddrStr} t.SyncClient.MustPublish(ctx, pubsubTracerTopic, tracedMsg) t.RecordMessage("waiting for all nodes to be ready") From eb65f1e441b8de259c62c222d0411368e613fd46 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 26 Jun 2020 13:14:28 +0300 Subject: [PATCH 07/11] output the tracer logs under TestOutputPath --- lotus-soup/tracer.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lotus-soup/tracer.go b/lotus-soup/tracer.go index 9995bcd42..083f222e9 100644 --- a/lotus-soup/tracer.go +++ b/lotus-soup/tracer.go @@ -56,7 +56,8 @@ func preparePubsubTracer(t *TestEnvironment) (*PubsubTracer, error) { return nil, err } - traced, err := traced.NewTraceCollector(host, "traced.logs") + tracedDir := t.TestOutputsPath + "/traced.logs" + traced, err := traced.NewTraceCollector(host, tracedDir) if err != nil { host.Close() return nil, err From 30a6361a8f7332aba5b3997ff9b2372942553561 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 26 Jun 2020 14:06:45 +0300 Subject: [PATCH 08/11] fix typo Co-authored-by: Anton Evangelatov --- lotus-soup/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lotus-soup/node.go b/lotus-soup/node.go index 57d47d8f5..8a04b6775 100644 --- a/lotus-soup/node.go +++ b/lotus-soup/node.go @@ -697,7 +697,7 @@ func getPubsubTracerConfig(ctx context.Context, t *TestEnvironment) (string, err case m := <-ch: return m.Tracer, nil case err := <-sub.Done(): - return "", fmt.Errorf("got error while waiting for clients addrs: %w", err) + return "", fmt.Errorf("got error while waiting for pubsub tracer config: %w", err) } } From b1159b657de9fa33dc968252be08ea72b63c4a52 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 26 Jun 2020 14:10:39 +0300 Subject: [PATCH 09/11] log close errors with RecordMessage --- lotus-soup/tracer.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lotus-soup/tracer.go b/lotus-soup/tracer.go index 083f222e9..17a287615 100644 --- a/lotus-soup/tracer.go +++ b/lotus-soup/tracer.go @@ -4,7 +4,6 @@ import ( "context" "crypto/rand" "fmt" - "log" "github.com/testground/sdk-go/sync" @@ -29,12 +28,9 @@ type PubsubTracerMsg struct { Tracer string } -func (tr *PubsubTracer) Stop() { +func (tr *PubsubTracer) Stop() error { tr.traced.Stop() - err := tr.host.Close() - if err != nil { - log.Printf("error closing host: %s", err) - } + return tr.host.Close() } func preparePubsubTracer(t *TestEnvironment) (*PubsubTracer, error) { @@ -83,7 +79,12 @@ func runPubsubTracer(t *TestEnvironment) error { return err } - defer tracer.Stop() + defer func() { + err := tracer.Stop() + if err != nil { + t.RecordMessage("error stoping tracer: %s", err) + } + }() ctx := context.Background() t.SyncClient.MustSignalAndWait(ctx, stateDone, t.TestInstanceCount) From 909e0e401f4f0d5d346f9b55744e8e8d8c4f2d8e Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 26 Jun 2020 14:12:22 +0300 Subject: [PATCH 10/11] define enable_pubsub_tracer in manifest.toml --- lotus-soup/manifest.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lotus-soup/manifest.toml b/lotus-soup/manifest.toml index 6b75b00d1..f33fdd645 100644 --- a/lotus-soup/manifest.toml +++ b/lotus-soup/manifest.toml @@ -36,3 +36,6 @@ instances = { min = 1, max = 100, default = 5 } drand_period = { type = "duration", default="10s" } drand_threshold = { type = "int", default = 2 } drand_gossip_relay = { type = "bool", default = true } + + # Params relevant to pubsub tracing + enable_pubsub_tracer = { type = "bool", default = false } From 2a8333e0e40233feb295d3f641f6756345d80545 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 26 Jun 2020 17:16:50 +0300 Subject: [PATCH 11/11] gomod: update go-libp2p-pubsub-tracer@master --- lotus-soup/go.mod | 2 +- lotus-soup/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lotus-soup/go.mod b/lotus-soup/go.mod index 183ee495c..018902235 100644 --- a/lotus-soup/go.mod +++ b/lotus-soup/go.mod @@ -19,7 +19,7 @@ require ( github.com/ipld/go-car v0.1.1-0.20200526133713-1c7508d55aae github.com/libp2p/go-libp2p v0.10.0 github.com/libp2p/go-libp2p-core v0.6.0 - github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626081338-a4828eefb15e + github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 github.com/multiformats/go-multiaddr v0.2.2 github.com/testground/sdk-go v0.2.3-0.20200617132925-2e4d69f9ba38 ) diff --git a/lotus-soup/go.sum b/lotus-soup/go.sum index b10bef3b9..8116e54d0 100644 --- a/lotus-soup/go.sum +++ b/lotus-soup/go.sum @@ -861,8 +861,8 @@ github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uz github.com/libp2p/go-libp2p-pubsub v0.3.2-0.20200527132641-c0712c6e92cf/go.mod h1:TxPOBuo1FPdsTjFnv+FGZbNbWYsp74Culx+4ViQpato= github.com/libp2p/go-libp2p-pubsub v0.3.2 h1:k3cJm5JW5mjaWZkobS50sJLJWaB2mBi0HW4eRlE8mSo= github.com/libp2p/go-libp2p-pubsub v0.3.2/go.mod h1:Uss7/Cfz872KggNb+doCVPHeCDmXB7z500m/R8DaAUk= -github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626081338-a4828eefb15e h1:FCNPEyaLEWlatmmVqccs/dfxOGJVHMCCEb0Sku1lTck= -github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626081338-a4828eefb15e/go.mod h1:8ZodgKS4qRLayfw9FDKDd9DX4C16/GMofDxSldG8QPI= +github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 h1:2lH7rMlvDPSvXeOR+g7FE6aqiEwxtpxWKQL8uigk5fQ= +github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6/go.mod h1:8ZodgKS4qRLayfw9FDKDd9DX4C16/GMofDxSldG8QPI= github.com/libp2p/go-libp2p-quic-transport v0.1.1 h1:MFMJzvsxIEDEVKzO89BnB/FgvMj9WI4GDGUW2ArDPUA= github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= github.com/libp2p/go-libp2p-quic-transport v0.5.0 h1:BUN1lgYNUrtv4WLLQ5rQmC9MCJ6uEXusezGvYRNoJXE=