コード例 #1
0
        public void ExecuteWithInsufficientBalance()
        {
            var balance = ImmutableDictionary <(Address, Currency), FungibleAssetValue> .Empty
                          .Add((_sender, _currency), _currency * 1000)
                          .Add((_recipient, _currency), _currency * 10);

            var prevState = new State(
                balance: balance
                );
            var action = new TransferAsset(
                sender: _sender,
                recipient: _recipient,
                amount: _currency * 100000
                );

            Assert.Throws <InsufficientBalanceException>(() =>
            {
                action.Execute(new ActionContext()
                {
                    PreviousStates = prevState,
                    Signer         = _sender,
                    Rehearsal      = false,
                    BlockIndex     = 1,
                });
            });
        }
コード例 #2
0
        public void Execute()
        {
            var balance = ImmutableDictionary <(Address, Currency), FungibleAssetValue> .Empty
                          .Add((_sender, _currency), _currency * 1000)
                          .Add((_recipient, _currency), _currency * 10);

            var prevState = new State(
                balance: balance
                );
            var action = new TransferAsset(
                sender: _sender,
                recipient: _recipient,
                amount: _currency * 100
                );
            IAccountStateDelta nextState = action.Execute(new ActionContext()
            {
                PreviousStates = prevState,
                Signer         = _sender,
                Rehearsal      = false,
                BlockIndex     = 1,
            });

            Assert.Equal(_currency * 900, nextState.GetBalance(_sender, _currency));
            Assert.Equal(_currency * 110, nextState.GetBalance(_recipient, _currency));
        }
コード例 #3
0
        public void ExecuteWithMinterAsRecipient()
        {
            var currencyByRecipient = new Currency("NCG", 2, _sender);
            var balance             = ImmutableDictionary <(Address, Currency), FungibleAssetValue> .Empty
                                      .Add((_sender, currencyByRecipient), _currency * 1000)
                                      .Add((_recipient, currencyByRecipient), _currency * 10);

            var prevState = new State(
                balance: balance
                );
            var action = new TransferAsset(
                sender: _sender,
                recipient: _recipient,
                amount: currencyByRecipient * 100
                );
            var ex = Assert.Throws <InvalidTransferMinterException>(() =>
            {
                action.Execute(new ActionContext()
                {
                    PreviousStates = prevState,
                    Signer         = _sender,
                    Rehearsal      = false,
                    BlockIndex     = 1,
                });
            });

            Assert.Equal(new[] { _sender }, ex.Minters);
            Assert.Equal(_sender, ex.Sender);
            Assert.Equal(_recipient, ex.Recipient);
        }
コード例 #4
0
ファイル: Tx.cs プロジェクト: GunnerJnr/lib9c
        public void TransferAsset(
            [Argument("SENDER", Description = "An address of sender.")] string sender,
            [Argument("RECIPIENT", Description = "An address of recipient.")] string recipient,
            [Argument("AMOUNT", Description = "An amount of gold to transfer.")] int goldAmount,
            [Argument("GENESIS-BLOCK", Description = "A genesis block containing InitializeStates.")] string genesisBlock
            )
        {
            Block <NCAction> genesis = Block <NCAction> .Deserialize(File.ReadAllBytes(genesisBlock));

            var      initStates = (InitializeStates)genesis.Transactions.Single().Actions.Single().InnerAction;
            Currency currency   = new GoldCurrencyState(initStates.GoldCurrency).Currency;

            var action = new TransferAsset(
                new Address(sender),
                new Address(recipient),
                currency * goldAmount
                );

            var bencoded = new List(
                new IValue[]
            {
                (Text)nameof(TransferAsset),
                action.PlainValue
            }
                );

            byte[] raw = _codec.Encode(bencoded);
            Console.Write(ByteUtil.Hex(raw));
        }
コード例 #5
0
ファイル: Tx.cs プロジェクト: planetarium/lib9c
        public void TransferAsset(
            [Argument("SENDER", Description = "An address of sender.")] string sender,
            [Argument("RECIPIENT", Description = "An address of recipient.")] string recipient,
            [Argument("AMOUNT", Description = "An amount of gold to transfer.")] int goldAmount,
            [Argument("GENESIS-BLOCK", Description = "A genesis block containing InitializeStates.")] string genesisBlock
            )
        {
            byte[] genesisBytes = File.ReadAllBytes(genesisBlock);
            var    genesisDict  = (Bencodex.Types.Dictionary)_codec.Decode(genesisBytes);
            IReadOnlyList <Transaction <NCAction> > genesisTxs =
                BlockMarshaler.UnmarshalBlockTransactions <NCAction>(genesisDict);
            var      initStates = (InitializeStates)genesisTxs.Single().Actions.Single().InnerAction;
            Currency currency   = new GoldCurrencyState(initStates.GoldCurrency).Currency;

            var action = new TransferAsset(
                new Address(sender),
                new Address(recipient),
                currency * goldAmount
                );

            var bencoded = new List(
                (Text)nameof(TransferAsset),
                action.PlainValue
                );

            byte[] raw = _codec.Encode(bencoded);
            Console.Write(ByteUtil.Hex(raw));
        }
コード例 #6
0
        public async Task TransferNCGHistories()
        {
            PrivateKey minerPrivateKey = new PrivateKey();
            Address    sender = minerPrivateKey.ToAddress(), recipient = new PrivateKey().ToAddress();

            await BlockChain.MineBlock(sender);

            await BlockChain.MineBlock(recipient);

            var currency = new GoldCurrencyState((Dictionary)BlockChain.GetState(Addresses.GoldCurrency)).Currency;
            var transferAsset = new TransferAsset(sender, recipient, new FungibleAssetValue(currency, 10, 0));
            var tx       = BlockChain.MakeTransaction(minerPrivateKey, new PolymorphicAction <ActionBase>[] { transferAsset });
            var block    = await BlockChain.MineBlock(minerPrivateKey.ToAddress(), append : false);

            BlockChain.Append(block);
            Assert.NotNull(StandaloneContextFx.Store?.GetTxExecution(block.Hash, tx.Id));

            var blockHashHex = ByteUtil.Hex(block.Hash.ToByteArray());
            var result       =
                await ExecuteQueryAsync(
                    $"{{ transferNCGHistories(blockHash: \"{blockHashHex}\") {{ blockHash txId sender recipient amount }} }}");

            Assert.Null(result.Errors);
            Assert.Equal(new List <object>
            {
                new Dictionary <string, object>
                {
                    ["blockHash"] = block.Hash.ToString(),
                    ["txId"]      = tx.Id.ToString(),
                    ["sender"]    = transferAsset.Sender.ToString(),
                    ["recipient"] = transferAsset.Recipient.ToString(),
                    ["amount"]    = transferAsset.Amount.GetQuantityString(),
                }
            }, result.Data.As <Dictionary <string, object> >()["transferNCGHistories"]);
        }
コード例 #7
0
        public void ExecuteWithUnactivatedRecipient()
        {
            var activatedAddress = new ActivatedAccountsState().AddAccount(new PrivateKey().ToAddress());
            var balance          = ImmutableDictionary <(Address, Currency), FungibleAssetValue> .Empty
                                   .Add((_sender, _currency), _currency * 1000)
                                   .Add((_recipient, _currency), _currency * 10);

            var state = ImmutableDictionary <Address, IValue> .Empty
                        .Add(_sender.Derive(ActivationKey.DeriveKey), true.Serialize())
                        .Add(Addresses.ActivatedAccount, activatedAddress.Serialize());

            var prevState = new State(
                state: state,
                balance: balance
                );
            var action = new TransferAsset(
                sender: _sender,
                recipient: _recipient,
                amount: _currency * 100
                );
            var ex = Assert.Throws <InvalidTransferUnactivatedRecipientException>(() =>
            {
                action.Execute(new ActionContext()
                {
                    PreviousStates = prevState,
                    Signer         = _sender,
                    Rehearsal      = false,
                    BlockIndex     = 1,
                });
            });

            Assert.Equal(_sender, ex.Sender);
            Assert.Equal(_recipient, ex.Recipient);
        }
コード例 #8
0
        public void ExecuteWithInvalidSigner()
        {
            var balance = ImmutableDictionary <(Address, Currency), FungibleAssetValue> .Empty
                          .Add((_sender, _currency), _currency * 1000)
                          .Add((_recipient, _currency), _currency * 10);

            var prevState = new State(
                balance: balance
                );
            var action = new TransferAsset(
                sender: _sender,
                recipient: _recipient,
                amount: _currency * 100
                );

            var exc = Assert.Throws <InvalidTransferSignerException>(() =>
            {
                _ = action.Execute(new ActionContext()
                {
                    PreviousStates = prevState,
                    // 송금자가 직접 사인하지 않으면 실패해야 합니다.
                    Signer     = _recipient,
                    Rehearsal  = false,
                    BlockIndex = 1,
                });
            });

            Assert.Equal(exc.Sender, _sender);
            Assert.Equal(exc.Recipient, _recipient);
            Assert.Equal(exc.TxSigner, _recipient);
        }
コード例 #9
0
        public TransferAssetDto GetTransferAssetForEdit(int id)
        {
            TransferAsset transferAssets = repository.GetAll()
                                           .Where(item => !item.IsDelete)
                                           .SingleOrDefault(item => item.Id == id);

            return(ObjectMapper.Map <TransferAssetDto>(transferAssets));
        }
コード例 #10
0
        public TransferAssetDto CreateTransferAsset(TransferAssetDto input)
        {
            TransferAsset transferAsset = ObjectMapper.Map <TransferAsset>(input);

            SetAuditInsert(transferAsset);
            _ = repository.Insert(transferAsset);
            CurrentUnitOfWork.SaveChanges();
            return(input);
        }
コード例 #11
0
        public static Payload MakeTransferPayload(string sender, string recipient, long amount)
        {
            var transfer = new TransferAsset
            {
                Sender    = sender.FromHexString(),
                Recipient = recipient.FromHexString(),
                Amount    = amount
            };

            return(TransactionFactory.MakePayload(transfer, PayloadType.TransferAsset));
        }
コード例 #12
0
        private void ProcessTransferAsset(TransferAsset transferAsset)
        {
            _clientCryptoService.DecodeEcdhTuple(transferAsset.TransferredAsset.EcdhTuple, null, out byte[] blindingFactor, out byte[] assetId);
            AttributeType attributeType = _assetsService.GetAttributeType(assetId);

            _dataAccessService.StoreSpAttribute(_accountId, attributeType, assetId, transferAsset.Signer.Value.ToHexString(), blindingFactor, transferAsset.TransferredAsset.AssetCommitment, transferAsset.SurjectionProof.AssetCommitments[0]);

            _idenitiesHubContext.Clients.Group(_accountId.ToString(CultureInfo.InvariantCulture)).SendAsync("PushAttribute", new SpAttributeDto {
                AttributeType = attributeType.ToString(), Source = transferAsset.Signer.ArraySegment.Array.ToHexString(), AssetId = assetId.ToHexString(), OriginalBlindingFactor = blindingFactor.ToHexString(), OriginalCommitment = transferAsset.TransferredAsset.AssetCommitment.ToHexString(), IssuingCommitment = transferAsset.SurjectionProof.AssetCommitments[0].ToHexString(), Validated = false, IsOverriden = false
            });
        }
コード例 #13
0
        public void Rehearsal()
        {
            var action = new TransferAsset(
                sender: _sender,
                recipient: _recipient,
                amount: _currency * 100
                );

            IAccountStateDelta nextState = action.Execute(new ActionContext()
            {
                PreviousStates = new State(ImmutableDictionary <Address, IValue> .Empty),
                Signer         = default,
コード例 #14
0
        public ListResultDto <TransferAssetDto> GetTransferAssetByCode(string code)
        {
            code = code.ToLower();
            TransferAsset transferAsset = repository.GetAll()
                                          .Where(item => item.AssetCode.ToLower() == code)
                                          .SingleOrDefault();

            System.Collections.Generic.List <TransferAssetDto> transferAssets = new System.Collections.Generic.List <TransferAssetDto>
            {
                ObjectMapper.Map <TransferAssetDto>(transferAsset)
            };
            return(new ListResultDto <TransferAssetDto>(transferAssets));
        }
コード例 #15
0
        public void DeleteTransferAsset(int id)
        {
            TransferAsset transferAsset = repository.GetAll()
                                          .Where(item => !item.IsDelete)
                                          .SingleOrDefault(item => item.Id == id);

            if (transferAsset != null)
            {
                transferAsset.IsDelete = true;
                repository.Update(transferAsset);
                CurrentUnitOfWork.SaveChanges();
            }
        }
コード例 #16
0
        public int TransferAsset(
            [Argument("SENDER-ADDRESS", Description = "A hex-encoded sender address.")] string senderAddress,
            [Argument("RECIPIENT-ADDRESS", Description = "A hex-encoded recipient address.")] string recipientAddress,
            [Argument("AMOUNT", Description = "The amount of asset to transfer.")]  string amount,
            [Argument("PATH", Description = "A file path of base64 encoded action.")] string?filePath = null,
            [Argument("MEMO", Description = "A memo of asset transfer")] string?memo = null
            )
        {
            try
            {
                filePath ??= Path.Combine(Path.GetTempPath(), Path.GetTempFileName());

                // Minter for 9c-mainnet
                var currency = new Currency("NCG", 2, minter: new Address("47d082a115c63e7b58b1532d20e631538eafadde"));
                FungibleAssetValue amountFungibleAssetValue =
                    FungibleAssetValue.Parse(currency, amount);
                Address sender    = new Address(ByteUtil.ParseHex(senderAddress));
                Address recipient = new Address(ByteUtil.ParseHex(recipientAddress));
                Nekoyume.Action.TransferAsset action = new TransferAsset(
                    sender,
                    recipient,
                    amountFungibleAssetValue,
                    memo);

                var encoded = new List(
                    new[]
                {
                    (Text)nameof(Nekoyume.Action.TransferAsset),
                    action.PlainValue
                }
                    );

                byte[] raw = Codec.Encode(encoded);
                File.WriteAllText(filePath, Convert.ToBase64String(raw));
                Console.Write(Convert.ToBase64String(raw));
                return(0);
            }
            catch (Exception e)
            {
                _console.Error.WriteLine(e);
                return(-1);
            }
        }
コード例 #17
0
        public TransferAssetDto UpdateTransferAsset(TransferAssetDto input)
        {
            TransferAsset transferAsset = repository
                                          .GetAll()
                                          .Where(item => !item.IsDelete)
                                          .SingleOrDefault(item => item.Id == input.Id);

            if (transferAsset is null)
            {
                return(null);
            }
            else
            {
                ObjectMapper.Map(input, transferAsset);
                SetAuditEdit(transferAsset);
                transferAsset = repository.Update(transferAsset);
                CurrentUnitOfWork.SaveChanges();
                return(ObjectMapper.Map <TransferAssetDto>(transferAsset));
            }
        }
コード例 #18
0
        public void ExecuteWithInvalidRecipient()
        {
            var balance = ImmutableDictionary <(Address, Currency), FungibleAssetValue> .Empty
                          .Add((_sender, _currency), _currency * 1000);

            var prevState = new State(
                balance: balance
                );
            // Should not allow TransferAsset with same sender and recipient.
            var action = new TransferAsset(
                sender: _sender,
                recipient: _sender,
                amount: _currency * 100
                );

            // No exception should be thrown when its index is less then 380000.
            _ = action.Execute(new ActionContext()
            {
                PreviousStates = prevState,
                Signer         = _sender,
                Rehearsal      = false,
                BlockIndex     = 1,
            });

            var exc = Assert.Throws <InvalidTransferRecipientException>(() =>
            {
                _ = action.Execute(new ActionContext()
                {
                    PreviousStates = prevState,
                    Signer         = _sender,
                    Rehearsal      = false,
                    BlockIndex     = 380001,
                });
            });

            Assert.Equal(exc.Sender, _sender);
            Assert.Equal(exc.Recipient, _sender);
        }
コード例 #19
0
        public void TransferAsset(
            int amount,
            int expectedCode,
            string?memo = null)
        {
            var senderPrivateKey    = new PrivateKey();
            var recipientPrivateKey = new PrivateKey();
            var filePath            = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
            var resultCode          = _command.TransferAsset(
                senderPrivateKey.ToAddress().ToHex(),
                recipientPrivateKey.ToAddress().ToHex(),
                Convert.ToString(amount),
                filePath,
                memo);

            Assert.Equal(expectedCode, resultCode);

            if (resultCode == 0)
            {
                var    rawAction = Convert.FromBase64String(File.ReadAllText(filePath));
                var    decoded   = (List)_codec.Decode(rawAction);
                string type      = (Text)decoded[0];
                Assert.Equal(nameof(Nekoyume.Action.TransferAsset), type);
                Dictionary plainValue = (Dictionary)decoded[1];
                var        action     = new TransferAsset();
                action.LoadPlainValue(plainValue);
                Assert.Equal(memo, action.Memo);
                Assert.Equal(amount, action.Amount.MajorUnit);
                Assert.Equal(senderPrivateKey.ToAddress(), action.Sender);
                Assert.Equal(recipientPrivateKey.ToAddress(), action.Recipient);
            }
            else
            {
                Assert.Contains("System.FormatException: Could not find any recognizable digits.", _console.Error.ToString());
            }
        }
コード例 #20
0
ファイル: BlockPolicyTest.cs プロジェクト: planetarium/lib9c
        public async Task MixedMiningPolicy()
        {
            var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 };
            var authorizedMinerKey   = new PrivateKey();
            var permissionedMinerKey = new PrivateKey();
            var someMinerKey         = new PrivateKey();
            var addresses            = new Address[]
            {
                authorizedMinerKey.ToAddress(),
                permissionedMinerKey.ToAddress(),
                someMinerKey.ToAddress(),
            };
            var pendingActivations = new[]
            {
                authorizedMinerKey,
                permissionedMinerKey,
                someMinerKey,
            }.Select(key => ActivationKey.Create(key, nonce).Item2).ToArray();
            var action = new TransferAsset(
                new PrivateKey().ToAddress(),
                new PrivateKey().ToAddress(),
                new FungibleAssetValue(_currency, 0, 0));

            // This creates genesis with _privateKey as its miner.
            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                default(Address),
                ImmutableHashSet <Address> .Empty,
                pendingActivations: pendingActivations);

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));
            var blockPolicySource = new BlockPolicySource(Logger.None);
            var blockChain        = new BlockChain <PolymorphicAction <ActionBase> >(
                blockPolicySource.GetPolicy(
                    minimumDifficulty: 10_000,
                    hashAlgorithmTypePolicy: null,
                    maxBlockBytesPolicy: null,
                    minTransactionsPerBlockPolicy: null,
                    maxTransactionsPerBlockPolicy: null,
                    maxTransactionsPerSignerPerBlockPolicy: null,
                    authorizedMinersPolicy: AuthorizedMinersPolicy
                    .Default
                    .Add(new SpannedSubPolicy <ImmutableHashSet <Address> >(
                             startIndex: 0,
                             endIndex: 6,
                             filter: index => index % 2 == 0,
                             value: new Address[] { authorizedMinerKey.ToAddress() }
                             .ToImmutableHashSet())),
                    permissionedMinersPolicy: PermissionedMinersPolicy
                    .Default
                    .Add(new SpannedSubPolicy <ImmutableHashSet <Address> >(
                             startIndex: 2,
                             endIndex: 10,
                             filter: index => index % 3 == 0,
                             value: new Address[] { permissionedMinerKey.ToAddress() }
                             .ToImmutableHashSet()))),
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >(),
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );

            Transaction <PolymorphicAction <ActionBase> > proof;

            // Index 1: Anyone can mine.
            await blockChain.MineBlock(someMinerKey);

            // Index 2: Only authorized miner can mine.
            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(permissionedMinerKey));

            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(someMinerKey));

            await blockChain.MineBlock(authorizedMinerKey);

            // Index 3: Only permissioned miner can mine.
            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(authorizedMinerKey));

            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(someMinerKey));

            await blockChain.MineBlock(permissionedMinerKey);

            // Index 4: Only authorized miner can mine.
            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(permissionedMinerKey));

            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(someMinerKey));

            await blockChain.MineBlock(authorizedMinerKey);

            // Index 5: Anyone can mine again.
            await blockChain.MineBlock(someMinerKey);

            // Index 6: In case both authorized mining and permissioned mining apply,
            // only authorized miner can mine.
            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(permissionedMinerKey));

            await blockChain.MineBlock(authorizedMinerKey);

            // Index 7, 8, 9: Check authorized mining ended.
            await blockChain.MineBlock(someMinerKey);

            await blockChain.MineBlock(someMinerKey);

            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(someMinerKey));

            proof = blockChain.MakeTransaction(
                permissionedMinerKey,
                new PolymorphicAction <ActionBase>[] { action });
            await blockChain.MineBlock(permissionedMinerKey);

            // Index 10, 11, 12: Check permissioned mining ended.
            await blockChain.MineBlock(someMinerKey);

            await blockChain.MineBlock(someMinerKey);

            await blockChain.MineBlock(someMinerKey);

            // Index 13, 14: Check authorized miner and permissioned miner can also mine
            // when policy is allowed for all miners.
            await blockChain.MineBlock(authorizedMinerKey);

            await blockChain.MineBlock(permissionedMinerKey);
        }
コード例 #21
0
        public async Task Transfer(string?memo, bool error)
        {
            NineChroniclesNodeService service = StandaloneContextFx.NineChroniclesNodeService !;
            Currency goldCurrency             = new GoldCurrencyState(
                (Dictionary)BlockChain.GetState(GoldCurrencyState.Address)
                ).Currency;

            Address senderAddress = service.MinerPrivateKey !.ToAddress();
            var     store         = service.Store;
            await BlockChain.MineBlock(senderAddress);

            await BlockChain.MineBlock(senderAddress);

            // 10 + 10 (mining rewards)
            Assert.Equal(
                20 * goldCurrency,
                BlockChain.GetBalance(senderAddress, goldCurrency)
                );

            Address recipient = new PrivateKey().ToAddress();
            long    txNonce   = BlockChain.GetNextTxNonce(senderAddress);

            var args = $"recipient: \"{recipient}\", txNonce: {txNonce}, amount: \"17.5\"";

            if (!(memo is null))
            {
                args += $"memo: \"{memo}\"";
            }

            var             query  = $"mutation {{ transfer({args}) }}";
            ExecutionResult result = await ExecuteQueryAsync(query);

            if (error)
            {
                Assert.NotNull(result.Errors);
            }
            else
            {
                Assert.Null(result.Errors);

                var stagedTxIds = BlockChain.GetStagedTransactionIds().ToImmutableList();
                Assert.Single(stagedTxIds);
                string transferTxIdString = stagedTxIds.Single().ToString();
                TxId   transferTxId       = new TxId(ByteUtil.ParseHex(transferTxIdString));

                Transaction <NCAction>?tx = BlockChain.StagePolicy.Get(BlockChain, transferTxId, false);
                Assert.NotNull(tx);
                Assert.IsType <TransferAsset>(tx !.Actions.Single().InnerAction);
                TransferAsset transferAsset = (TransferAsset)tx.Actions.Single().InnerAction;
                Assert.Equal(memo, transferAsset.Memo);

                var expectedResult = new Dictionary <string, object>
                {
                    ["transfer"] = transferTxIdString,
                };

                Assert.Equal(expectedResult, result.Data);

                await BlockChain.MineBlock(recipient);

                // 10 + 10 - 17.5(transfer)
                Assert.Equal(
                    FungibleAssetValue.Parse(goldCurrency, "2.5"),
                    BlockChain.GetBalance(senderAddress, goldCurrency)
                    );

                // 0 + 17.5(transfer) + 10(mining reward)
                Assert.Equal(
                    FungibleAssetValue.Parse(goldCurrency, "27.5"),
                    BlockChain.GetBalance(recipient, goldCurrency)
                    );
            }
        }
コード例 #22
0
        protected override Memory <byte> ParseTransactionalTransitional(ushort version, Memory <byte> spanBody, out TransactionalTransitionalPacketBase transactionalBlockBase)
        {
            TransferAsset block = null;

            if (version == 1)
            {
                int readBytes = 0;

                byte[] assetCommitment = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                readBytes += Globals.NODE_PUBLIC_KEY_SIZE;

                byte[] assetId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                readBytes += Globals.NODE_PUBLIC_KEY_SIZE;

                byte[] mask = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                readBytes += Globals.NODE_PUBLIC_KEY_SIZE;

                ushort assetCommitmentsCount = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);
                readBytes += sizeof(ushort);

                byte[][] assetCommitments = new byte[assetCommitmentsCount][];

                for (int i = 0; i < assetCommitmentsCount; i++)
                {
                    assetCommitments[i] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                    readBytes          += Globals.NODE_PUBLIC_KEY_SIZE;
                }

                byte[] e = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                readBytes += Globals.NODE_PUBLIC_KEY_SIZE;

                byte[][] s = new byte[assetCommitmentsCount][];

                for (int i = 0; i < assetCommitmentsCount; i++)
                {
                    s[i]       = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                    readBytes += Globals.NODE_PUBLIC_KEY_SIZE;
                }

                block = new TransferAsset
                {
                    TransferredAsset = new EncryptedAsset
                    {
                        AssetCommitment = assetCommitment,
                        EcdhTuple       = new EcdhTupleCA
                        {
                            AssetId = assetId,
                            Mask    = mask
                        }
                    },
                    SurjectionProof = new SurjectionProof
                    {
                        AssetCommitments = assetCommitments,
                        Rs = new BorromeanRingSignature
                        {
                            E = e,
                            S = s
                        }
                    }
                };

                transactionalBlockBase = block;
                return(spanBody.Slice(readBytes));
            }

            throw new BlockVersionNotSupportedException(version, BlockType);
        }