public async Task NodeStatus()
        {
            var cts = new CancellationTokenSource();

            var apvPrivateKey = new PrivateKey();
            var apv           = AppProtocolVersion.Sign(apvPrivateKey, 0);
            var genesisBlock  = BlockChain <EmptyAction> .MakeGenesisBlock(
                HashAlgorithmType.Of <SHA256>()
                );

            // 에러로 인하여 NineChroniclesNodeService 를 사용할 수 없습니다. https://git.io/JfS0M
            // 따라서 LibplanetNodeService로 비슷한 환경을 맞춥니다.
            // 1. 노드를 생성합니다.
            var seedNode = CreateLibplanetNodeService <EmptyAction>(genesisBlock, apv, apvPrivateKey.PublicKey);

            await StartAsync(seedNode.Swarm, cts.Token);

            var service = CreateLibplanetNodeService <EmptyAction>(genesisBlock, apv, apvPrivateKey.PublicKey, peers: new [] { seedNode.Swarm.AsPeer });

            // 2. NineChroniclesNodeService.ConfigureStandaloneContext(standaloneContext)를 호출합니다.
            // BlockChain 객체 공유 및 PreloadEnded, BootstrapEnded 이벤트 훅의 처리를 합니다.
            // BlockChain 객체 공유는 액션 타입이 달라 생략합니다.
            _ = service.BootstrapEnded.WaitAsync()
                .ContinueWith(task => StandaloneContextFx.BootstrapEnded = true);
            _ = service.PreloadEnded.WaitAsync()
                .ContinueWith(task => StandaloneContextFx.PreloadEnded = true);

            var bootstrapEndedTask = service.BootstrapEnded.WaitAsync();
            var preloadEndedTask   = service.PreloadEnded.WaitAsync();

            async Task <Dictionary <string, bool> > QueryNodeStatus()
            {
                var result = await ExecuteQueryAsync("query { nodeStatus { bootstrapEnded preloadEnded } }");

                var data           = (Dictionary <string, object>)result.Data;
                var nodeStatusData = (Dictionary <string, object>)data["nodeStatus"];

                return(nodeStatusData.ToDictionary(pair => pair.Key, pair => (bool)pair.Value));
            }

            var nodeStatus = await QueryNodeStatus();

            Assert.False(nodeStatus["bootstrapEnded"]);
            Assert.False(nodeStatus["preloadEnded"]);

            _ = service.StartAsync(cts.Token);

            await bootstrapEndedTask;
            await preloadEndedTask;

            // ContinueWith으로 넘긴 태스크가 실행되기를 기다립니다.
            await Task.Delay(1000);

            nodeStatus = await QueryNodeStatus();

            Assert.True(nodeStatus["bootstrapEnded"]);
            Assert.True(nodeStatus["preloadEnded"]);

            await seedNode.StopAsync(cts.Token);
        }
Пример #2
0
        public async Task ReadMessageCancelAsync()
        {
            var cts = new CancellationTokenSource();

            cts.CancelAfter(TimeSpan.FromSeconds(3));
            var listener = new TcpListener(IPAddress.Any, 0);

            listener.Start();
            var client = new TcpClient();
            await client.ConnectAsync("127.0.0.1", ((IPEndPoint)listener.LocalEndpoint).Port);

            TcpClient listenerSocket = await listener.AcceptTcpClientAsync();

            TcpTransport transport = CreateTcpTransport(
                appProtocolVersion: AppProtocolVersion.Sign(new PrivateKey(), 1));

            try
            {
                await Assert.ThrowsAsync <TaskCanceledException>(async() =>
                                                                 await transport.ReadMessageAsync(listenerSocket, cts.Token));
            }
            finally
            {
                listenerSocket.Dispose();
                client.Dispose();
            }
        }
Пример #3
0
        public async Task HandleDifferentAppProtocolVersion()
        {
            var isCalled = false;

            var signer            = new PrivateKey();
            AppProtocolVersion v1 = AppProtocolVersion.Sign(signer, 1);
            AppProtocolVersion v2 = AppProtocolVersion.Sign(signer, 2);
            var a = CreateSwarm(
                appProtocolVersion: v1,
                differentAppProtocolVersionEncountered: (_, ver, __) =>
            {
                isCalled = true;
            }
                );
            var b = CreateSwarm(appProtocolVersion: v2);

            try
            {
                await StartAsync(b);

                await Assert.ThrowsAsync <PeerDiscoveryException>(() => BootstrapAsync(a, b.AsPeer));

                Assert.True(isCalled);
            }
            finally
            {
                await StopAsync(a);
                await StopAsync(b);

                a.Dispose();
                b.Dispose();
            }
        }
Пример #4
0
        public void Decode()
        {
            BlockHash[] blockHashes = GenerateRandomBlockHashes(100L).ToArray();
            var         msg         = new BlockHashes(123, blockHashes);

            Assert.Equal(123, msg.StartIndex);
            Assert.Equal(blockHashes, msg.Hashes);
            var privKey               = new PrivateKey();
            AppProtocolVersion ver    = AppProtocolVersion.Sign(privKey, 3);
            Peer         peer         = new BoundPeer(privKey.PublicKey, new DnsEndPoint("0.0.0.0", 1234));
            var          messageCodec = new NetMQMessageCodec();
            NetMQMessage encoded      = messageCodec.Encode(
                msg,
                privKey,
                peer,
                DateTimeOffset.UtcNow,
                ver);
            BlockHashes restored = (BlockHashes)messageCodec.Decode(
                encoded,
                true,
                (b, p, a) => { },
                null);

            Assert.Equal(msg.StartIndex, restored.StartIndex);
            Assert.Equal(msg.Hashes, restored.Hashes);
        }
Пример #5
0
        public static IEnumerable <object[]> GetPeers()
        {
            var signer              = new PrivateKey();
            AppProtocolVersion ver  = AppProtocolVersion.Sign(signer, 1);
            AppProtocolVersion ver2 = AppProtocolVersion.Sign(
                signer: signer,
                version: 2,
                extra: Bencodex.Types.Dictionary.Empty.Add("foo", 123).Add("bar", 456)
                );

            yield return(new object[]
            {
                new Peer(
                    new PublicKey(new byte[]
                {
                    0x04, 0xb5, 0xa2, 0x4a, 0xa2, 0x11, 0x27, 0x20, 0x42, 0x3b,
                    0xad, 0x39, 0xa0, 0x20, 0x51, 0x82, 0x37, 0x9d, 0x6f, 0x2b,
                    0x33, 0xe3, 0x48, 0x7c, 0x9a, 0xb6, 0xcc, 0x8f, 0xc4, 0x96,
                    0xf8, 0xa5, 0x48, 0x34, 0x40, 0xef, 0xbb, 0xef, 0x06, 0x57,
                    0xac, 0x2e, 0xf6, 0xc6, 0xee, 0x05, 0xdb, 0x06, 0xa9, 0x45,
                    0x32, 0xfd, 0xa7, 0xdd, 0xc4, 0x4a, 0x16, 0x95, 0xe5, 0xce,
                    0x1a, 0x3d, 0x3c, 0x76, 0xdb,
                })),
            });
        }
Пример #6
0
        public async Task ReadWriteMessageWithInvalidMagicCookieAsync()
        {
            byte[] invalidCookie = { 0x01, 0x02 };
            Assert.False(TcpTransport.MagicCookie.SequenceEqual(invalidCookie));

            var listener = new TcpListener(IPAddress.Any, 0);

            listener.Start();
            var client = new TcpClient();
            await client.ConnectAsync("127.0.0.1", ((IPEndPoint)listener.LocalEndpoint).Port);

            TcpClient listenerSocket = await listener.AcceptTcpClientAsync();

            AppProtocolVersion version   = AppProtocolVersion.Sign(new PrivateKey(), 1);
            TcpTransport       transport = CreateTcpTransport(appProtocolVersion: version);

            try
            {
                var message = new Ping
                {
                    Identity = Guid.NewGuid().ToByteArray(),
                };

                var    codec      = new TcpMessageCodec();
                byte[] serialized = codec.Encode(
                    message,
                    new PrivateKey(),
                    transport.AsPeer,
                    DateTimeOffset.UtcNow,
                    version);
                int length = serialized.Length;
                var buffer = new byte[invalidCookie.Length + sizeof(int) + length];
                invalidCookie.CopyTo(buffer, 0);
                BitConverter.GetBytes(length).CopyTo(buffer, invalidCookie.Length);
                serialized.CopyTo(buffer, invalidCookie.Length + sizeof(int));
                NetworkStream stream = client.GetStream();
                await stream.WriteAsync(buffer, 0, buffer.Length, default);

                await Assert.ThrowsAsync <InvalidMagicCookieException>(
                    async() => await transport.ReadMessageAsync(listenerSocket, default));

                byte[] shortBuffer = { 0x00 };
                await stream.WriteAsync(shortBuffer, 0, shortBuffer.Length, default);

                await Assert.ThrowsAsync <InvalidMagicCookieException>(
                    async() => await transport.ReadMessageAsync(listenerSocket, default));
            }
            finally
            {
                listenerSocket.Dispose();
                client.Dispose();
            }
        }
Пример #7
0
        public void String()
        {
            var signer = new PrivateKey();
            AppProtocolVersion claim = AppProtocolVersion.Sign(signer, 123);

            Assert.Equal("123", claim.ToString());

            AppProtocolVersion claimWithExtra =
                AppProtocolVersion.Sign(signer, 456, (Bencodex.Types.Text) "extra");

            Assert.Equal("456 (Bencodex.Types.Text \"extra\")", claimWithExtra.ToString());
        }
 private void ConfigureNineChroniclesNodeService()
 {
     _standaloneContext.NineChroniclesNodeService = new NineChroniclesNodeService(
         new PrivateKey(),
         new LibplanetNodeServiceProperties <PolymorphicAction <ActionBase> >
     {
         GenesisBlock       = _standaloneContext.BlockChain !.Genesis,
         StorePath          = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()),
         AppProtocolVersion = AppProtocolVersion.Sign(new PrivateKey(), 0),
         SwarmPrivateKey    = new PrivateKey(),
         Host = IPAddress.Loopback.ToString(),
     },
Пример #9
0
 public SwarmBenchmark()
 {
     _policy = new NullPolicy <DumbAction>();
     _blocks = new List <Block <DumbAction> >
     {
         TestUtils.MineGenesis <DumbAction>(),
     };
     _appProtocolVersion = AppProtocolVersion.Sign(new PrivateKey(), 1);
     _blocks.Add(TestUtils.MineNext(_blocks[0]));
     _blocks.Add(TestUtils.MineNext(_blocks[1]));
     _blocks.Add(TestUtils.MineNext(_blocks[2]));
     _blocks.Add(TestUtils.MineNext(_blocks[3]));
 }
Пример #10
0
        public async Task SubscribePreloadProgress()
        {
            var cts = new CancellationTokenSource();

            var apvPrivateKey = new PrivateKey();
            var apv           = AppProtocolVersion.Sign(apvPrivateKey, 0);
            var genesisBlock  = BlockChain <EmptyAction> .MakeGenesisBlock(
                HashAlgorithmType.Of <SHA256>()
                );

            // 에러로 인하여 NineChroniclesNodeService 를 사용할 수 없습니다. https://git.io/JfS0M
            // 따라서 LibplanetNodeService로 비슷한 환경을 맞춥니다.
            // 1. 노드를 생성합니다.
            var seedNode = CreateLibplanetNodeService(genesisBlock, apv, apvPrivateKey.PublicKey);

            await StartAsync(seedNode.Swarm, cts.Token);

            // 2. Progress를 넘겨 preloadProgress subscription 과 연결합니다.
            var service = CreateLibplanetNodeService(
                genesisBlock,
                apv,
                apvPrivateKey.PublicKey,
                new Progress <PreloadState>(state =>
            {
                StandaloneContextFx.PreloadStateSubject.OnNext(state);
            }),
                new [] { seedNode.Swarm.AsPeer });

            var miner = new PrivateKey();
            await seedNode.BlockChain.MineBlock(miner);

            var result = await ExecuteQueryAsync("subscription { preloadProgress { currentPhase totalPhase extra { type currentCount totalCount } } }");

            Assert.IsType <SubscriptionExecutionResult>(result);

            _ = service.StartAsync(cts.Token);

            await service.PreloadEnded.WaitAsync(cts.Token);

            var subscribeResult = (SubscriptionExecutionResult)result;
            var stream          = subscribeResult.Streams.Values.FirstOrDefault();

            // BlockHashDownloadState  : 2
            // BlockDownloadState      : 1
            // BlockVerificationState  : 1
            // ActionExecutionState    : 1
            const int preloadStatesCount     = 5;
            var       preloadProgressRecords =
                new List <(long currentPhase, long totalPhase, string type, long currentCount, long totalCount)>();
            var expectedPreloadProgress = new[]
Пример #11
0
 public SwarmBenchmark()
 {
     _policy      = new NullPolicy <DumbAction>();
     _stagePolicy = new VolatileStagePolicy <DumbAction>();
     _miner       = TestUtils.ChainPrivateKey;
     _blocks      = new List <Block <DumbAction> >
     {
         TestUtils.MineGenesisBlock <DumbAction>(_policy.GetHashAlgorithm, _miner),
     };
     _appProtocolVersion = AppProtocolVersion.Sign(new PrivateKey(), 1);
     _blocks.Add(TestUtils.MineNextBlock(_blocks[0], _policy.GetHashAlgorithm, _miner));
     _blocks.Add(TestUtils.MineNextBlock(_blocks[1], _policy.GetHashAlgorithm, _miner));
     _blocks.Add(TestUtils.MineNextBlock(_blocks[2], _policy.GetHashAlgorithm, _miner));
     _blocks.Add(TestUtils.MineNextBlock(_blocks[3], _policy.GetHashAlgorithm, _miner));
 }
Пример #12
0
        public void DataFrames()
        {
            HashDigest <SHA256>[] blockHashes = GenerateRandomBlockHashes(100L).ToArray();
            var msg = new BlockHashes(123, blockHashes);

            Assert.Equal(123, msg.StartIndex);
            Assert.Equal(blockHashes, msg.Hashes);
            var privKey            = new PrivateKey();
            AppProtocolVersion ver = AppProtocolVersion.Sign(privKey, 3);
            Peer peer = new BoundPeer(privKey.PublicKey, new DnsEndPoint("0.0.0.0", 1234), ver);

            NetMQFrame[] frames   = msg.ToNetMQMessage(privKey, peer).Skip(3).ToArray();
            var          restored = new BlockHashes(frames);

            Assert.Equal(msg.StartIndex, restored.StartIndex);
            Assert.Equal(msg.Hashes, restored.Hashes);
        }
Пример #13
0
        public async Task ReadWriteMessageAsync()
        {
            var listener = new TcpListener(IPAddress.Any, 0);

            listener.Start();
            var client = new TcpClient();
            await client.ConnectAsync("127.0.0.1", ((IPEndPoint)listener.LocalEndpoint).Port);

            TcpClient listenerSocket = await listener.AcceptTcpClientAsync();

            TcpTransport transport = CreateTcpTransport(
                appProtocolVersion: AppProtocolVersion.Sign(new PrivateKey(), 1));

            try
            {
                var message1 = new Ping
                {
                    Identity = Guid.NewGuid().ToByteArray(),
                };

                var message2 = new Pong
                {
                    Identity = Guid.NewGuid().ToByteArray(),
                };

                await transport.WriteMessageAsync(message1, client, default);

                await transport.WriteMessageAsync(message2, client, default);

                Message[] messages = new Message[2];
                messages[0] = await transport.ReadMessageAsync(listenerSocket, default);

                messages[1] = await transport.ReadMessageAsync(listenerSocket, default);

                Assert.Equal(2, messages.Length);
                Assert.Contains(messages, message => message is Ping);
                Assert.Contains(messages, message => message is Pong);
            }
            finally
            {
                listenerSocket.Dispose();
                client.Dispose();
            }
        }
Пример #14
0
        public async Task NodeStatusStagedTxIds()
        {
            var apvPrivateKey = new PrivateKey();
            var apv           = AppProtocolVersion.Sign(apvPrivateKey, 0);
            var genesis       = BlockChain <PolymorphicAction <ActionBase> > .MakeGenesisBlock();

            var service = ServiceBuilder.CreateNineChroniclesNodeService(genesis);

            StandaloneServices.ConfigureStandaloneContext(service, StandaloneContextFx);

            var result = await ExecuteQueryAsync("query { nodeStatus { stagedTxIds } }");

            var expectedResult = new Dictionary <string, object>()
            {
                ["nodeStatus"] = new Dictionary <string, object>()
                {
                    ["stagedTxIds"] = new List <object>()
                },
            };

            Assert.Null(result.Errors);
            Assert.Equal(expectedResult, result.Data);

            var tx = StandaloneContextFx.BlockChain.MakeTransaction(
                new PrivateKey(),
                new PolymorphicAction <ActionBase>[] { }
                );

            result = await ExecuteQueryAsync("query { nodeStatus { stagedTxIds } }");

            expectedResult = new Dictionary <string, object>()
            {
                ["nodeStatus"] = new Dictionary <string, object>()
                {
                    ["stagedTxIds"] = new List <object>
                    {
                        tx.Id.ToString(),
                    }
                },
            };
            Assert.Null(result.Errors);
            Assert.Equal(expectedResult, result.Data);
        }
        public async Task DetectAppProtocolVersion()
        {
            var blockChain = _blockchains[0];

            var signer            = new PrivateKey();
            AppProtocolVersion v2 = AppProtocolVersion.Sign(signer, 2);
            AppProtocolVersion v3 = AppProtocolVersion.Sign(signer, 3);
            var a = CreateSwarm(blockChain, appProtocolVersion: v2);
            var b = CreateSwarm(blockChain, appProtocolVersion: v3);
            var c = CreateSwarm(blockChain, appProtocolVersion: v2);
            var d = CreateSwarm(blockChain, appProtocolVersion: v3);

            try
            {
                await StartAsync(c);
                await StartAsync(d);

                var peers = new[] { c.AsPeer, d.AsPeer };

                foreach (var peer in peers)
                {
                    await a.AddPeersAsync(new[] { peer }, null);

                    await b.AddPeersAsync(new[] { peer }, null);
                }

                Assert.Equal(new[] { c.AsPeer }, a.Peers.ToArray());
                Assert.Equal(new[] { d.AsPeer }, b.Peers.ToArray());
            }
            finally
            {
                await StopAsync(c);
                await StopAsync(d);

                a.Dispose();
                b.Dispose();
                c.Dispose();
                d.Dispose();
            }
        }
Пример #16
0
        public async Task QueryAppProtocolVersion()
        {
            var fx                 = new DefaultStoreFixture();
            var policy             = new BlockPolicy <DumbAction>();
            var blockchain         = TestUtils.MakeBlockChain(policy, fx.Store, fx.StateStore);
            var apvKey             = new PrivateKey();
            var swarmKey           = new PrivateKey();
            AppProtocolVersion apv = AppProtocolVersion.Sign(apvKey, 1);

            string host = IPAddress.Loopback.ToString();
            int    port = FreeTcpPort();

            using (var swarm = new Swarm <DumbAction>(
                       blockchain,
                       swarmKey,
                       apv,
                       host: host,
                       listenPort: port))
            {
                var peer = new BoundPeer(swarmKey.PublicKey, new DnsEndPoint(host, port));
                // Before swarm starting...
                Assert.Throws <TimeoutException>(() =>
                {
                    peer.QueryAppProtocolVersion(timeout: TimeSpan.FromSeconds(1));
                });
                _ = swarm.StartAsync();
                try
                {
                    AppProtocolVersion receivedAPV = peer.QueryAppProtocolVersion();
                    Assert.Equal(apv, receivedAPV);
                }
                finally
                {
                    await swarm.StopAsync();
                }
            }
        }
Пример #17
0
        public void Sign()
        {
            var                signer     = new PrivateKey();
            PublicKey          otherParty = new PrivateKey().PublicKey;
            AppProtocolVersion claim      = AppProtocolVersion.Sign(signer, 1, null);

            Assert.Equal(1, claim.Version);
            Assert.Null(claim.Extra);
            Assert.True(claim.Verify(signer.PublicKey));
            Assert.False(claim.Verify(otherParty));

            AppProtocolVersion claimWithExtra =
                AppProtocolVersion.Sign(signer, 2, (Bencodex.Types.Text) "extra");

            Assert.Equal(2, claimWithExtra.Version);
            Assert.Equal((Bencodex.Types.Text) "extra", claimWithExtra.Extra);
            Assert.True(claimWithExtra.Verify(signer.PublicKey));
            Assert.False(claimWithExtra.Verify(otherParty));

            ArgumentNullException exception =
                Assert.Throws <ArgumentNullException>(() => AppProtocolVersion.Sign(null, 1));

            Assert.Equal("signer", exception.ParamName);
        }
        public async Task ActivationKeyNonce_Throw_ExecutionError(string code, string msg)
        {
            var adminPrivateKey         = new PrivateKey();
            var adminAddress            = adminPrivateKey.ToAddress();
            var activatedAccounts       = ImmutableHashSet <Address> .Empty;
            var pendingActivationStates = new List <PendingActivationState>();

            Block <PolymorphicAction <ActionBase> > genesis =
                BlockChain <PolymorphicAction <ActionBase> > .MakeGenesisBlock(
                    HashAlgorithmType.Of <SHA256>(),
                    new PolymorphicAction <ActionBase>[]
            {
                new InitializeStates(
                    rankingState: new RankingState(),
                    shopState: new ShopState(),
                    gameConfigState: new GameConfigState(),
                    redeemCodeState: new RedeemCodeState(Bencodex.Types.Dictionary.Empty
                                                         .Add("address", RedeemCodeState.Address.Serialize())
                                                         .Add("map", Bencodex.Types.Dictionary.Empty)
                                                         ),
                    adminAddressState: new AdminState(adminAddress, 1500000),
                    activatedAccountsState: new ActivatedAccountsState(activatedAccounts),
                    goldCurrencyState: new GoldCurrencyState(new Currency("NCG", 2, minter: null)),
                    goldDistributions: new GoldDistribution[0],
                    tableSheets: _sheets,
                    pendingActivationStates: pendingActivationStates.ToArray()
                    ),
            }
                    );

            var apvPrivateKey = new PrivateKey();
            var apv           = AppProtocolVersion.Sign(apvPrivateKey, 0);

            var userPrivateKey = new PrivateKey();
            var properties     = new LibplanetNodeServiceProperties <PolymorphicAction <ActionBase> >
            {
                Host = System.Net.IPAddress.Loopback.ToString(),
                AppProtocolVersion   = apv,
                GenesisBlock         = genesis,
                StorePath            = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()),
                StoreStatesCacheSize = 2,
                SwarmPrivateKey      = new PrivateKey(),
                Port    = null,
                NoMiner = true,
                Render  = false,
                Peers   = ImmutableHashSet <Peer> .Empty,
                TrustedAppProtocolVersionSigners = null,
                StaticPeers = ImmutableHashSet <BoundPeer> .Empty
            };
            var blockPolicy = NineChroniclesNodeService.GetTestBlockPolicy();

            var service = new NineChroniclesNodeService(userPrivateKey, properties, blockPolicy, NetworkType.Test);

            StandaloneContextFx.NineChroniclesNodeService = service;
            StandaloneContextFx.BlockChain = service.Swarm?.BlockChain;

            var query       = $"query {{ activationKeyNonce(invitationCode: \"{code}\") }}";
            var queryResult = await ExecuteQueryAsync(query);

            Assert.Single(queryResult.Errors);
            Assert.Equal(msg, queryResult.Errors.First().Message);
        }
Пример #19
0
        public void Sign(
            [Argument(Name = "KEY-ID", Description = "A private key to use for signing.")]
            Guid keyId,
            [Argument(Name = "VERSION", Description = "A version number to sign.")]
            int version,
            [Option(
                 'p',
                 ValueName = "PASSPHRASE",
                 Description = "Take passphrase through this option instead of prompt."
                 )]
            string?passphrase = null,
            [Option(
                 'E',
                 ValueName = "FILE",
                 Description = "Bencodex file to use for extra data.  " +
                               "For standard input, use a hyphen (`-').  " +
                               "For an actual file named a hyphen, prepend `./', i.e., `./-'."
                 )]
            string?extraFile = null,
            [Option(
                 'e',
                 ValueName = "KEY=VALUE",
                 Description = "Set a value to a key on extra Bencodex dictionary.  " +
                               "Can be applied multiple times (e.g., `-e foo=1 -e bar=baz').  " +
                               "This option implies the extra data to be a Bencodex dictionary, " +
                               "hence cannot be used together with -E/--extra-file option."
                 )]
            string[]?extra = null
            )
        {
            PrivateKey key        = new KeyCommand().UnprotectKey(keyId, passphrase);
            IValue?    extraValue = null;

            if (extraFile is string path)
            {
                if (extra is string[] e && e.Length > 0)
                {
                    throw Utils.Error(
                              "-E/--extra-file and -e/--extra cannot be used together at a time."
                              );
                }

                var codec = new Codec();
                if (path == "-")
                {
                    // Stream for stdin does not support .Seek()
                    using MemoryStream buffer = new MemoryStream();
                    using (Stream stream = Console.OpenStandardInput())
                    {
                        stream.CopyTo(buffer);
                    }

                    buffer.Seek(0, SeekOrigin.Begin);
                    extraValue = codec.Decode(buffer);
                }
                else
                {
                    using Stream stream = File.Open(path, FileMode.Open, FileAccess.Read);
                    extraValue          = codec.Decode(stream);
                }
            }
            else if (extra is string[] e && e.Length > 0)
            {
                var dict = Bencodex.Types.Dictionary.Empty;
                foreach (string pair in e)
                {
                    int sepPos = pair.IndexOf('=');
                    if (sepPos < 0)
                    {
                        throw Utils.Error(
                                  "-e/--extra must be a pair of KEY=VALUE, but no equal (=) separator: " +
                                  $"`{pair}'."
                                  );
                    }

                    string key_  = pair.Substring(0, sepPos);
                    string value = pair.Substring(sepPos + 1);
                    dict = dict.SetItem(key_, value);
                }

                extraValue = dict;
            }

            AppProtocolVersion v = AppProtocolVersion.Sign(key, version, extraValue);

            Console.WriteLine(v.Token);
        }
        public async Task ActivationStatus(bool existsActivatedAccounts)
        {
            var adminPrivateKey   = new PrivateKey();
            var adminAddress      = adminPrivateKey.ToAddress();
            var activatedAccounts = ImmutableHashSet <Address> .Empty;

            if (existsActivatedAccounts)
            {
                activatedAccounts = new[] { adminAddress }.ToImmutableHashSet();
            }

            Block <PolymorphicAction <ActionBase> > genesis =
                BlockChain <PolymorphicAction <ActionBase> > .MakeGenesisBlock(
                    new PolymorphicAction <ActionBase>[]
            {
                new InitializeStates(
                    rankingState: new RankingState(),
                    shopState: new ShopState(),
                    gameConfigState: new GameConfigState(),
                    redeemCodeState: new RedeemCodeState(Bencodex.Types.Dictionary.Empty
                                                         .Add("address", RedeemCodeState.Address.Serialize())
                                                         .Add("map", Bencodex.Types.Dictionary.Empty)
                                                         ),
                    adminAddressState: new AdminState(adminAddress, 1500000),
                    activatedAccountsState: new ActivatedAccountsState(activatedAccounts),
                    goldCurrencyState: new GoldCurrencyState(new Currency("NCG", 2, minter: null)),
                    goldDistributions: new GoldDistribution[0],
                    tableSheets: _sheets,
                    pendingActivationStates: new PendingActivationState[] { }
                    ),
            }
                    );

            var apvPrivateKey  = new PrivateKey();
            var apv            = AppProtocolVersion.Sign(apvPrivateKey, 0);
            var userPrivateKey = new PrivateKey();
            var properties     = new LibplanetNodeServiceProperties <PolymorphicAction <ActionBase> >
            {
                Host = System.Net.IPAddress.Loopback.ToString(),
                AppProtocolVersion   = apv,
                GenesisBlock         = genesis,
                StorePath            = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()),
                StoreStatesCacheSize = 2,
                SwarmPrivateKey      = new PrivateKey(),
                Port = null,
                MinimumDifficulty = 4096,
                NoMiner           = true,
                Render            = false,
                Peers             = ImmutableHashSet <Peer> .Empty,
                TrustedAppProtocolVersionSigners = null,
                StaticPeers = ImmutableHashSet <Peer> .Empty
            };

            var service = new NineChroniclesNodeService(userPrivateKey, properties, null);

            StandaloneContextFx.NineChroniclesNodeService = service;
            StandaloneContextFx.BlockChain = service.Swarm?.BlockChain;

            var blockChain = StandaloneContextFx.BlockChain !;

            var queryResult = await ExecuteQueryAsync("query { activationStatus { activated } }");

            var result = (bool)queryResult.Data
                         .As <Dictionary <string, object> >()["activationStatus"]
                         .As <Dictionary <string, object> >()["activated"];

            // ActivatedAccounts가 비어있을때는 true이고 하나라도 있을경우 false
            Assert.Equal(!existsActivatedAccounts, result);

            var nonce      = new byte[] { 0x00, 0x01, 0x02, 0x03 };
            var privateKey = new PrivateKey();

            (ActivationKey activationKey, PendingActivationState pendingActivation) =
                ActivationKey.Create(privateKey, nonce);
            PolymorphicAction <ActionBase> action = new CreatePendingActivation(pendingActivation);

            blockChain.MakeTransaction(adminPrivateKey, new[] { action });
            await blockChain.MineBlock(adminAddress);

            action = activationKey.CreateActivateAccount(nonce);
            blockChain.MakeTransaction(userPrivateKey, new[] { action });
            await blockChain.MineBlock(adminAddress);

            queryResult = await ExecuteQueryAsync("query { activationStatus { activated } }");

            result = (bool)queryResult.Data
                     .As <Dictionary <string, object> >()["activationStatus"]
                     .As <Dictionary <string, object> >()["activated"];

            // ActivatedAccounts에 Address가 추가 되었기 때문에 true
            Assert.True(result);
        }
        public async Task ActivateAccount()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress = adminPrivateKey.ToAddress();
            var activateAccounts = new[] { adminAddress }.ToImmutableHashSet();

            Block <PolymorphicAction <ActionBase> > genesis =
                BlockChain <PolymorphicAction <ActionBase> > .MakeGenesisBlock(
                    new PolymorphicAction <ActionBase>[]
            {
                new InitializeStates()
                {
                    RankingState     = new RankingState(),
                    ShopState        = new ShopState(),
                    TableSheetsState = new TableSheetsState(),
                    GameConfigState  = new GameConfigState(),
                    RedeemCodeState  = new RedeemCodeState(Bencodex.Types.Dictionary.Empty
                                                           .Add("address", RedeemCodeState.Address.Serialize())
                                                           .Add("map", Bencodex.Types.Dictionary.Empty)
                                                           ),
                    AdminAddressState      = new AdminState(adminAddress, 1500000),
                    ActivatedAccountsState = new ActivatedAccountsState(activateAccounts),
                    GoldCurrencyState      = new GoldCurrencyState(new Currency("NCG", minter: null)),
                    GoldDistributions      = new GoldDistribution[0],
                },
            }
                    );

            var apvPrivateKey = new PrivateKey();
            var apv            = AppProtocolVersion.Sign(apvPrivateKey, 0);
            var userPrivateKey = new PrivateKey();
            var properties     = new LibplanetNodeServiceProperties <PolymorphicAction <ActionBase> >
            {
                Host = System.Net.IPAddress.Loopback.ToString(),
                AppProtocolVersion   = apv,
                GenesisBlock         = genesis,
                StorePath            = null,
                StoreStatesCacheSize = 2,
                PrivateKey           = userPrivateKey,
                Port = null,
                MinimumDifficulty = 4096,
                NoMiner           = true,
                Render            = false,
                Peers             = ImmutableHashSet <Peer> .Empty,
                TrustedAppProtocolVersionSigners = null,
            };

            var service = new NineChroniclesNodeService(properties, null);

            service.PrivateKey = userPrivateKey;
            StandaloneContextFx.NineChroniclesNodeService = service;
            StandaloneContextFx.BlockChain = service.Swarm.BlockChain;

            var blockChain = StandaloneContextFx.BlockChain;

            var nonce      = new byte[] { 0x00, 0x01, 0x02, 0x03 };
            var privateKey = new PrivateKey();

            (ActivationKey activationKey, PendingActivationState pendingActivation) =
                ActivationKey.Create(privateKey, nonce);
            PolymorphicAction <ActionBase> action = new CreatePendingActivation(pendingActivation);

            blockChain.MakeTransaction(adminPrivateKey, new[] { action });
            await blockChain.MineBlock(adminAddress);

            var encodedActivationKey = activationKey.Encode();
            var queryResult          = await ExecuteQueryAsync(
                $"mutation {{ activationStatus {{ activateAccount(encodedActivationKey: \"{encodedActivationKey}\") }} }}");

            await blockChain.MineBlock(adminAddress);

            var result = (bool)queryResult.Data
                         .As <Dictionary <string, object> >()["activationStatus"]
                         .As <Dictionary <string, object> >()["activateAccount"];

            Assert.True(result);

            var state = (Bencodex.Types.Dictionary)blockChain.GetState(
                ActivatedAccountsState.Address);
            var activatedAccountsState = new ActivatedAccountsState(state);
            var userAddress            = userPrivateKey.ToAddress();

            Assert.True(activatedAccountsState.Accounts.Contains(userAddress));
        }
Пример #22
0
        public void Equality()
        {
            var signer = new PrivateKey();
            AppProtocolVersion claim =
                AppProtocolVersion.Sign(signer, 123, (Bencodex.Types.Text) "foo");

            var claim2 = new AppProtocolVersion(124, claim.Extra, claim.Signature, claim.Signer);

            Assert.False(((IEquatable <AppProtocolVersion>)claim).Equals(claim2));
            Assert.False(((object)claim).Equals(claim2));
            Assert.NotEqual(claim.GetHashCode(), claim2.GetHashCode());
            Assert.False(claim == claim2);
            Assert.True(claim != claim2);

            var claim3 = new AppProtocolVersion(
                claim.Version,
                Bencodex.Types.Null.Value,
                claim.Signature,
                claim.Signer
                );

            Assert.False(((IEquatable <AppProtocolVersion>)claim).Equals(claim3));
            Assert.False(((object)claim).Equals(claim3));
            Assert.NotEqual(claim.GetHashCode(), claim3.GetHashCode());
            Assert.False(claim == claim3);
            Assert.True(claim != claim3);

            var claim4 = new AppProtocolVersion(
                claim.Version,
                claim.Extra,
                ImmutableArray <byte> .Empty,
                claim.Signer
                );

            Assert.False(((IEquatable <AppProtocolVersion>)claim).Equals(claim4));
            Assert.False(((object)claim).Equals(claim4));
            Assert.NotEqual(claim.GetHashCode(), claim4.GetHashCode());
            Assert.False(claim == claim4);
            Assert.True(claim != claim4);

            var claim5 = new AppProtocolVersion(
                claim.Version,
                claim.Extra,
                claim.Signature,
                new PrivateKey().ToAddress()
                );

            Assert.False(((IEquatable <AppProtocolVersion>)claim).Equals(claim5));
            Assert.False(((object)claim).Equals(claim5));
            Assert.NotEqual(claim.GetHashCode(), claim5.GetHashCode());
            Assert.False(claim == claim5);
            Assert.True(claim != claim5);

            var codec     = new Codec();
            var sameClaim = new AppProtocolVersion(
                claim.Version,
                codec.Decode(codec.Encode(claim.Extra)),
                ImmutableArray.Create(claim.Signature, 0, claim.Signature.Length),
                new Address(claim.Signer.ByteArray)
                );

            Assert.True(((IEquatable <AppProtocolVersion>)claim).Equals(sameClaim));
            Assert.True(((object)claim).Equals(sameClaim));
            Assert.Equal(claim.GetHashCode(), sameClaim.GetHashCode());
            Assert.True(claim == sameClaim);
            Assert.False(claim != sameClaim);

            AppProtocolVersion claimWithoutExtra = AppProtocolVersion.Sign(signer, 1);
            var sameClaimWithoutExtra            = new AppProtocolVersion(
                claimWithoutExtra.Version,
                claimWithoutExtra.Extra,
                ImmutableArray.Create(
                    claimWithoutExtra.Signature,
                    0,
                    claimWithoutExtra.Signature.Length
                    ),
                new Address(claimWithoutExtra.Signer.ByteArray)
                );

            Assert.True(
                ((IEquatable <AppProtocolVersion>)claimWithoutExtra).Equals(sameClaimWithoutExtra)
                );
            Assert.True(((object)claimWithoutExtra).Equals(sameClaimWithoutExtra));
            Assert.Equal(claimWithoutExtra.GetHashCode(), sameClaimWithoutExtra.GetHashCode());
            Assert.True(claimWithoutExtra == sameClaimWithoutExtra);
            Assert.False(claimWithoutExtra != sameClaimWithoutExtra);
        }
Пример #23
0
        public async Task QueryAppProtocolVersion(SwarmOptions.TransportType transportType)
        {
            var fx                 = new MemoryStoreFixture();
            var policy             = new BlockPolicy <DumbAction>();
            var blockchain         = MakeBlockChain(policy, fx.Store, fx.StateStore);
            var apvKey             = new PrivateKey();
            var swarmKey           = new PrivateKey();
            AppProtocolVersion apv = AppProtocolVersion.Sign(apvKey, 1);

            string host = IPAddress.Loopback.ToString();
            int    port = FreeTcpPort();

            var option = new SwarmOptions
            {
                Type = transportType,
            };

            using (var swarm = new Swarm <DumbAction>(
                       blockchain,
                       swarmKey,
                       apv,
                       host: host,
                       listenPort: port,
                       options: option))
            {
                var peer = new BoundPeer(swarmKey.PublicKey, new DnsEndPoint(host, port));
                // Before swarm starting...
                await Assert.ThrowsAsync <TimeoutException>(async() =>
                {
                    if (swarm.Transport is NetMQTransport)
                    {
                        peer.QueryAppProtocolVersionNetMQ(timeout: TimeSpan.FromSeconds(1));
                    }
                    else if (swarm.Transport is TcpTransport)
                    {
                        await peer.QueryAppProtocolVersionTcp(timeout: TimeSpan.FromSeconds(1));
                    }
                    else
                    {
                        throw new XunitException(
                            "Each type of transport must have corresponding test case.");
                    }
                });

                _ = swarm.StartAsync();
                try
                {
                    AppProtocolVersion receivedAPV = default;
                    if (swarm.Transport is NetMQTransport)
                    {
                        receivedAPV = peer.QueryAppProtocolVersionNetMQ();
                    }
                    else if (swarm.Transport is TcpTransport)
                    {
                        receivedAPV = await peer.QueryAppProtocolVersionTcp();
                    }
                    else
                    {
                        throw new XunitException(
                                  "Each type of transport must have corresponding test case.");
                    }

                    Assert.Equal(apv, receivedAPV);
                }
                finally
                {
                    await swarm.StopAsync();
                }
            }

            if (transportType == SwarmOptions.TransportType.NetMQTransport)
            {
                NetMQConfig.Cleanup(false);
            }
        }
Пример #24
0
        public async Task IgnoreUntrustedAppProtocolVersion()
        {
            var signer = new PrivateKey();
            AppProtocolVersion older = AppProtocolVersion.Sign(signer, 2);
            AppProtocolVersion newer = AppProtocolVersion.Sign(signer, 3);

            var untrustedSigner = new PrivateKey();
            AppProtocolVersion untrustedOlder = AppProtocolVersion.Sign(untrustedSigner, 2);
            AppProtocolVersion untrustedNewer = AppProtocolVersion.Sign(untrustedSigner, 3);

            _output.WriteLine("Trusted version signer: {0}", signer.ToAddress());
            _output.WriteLine("Untrusted version signer: {0}", untrustedSigner.ToAddress());

            var logs = new ConcurrentDictionary <Peer, AppProtocolVersion>();

            void DifferentAppProtocolVersionEncountered(
                Peer peer,
                AppProtocolVersion peerVersion,
                AppProtocolVersion localVersion
                )
            {
                logs[peer] = peerVersion;
            }

            var a = CreateSwarm(
                appProtocolVersion: older,
                trustedAppProtocolVersionSigners: new[] { signer.PublicKey },
                differentAppProtocolVersionEncountered: DifferentAppProtocolVersionEncountered
                );
            var b = CreateSwarm(
                appProtocolVersion: newer,
                trustedAppProtocolVersionSigners: new[] { signer.PublicKey }
                );
            var c = CreateSwarm(
                appProtocolVersion: older,
                trustedAppProtocolVersionSigners: new[] { signer.PublicKey }
                );
            var d = CreateSwarm(
                appProtocolVersion: newer,
                trustedAppProtocolVersionSigners: new[] { signer.PublicKey }
                );
            var e = CreateSwarm(
                appProtocolVersion: untrustedOlder,
                trustedAppProtocolVersionSigners: new[] { untrustedSigner.PublicKey }
                );
            var f = CreateSwarm(
                appProtocolVersion: untrustedNewer,
                trustedAppProtocolVersionSigners: new[] { untrustedSigner.PublicKey }
                );

            try
            {
                await StartAsync(c);
                await StartAsync(d);
                await StartAsync(e);
                await StartAsync(f);

                await a.AddPeersAsync(new[] { c.AsPeer }, TimeSpan.FromSeconds(1));

                await a.AddPeersAsync(new[] { d.AsPeer }, TimeSpan.FromSeconds(1));

                await a.AddPeersAsync(new[] { e.AsPeer }, TimeSpan.FromSeconds(1));

                await a.AddPeersAsync(new[] { f.AsPeer }, TimeSpan.FromSeconds(1));

                await b.AddPeersAsync(new[] { c.AsPeer }, TimeSpan.FromSeconds(1));

                await b.AddPeersAsync(new[] { d.AsPeer }, TimeSpan.FromSeconds(1));

                await b.AddPeersAsync(new[] { e.AsPeer }, TimeSpan.FromSeconds(1));

                await b.AddPeersAsync(new[] { f.AsPeer }, TimeSpan.FromSeconds(1));

                Assert.Equal(new[] { c.AsPeer }, a.Peers.ToArray());
                Assert.Equal(new[] { d.AsPeer }, b.Peers.ToArray());

                _output.WriteLine("Logged encountered peers:");
                foreach (KeyValuePair <Peer, AppProtocolVersion> kv in logs)
                {
                    _output.WriteLine(
                        "{0}; {1}; {2} -> {3}",
                        kv.Key,
                        kv.Value.Version,
                        kv.Value.Signer,
                        kv.Value.Verify(signer.PublicKey) ? "verified" : "not verified"
                        );
                }
            }
            finally
            {
                await StopAsync(c);
                await StopAsync(d);
                await StopAsync(e);
                await StopAsync(f);

                a.Dispose();
                b.Dispose();
                c.Dispose();
                d.Dispose();
                e.Dispose();
                f.Dispose();
            }
        }
Пример #25
0
        public static IEnumerable <object[]> GetPeers()
        {
            var signer             = new PrivateKey();
            AppProtocolVersion ver = AppProtocolVersion.Sign(signer, 1);

            yield return(new object[]
            {
                new BoundPeer(
                    new PublicKey(new byte[]
                {
                    0x04, 0xb5, 0xa2, 0x4a, 0xa2, 0x11, 0x27, 0x20, 0x42, 0x3b,
                    0xad, 0x39, 0xa0, 0x20, 0x51, 0x82, 0x37, 0x9d, 0x6f, 0x2b,
                    0x33, 0xe3, 0x48, 0x7c, 0x9a, 0xb6, 0xcc, 0x8f, 0xc4, 0x96,
                    0xf8, 0xa5, 0x48, 0x34, 0x40, 0xef, 0xbb, 0xef, 0x06, 0x57,
                    0xac, 0x2e, 0xf6, 0xc6, 0xee, 0x05, 0xdb, 0x06, 0xa9, 0x45,
                    0x32, 0xfd, 0xa7, 0xdd, 0xc4, 0x4a, 0x16, 0x95, 0xe5, 0xce,
                    0x1a, 0x3d, 0x3c, 0x76, 0xdb,
                }),
                    new DnsEndPoint("0.0.0.0", 1234),
                    ver,
                    IPAddress.IPv6Loopback),
            });

            yield return(new object[]
            {
                new BoundPeer(
                    new PublicKey(new byte[]
                {
                    0x04, 0xb5, 0xa2, 0x4a, 0xa2, 0x11, 0x27, 0x20, 0x42, 0x3b,
                    0xad, 0x39, 0xa0, 0x20, 0x51, 0x82, 0x37, 0x9d, 0x6f, 0x2b,
                    0x33, 0xe3, 0x48, 0x7c, 0x9a, 0xb6, 0xcc, 0x8f, 0xc4, 0x96,
                    0xf8, 0xa5, 0x48, 0x34, 0x40, 0xef, 0xbb, 0xef, 0x06, 0x57,
                    0xac, 0x2e, 0xf6, 0xc6, 0xee, 0x05, 0xdb, 0x06, 0xa9, 0x45,
                    0x32, 0xfd, 0xa7, 0xdd, 0xc4, 0x4a, 0x16, 0x95, 0xe5, 0xce,
                    0x1a, 0x3d, 0x3c, 0x76, 0xdb,
                }),
                    new DnsEndPoint("0.0.0.0", 1234),
                    ver),
            });

            yield return(new object[]
            {
                new BoundPeer(
                    new PublicKey(new byte[]
                {
                    0x04, 0xb5, 0xa2, 0x4a, 0xa2, 0x11, 0x27, 0x20, 0x42, 0x3b,
                    0xad, 0x39, 0xa0, 0x20, 0x51, 0x82, 0x37, 0x9d, 0x6f, 0x2b,
                    0x33, 0xe3, 0x48, 0x7c, 0x9a, 0xb6, 0xcc, 0x8f, 0xc4, 0x96,
                    0xf8, 0xa5, 0x48, 0x34, 0x40, 0xef, 0xbb, 0xef, 0x06, 0x57,
                    0xac, 0x2e, 0xf6, 0xc6, 0xee, 0x05, 0xdb, 0x06, 0xa9, 0x45,
                    0x32, 0xfd, 0xa7, 0xdd, 0xc4, 0x4a, 0x16, 0x95, 0xe5, 0xce,
                    0x1a, 0x3d, 0x3c, 0x76, 0xdb,
                }),
                    new DnsEndPoint("0.0.0.0", 1234),
                    ver),
            });

            yield return(new object[]
            {
                new Peer(
                    new PublicKey(new byte[]
                {
                    0x04, 0xb5, 0xa2, 0x4a, 0xa2, 0x11, 0x27, 0x20, 0x42, 0x3b,
                    0xad, 0x39, 0xa0, 0x20, 0x51, 0x82, 0x37, 0x9d, 0x6f, 0x2b,
                    0x33, 0xe3, 0x48, 0x7c, 0x9a, 0xb6, 0xcc, 0x8f, 0xc4, 0x96,
                    0xf8, 0xa5, 0x48, 0x34, 0x40, 0xef, 0xbb, 0xef, 0x06, 0x57,
                    0xac, 0x2e, 0xf6, 0xc6, 0xee, 0x05, 0xdb, 0x06, 0xa9, 0x45,
                    0x32, 0xfd, 0xa7, 0xdd, 0xc4, 0x4a, 0x16, 0x95, 0xe5, 0xce,
                    0x1a, 0x3d, 0x3c, 0x76, 0xdb,
                }),
                    ver),
            });
        }
Пример #26
0
        public async Task SubscribeDifferentAppProtocolVersionEncounter()
        {
            var result = await ExecuteQueryAsync(@"
                subscription {
                    differentAppProtocolVersionEncounter {
                        peer
                        peerVersion {
                            version
                            signer
                            signature
                            extra
                        }
                        localVersion {
                            version
                            signer
                            signature
                            extra
                        }
                    }
                }
            ");

            var subscribeResult = (SubscriptionExecutionResult)result;
            var stream          = subscribeResult.Streams.Values.FirstOrDefault();

            Assert.NotNull(stream);

            Assert.ThrowsAsync <OperationCanceledException>(async() =>
            {
                await stream.Take(1).Timeout(TimeSpan.FromMilliseconds(5000)).FirstAsync();
            });

            var apvPrivateKey = new PrivateKey();
            var apv1          = AppProtocolVersion.Sign(apvPrivateKey, 1);
            var apv2          = AppProtocolVersion.Sign(apvPrivateKey, 0);
            var peer          = new Peer(apvPrivateKey.PublicKey, apv1);

            StandaloneContextFx.DifferentAppProtocolVersionEncounterSubject.OnNext(
                new DifferentAppProtocolVersionEncounter
            {
                Peer         = peer,
                PeerVersion  = apv1,
                LocalVersion = apv2,
            }
                );
            var rawEvents = await stream.Take(1);

            var rawEvent = (Dictionary <string, object>)rawEvents.Data;
            var differentAppProtocolVersionEncounter =
                (Dictionary <string, object>)rawEvent["differentAppProtocolVersionEncounter"];

            Assert.Equal(
                peer.ToString(),
                differentAppProtocolVersionEncounter["peer"]
                );
            var peerVersion =
                (Dictionary <string, object>)differentAppProtocolVersionEncounter["peerVersion"];

            Assert.Equal(apv1.Version, peerVersion["version"]);
            Assert.Equal(apv1.Signer, new Address(((string)peerVersion["signer"]).Substring(2)));
            Assert.Equal(apv1.Signature, ByteUtil.ParseHex((string)peerVersion["signature"]));
            Assert.Equal(apv1.Extra, peerVersion["extra"]);
            var localVersion =
                (Dictionary <string, object>)differentAppProtocolVersionEncounter["localVersion"];

            Assert.Equal(apv2.Version, localVersion["version"]);
            Assert.Equal(apv2.Signer, new Address(((string)localVersion["signer"]).Substring(2)));
            Assert.Equal(apv2.Signature, ByteUtil.ParseHex((string)localVersion["signature"]));
            Assert.Equal(apv2.Extra, localVersion["extra"]);
        }
        void OnGUI()
        {
            _showPrivateKey = EditorGUILayout.Foldout(_showPrivateKey, "Private Key");
            if (_showPrivateKey)
            {
                _selectedPrivateKeyIndex = EditorGUILayout.Popup(
                    "Private Key",
                    _selectedPrivateKeyIndex,
                    _privateKeyOptions);
                if (_selectedPrivateKeyIndex == _privateKeyOptions.Length - 1)
                {
                    _toggledOnTypePrivateKey = EditorGUILayout.Toggle(
                        "Type New Private Key",
                        _toggledOnTypePrivateKey);
                    if (_toggledOnTypePrivateKey)
                    {
                        _privateKey =
                            EditorGUILayout.PasswordField("New Private Key", _privateKey) ??
                            string.Empty;
                        ShowError(_privateKey.Any() ? null : "New private key is empty.");
                    }
                }

                _privateKeyPassphrase =
                    EditorGUILayout.PasswordField("Passphrase", _privateKeyPassphrase) ??
                    string.Empty;
                ShowError(_privateKeyPassphrase.Any() ? null : "Passphrase is empty.");

                if (_selectedPrivateKeyIndex == _privateKeyOptions.Length - 1)
                {
                    EditorGUI.BeginDisabledGroup(!_privateKeyPassphrase.Any());
                    if (GUILayout.Button("Create"))
                    {
                        var privateKey = _toggledOnTypePrivateKey
                            ? new PrivateKey(ByteUtil.ParseHex(_privateKey))
                            : new PrivateKey();
                        var ppk = ProtectedPrivateKey.Protect(privateKey, _privateKeyPassphrase);
                        _keyStore.Add(ppk);
                        RefreshPrivateKeys();
                        _selectedPrivateKeyIndex = Array.IndexOf(_privateKeys, privateKey);
                    }

                    EditorGUI.EndDisabledGroup();
                }
            }

            HorizontalLine();

            _showParameters = EditorGUILayout.Foldout(_showParameters, "Parameters");
            if (_showParameters)
            {
                _versionString = EditorGUILayout.TextField("Version", _versionString);
                try
                {
                    version = int.Parse(_versionString, CultureInfo.InvariantCulture);
                }
                catch (Exception e)
                {
                    ShowError(e.Message);
                }

                macOSBinaryUrl   = EditorGUILayout.TextField("macOS Binary URL", macOSBinaryUrl);
                windowsBinaryUrl =
                    EditorGUILayout.TextField("Windows Binary URL", windowsBinaryUrl);
            }

            HorizontalLine();

            EditorGUI.BeginDisabledGroup(
                !(_privateKeyPassphrase.Any() &&
                  _selectedPrivateKeyIndex < _privateKeyOptions.Length - 1));
            if (GUILayout.Button("Sign"))
            {
                var appProtocolVersionExtra =
                    new AppProtocolVersionExtra(macOSBinaryUrl, windowsBinaryUrl, _timestamp);

                PrivateKey key;
                try
                {
                    key = _privateKeys[_selectedPrivateKeyIndex].Item2
                          .Unprotect(_privateKeyPassphrase);
                }
                catch (IncorrectPassphraseException)
                {
                    EditorUtility.DisplayDialog(
                        "Unmatched passphrase",
                        "Private key passphrase is incorrect.",
                        "Retype passphrase"
                        );
                    _privateKeyPassphrase = string.Empty;
                    return;
                }

                _appProtocolVersion = AppProtocolVersion.Sign(
                    key,
                    version,
                    appProtocolVersionExtra.Serialize());
            }

            EditorGUI.EndDisabledGroup();

            if (_appProtocolVersion is AppProtocolVersion v)
            {
                GUILayout.TextArea(v.Token);
            }
        }
Пример #28
0
        public async Task SubscribePreloadProgress()
        {
            var cts = new CancellationTokenSource();

            var apvPrivateKey = new PrivateKey();
            var apv           = AppProtocolVersion.Sign(apvPrivateKey, 0);
            var genesisBlock  = BlockChain <EmptyAction> .MakeGenesisBlock();

            // 에러로 인하여 NineChroniclesNodeService 를 사용할 수 없습니다. https://git.io/JfS0M
            // 따라서 LibplanetNodeService로 비슷한 환경을 맞춥니다.
            // 1. 노드를 생성합니다.
            var seedNode = CreateLibplanetNodeService <EmptyAction>(genesisBlock, apv, apvPrivateKey.PublicKey);

            await StartAsync(seedNode.Swarm, cts.Token);

            // 2. Progress를 넘겨 preloadProgress subscription 과 연결합니다.
            var service = CreateLibplanetNodeService <EmptyAction>(
                genesisBlock,
                apv,
                apvPrivateKey.PublicKey,
                new Progress <PreloadState>(state =>
            {
                StandaloneContextFx.PreloadStateSubject.OnNext(state);
            }),
                new [] { seedNode.Swarm.AsPeer });

            var miner = new PrivateKey().ToAddress();
            await seedNode.BlockChain.MineBlock(miner);

            var result = await ExecuteQueryAsync("subscription { preloadProgress { currentPhase totalPhase extra { type currentCount totalCount } } }");

            Assert.IsType <SubscriptionExecutionResult>(result);

            service.StartAsync(cts.Token);

            await service.PreloadEnded.WaitAsync(cts.Token);

            var subscribeResult = (SubscriptionExecutionResult)result;
            var stream          = subscribeResult.Streams.Values.FirstOrDefault();

            // BlockHashDownloadState  : 1
            // BlockDownloadState      : 1
            // BlockVerificationState  : 1
            // ActionExecutionState    : 1
            const int preloadStatesCount     = 4;
            var       preloadProgressRecords =
                new List <(long currentPhase, long totalPhase, string type, long currentCount, long totalCount)>();
            var expectedPreloadProgress = new List <(long currentPhase, long totalPhase, string type, long currentCount, long totalCount)>
            {
                (1, 5, "BlockHashDownloadState", 1, 1),
                (2, 5, "BlockDownloadState", 1, 1),
                (3, 5, "BlockVerificationState", 1, 1),
                (5, 5, "ActionExecutionState", 1, 1),
            };

            foreach (var index in Enumerable.Range(1, preloadStatesCount))
            {
                var rawEvents = await stream.Take(index);

                var preloadProgress      = (Dictionary <string, object>)((Dictionary <string, object>)rawEvents.Data)["preloadProgress"];
                var preloadProgressExtra = (Dictionary <string, object>)preloadProgress["extra"];

                preloadProgressRecords.Add((
                                               (long)preloadProgress["currentPhase"],
                                               (long)preloadProgress["totalPhase"],
                                               (string)preloadProgressExtra["type"],
                                               (long)preloadProgressExtra["currentCount"],
                                               (long)preloadProgressExtra["totalCount"]));
            }

            Assert.True(preloadProgressRecords.ToImmutableHashSet().SetEquals(expectedPreloadProgress));

            await seedNode.StopAsync(cts.Token);

            await service.StopAsync(cts.Token);
        }