public void TestAddressGenerationFromPublicKey()
        {
            var expected = "0bebd6f0febfaf32b4c77eae6755b1d83478dcc9185c33c318d4b0a24ba54d68";

            var seed    = Ed25519Seed.FromMnemonic("witch collapse practice feed shame open despair creek road again ice least");
            var address = Ed25519Address.FromPublicKey(seed.KeyPair.PublicKey);

            Assert.AreEqual(expected, address.Address);
        }
Beispiel #2
0
        public static ReceiptPayload Deserialize(byte[] payload)
        {
            var payloadType = BitConverter.ToInt32(payload.Take(4).ToArray(), 0);
            var pointer     = 4;

            if (payloadType != ReceiptPayloadType)
            {
                throw new Exception($"Payload Type ({payloadType}) is not a receipt payload!");
            }

            var migratedAt = BitConverter.ToInt32(payload.Skip(pointer).Take(4).ToArray(), 0);

            pointer += 4;

            var final = payload[pointer] == 1;

            pointer += 1;

            var fundCount = BitConverter.ToInt16(payload.Skip(pointer).Take(2).ToArray(), 0);

            pointer += 2;

            var funds = new List <MigratedFunds>();

            for (var i = 0; i < fundCount; i++)
            {
                var tailTransactionHash = payload.Skip(pointer).Take(32).ToHex();
                pointer += 32;

                var address = Ed25519Address.Deserialize(payload.Skip(pointer).Take(33).ToArray());
                pointer += 33;

                var deposit = BitConverter.ToInt64(payload.Skip(pointer).Take(8).ToArray(), 0);
                pointer += 8;

                funds.Add(new MigratedFunds {
                    Address = address, Deposit = deposit, TailTransactionHash = tailTransactionHash
                });
            }

            var transactionLength = BitConverter.ToInt32(payload.Skip(pointer).Take(4).ToArray(), 0);

            pointer += 4;

            var transaction =
                Payload.Deserialize <TreasuryTransactionPayload>(payload.Skip(pointer).Take(transactionLength).ToArray());

            return(new ReceiptPayload
            {
                Final = final,
                Funds = funds,
                MigratedAt = migratedAt,
                Transaction = transaction,
                Type = payloadType
            });
        }
Beispiel #3
0
        public async Task <GetUnspentAddressesResponse> GetUnspentAddressesAsync(GetUnspentAddressesRequest request)
        {
            var nodeInfo = await this.Client.GetNodeInfoAsync();

            var state = new InMemoryBip44GeneratorState
            {
                AccountIndex = request.AccountIndex,
                AddressIndex = request.AddressOptions.StartIndex,
                IsInternal   = false
            };

            var unspentAddresses = new List <Bech32Address>();
            var isFirst          = true;
            var zeroCount        = 0;

            var foundAll = false;

            do
            {
                var bip32Path = Bip44AddressGenerator.GenerateAddress(state, isFirst);
                isFirst = false;

                var addressSeed = request.Seed.GenerateSeedFromPath(bip32Path);
                var address     = Ed25519Address.FromPublicKey(addressSeed.KeyPair.PublicKey);

                var addressWithBalance = await this.Client.GetAddressFromEd25519Async(address.Address);

                if (addressWithBalance.Balance == 0)
                {
                    zeroCount++;
                    if (zeroCount >= request.AddressOptions.ZeroCount)
                    {
                        foundAll = true;
                    }
                }
                else
                {
                    unspentAddresses.Add(Bech32Address.FromEd25519Address(addressWithBalance, bip32Path, nodeInfo.Bech32Hrp));

                    if (unspentAddresses.Count == request.AddressOptions.RequiredCount)
                    {
                        foundAll = true;
                    }
                }
            } while (!foundAll);

            return(new GetUnspentAddressesResponse(unspentAddresses));
        }
Beispiel #4
0
        public static Bech32Address FromEd25519Address(Ed25519Address address, Bip32Path path, string humanReadablePart)
        {
            var addressBytes = new List <byte>()
            {
                (byte)address.Type
            };

            addressBytes.AddRange(address.Address.HexToBytes());

            return(new Bech32Address
            {
                Balance = address.Balance,
                Path = path,
                Address = Crypto.Bech32.Encode(humanReadablePart, addressBytes.ToArray())
            });
        }
        public void TestAddressCreationFromEd25519AddressAndBip31Path()
        {
            var expectedAddressBech32Address = "iota1qq97h4hsl6l67v45cal2ue64k8vrg7xueyv9cv7rrr2tpgjt54xks8esknu";

            var address = new Ed25519Address
            {
                Address = "0bebd6f0febfaf32b4c77eae6755b1d83478dcc9185c33c318d4b0a24ba54d68", Balance = 100, DustAllowed = true
            };

            var path   = Bip44AddressGenerator.GenerateAddress(1, 1, false);
            var actual = Bech32Address.FromEd25519Address(address, path, "iota");

            Assert.AreEqual(expectedAddressBech32Address, actual.Address);
            Assert.AreEqual(path.ToString(), actual.Path.ToString());
            Assert.AreEqual(address.Balance, actual.Balance);
        }
Beispiel #6
0
 public SendTransferRequest(Ed25519Seed seed, Ed25519Address receiver, long amount) : this(seed,
                                                                                           new TransferOutput(receiver, amount))
 {
 }
 public TransferOutput(Ed25519Address receiver, long amount)
 {
     Receiver = receiver;
     Amount   = amount;
 }
Beispiel #8
0
        private async Task <Dictionary <UTXOInput, Ed25519Seed> > CalculateInputsAsync(Ed25519Seed seed, List <TransferOutput> outputs, int zeroCount, int accountIndex, int startIndex)
        {
            var state = new InMemoryBip44GeneratorState
            {
                AccountIndex = accountIndex,
                AddressIndex = startIndex,
                IsInternal   = false
            };

            var inputs           = new Dictionary <UTXOInput, Ed25519Seed>();
            var consumedBalance  = 0L;
            var isFirst          = true;
            var zeroBalanceCount = 0;
            var requiredBalance  = outputs.Sum(o => o.Amount);

            var foundAll = false;

            do
            {
                var bip32Path = Bip44AddressGenerator.GenerateAddress(state, isFirst);
                isFirst = false;

                var addressSeed = seed.GenerateSeedFromPath(bip32Path);
                var address     = Ed25519Address.FromPublicKey(addressSeed.KeyPair.PublicKey);

                var addressOutputs = await this.Client.GetOutputsFromEd25519Async(address.Address);

                if (addressOutputs.Count == 0)
                {
                    zeroBalanceCount++;
                    if (zeroBalanceCount >= zeroCount)
                    {
                        foundAll = true;
                    }
                }
                else
                {
                    foreach (var outputId in addressOutputs.OutputIds)
                    {
                        var addressOutput = await this.Client.FindOutputByIdAsync(outputId);

                        if (!addressOutput.IsSpent &&
                            consumedBalance < requiredBalance)
                        {
                            if (addressOutput.Output.Amount == 0)
                            {
                                zeroBalanceCount++;
                                if (zeroBalanceCount >= zeroCount)
                                {
                                    foundAll = true;
                                }
                            }
                            else
                            {
                                consumedBalance += addressOutput.Output.Amount;

                                inputs.Add(
                                    new UTXOInput
                                {
                                    TransactionId = addressOutput.TransactionId, TransactionOutputIndex = addressOutput.OutputIndex
                                },
                                    addressSeed);

                                if (consumedBalance < requiredBalance)
                                {
                                    continue;
                                }

                                if (consumedBalance - requiredBalance > 0)
                                {
                                    outputs.Add(new TransferOutput(addressOutput.Output.Address, consumedBalance - requiredBalance));
                                }

                                foundAll = true;
                            }
                        }
                    }
                }
            } while (!foundAll);

            return(inputs);
        }