コード例 #1
0
        private Transaction CreateDepositTransaction(BitcoinPubKeyAddress targetAddress, Block block, Money depositAmount, byte[] opReturnBytes)
        {
            // Create the deposit transaction.
            Transaction depositTransaction = this.transactionBuilder.BuildOpReturnTransaction(this.addressHelper.SourceChainMultisigAddress, opReturnBytes, depositAmount);

            // Add the deposit transaction to the block.
            block.AddTransaction(depositTransaction);

            this.opReturnDataReader.TryGetTargetAddress(depositTransaction, out string _).Returns(callInfo =>
            {
                callInfo[1] = targetAddress.ToString();
                return(true);
            });

            return(depositTransaction);
        }
コード例 #2
0
        public void ExtractDepositsFromBlock_Should_Only_Find_Deposits_To_Multisig()
        {
            Block block = this.network.Consensus.ConsensusFactory.CreateBlock();

            BitcoinPubKeyAddress targetAddress = this.addressHelper.GetNewTargetChainPubKeyAddress();

            byte[]      opReturnBytes      = Encoding.UTF8.GetBytes(targetAddress.ToString());
            long        depositAmount      = Money.COIN * 3;
            Transaction depositTransaction = this.transactionBuilder.BuildOpReturnTransaction(
                this.addressHelper.SourceChainMultisigAddress, opReturnBytes, depositAmount);

            block.AddTransaction(depositTransaction);

            this.opReturnDataReader.TryGetTargetAddress(depositTransaction)
            .Returns(targetAddress.ToString());

            Transaction nonDepositTransactionToMultisig = this.transactionBuilder.BuildTransaction(
                this.addressHelper.SourceChainMultisigAddress);

            block.AddTransaction(nonDepositTransactionToMultisig);

            BitcoinPubKeyAddress otherAddress = this.addressHelper.GetNewSourceChainPubKeyAddress();

            otherAddress.ToString().Should().NotBe(this.addressHelper.SourceChainMultisigAddress.ToString(),
                                                   "otherwise the next deposit should actually be extracted");
            Transaction depositTransactionToOtherAddress =
                this.transactionBuilder.BuildOpReturnTransaction(otherAddress, opReturnBytes);

            block.AddTransaction(depositTransactionToOtherAddress);

            Transaction nonDepositTransactionToOtherAddress = this.transactionBuilder.BuildTransaction(
                otherAddress);

            block.AddTransaction(nonDepositTransactionToOtherAddress);

            int blockHeight = 230;
            IReadOnlyList <IDeposit> extractedDeposits = this.depositExtractor.ExtractDepositsFromBlock(block, blockHeight);

            extractedDeposits.Count.Should().Be(1);
            IDeposit extractedTransaction = extractedDeposits[0];

            extractedTransaction.Amount.Satoshi.Should().Be(depositAmount);
            extractedTransaction.Id.Should().Be(depositTransaction.GetHash());
            extractedTransaction.TargetAddress.Should().Be(targetAddress.ToString());
            extractedTransaction.BlockNumber.Should().Be(blockHeight);
            extractedTransaction.BlockHash.Should().Be(block.GetHash());
        }
コード例 #3
0
        /// <summary>
        /// Creates a number of additional addresses in the current account.
        /// </summary>
        /// <remarks>
        /// The name given to the account is of the form "account (i)" by default, where (i) is an incremental index starting at 0.
        /// According to BIP44, an account at index (i) can only be created when the account at index (i - 1) contains at least one transaction.
        /// </remarks>
        /// <param name="network">The network these addresses will be for.</param>
        /// <param name="addressesQuantity">The number of addresses to create.</param>
        /// <param name="isChange">Whether the addresses added are change (internal) addresses or receiving (external) addresses.</param>
        /// <returns>The created addresses.</returns>
        public IEnumerable <HdAddress> CreateAddresses(Network network, int addressesQuantity, bool isChange = false)
        {
            ICollection <HdAddress> addresses = isChange ? this.InternalAddresses : this.ExternalAddresses;

            // Get the index of the last address.
            int firstNewAddressIndex = 0;

            if (addresses.Any())
            {
                firstNewAddressIndex = addresses.Max(add => add.Index) + 1;
            }

            var addressesCreated = new List <HdAddress>();

            for (int i = firstNewAddressIndex; i < firstNewAddressIndex + addressesQuantity; i++)
            {
                // Generate a new address.
                PubKey pubkey = HdOperations.GeneratePublicKey(this.ExtendedPubKey, i, isChange);
                BitcoinPubKeyAddress address = pubkey.GetAddress(network);

                // Add the new address details to the list of addresses.
                var newAddress = new HdAddress
                {
                    Index        = i,
                    HdPath       = HdOperations.CreateHdPath((int)this.GetCoinType(), this.Index, isChange, i),
                    ScriptPubKey = address.ScriptPubKey,
                    Pubkey       = pubkey.ScriptPubKey,
                    Address      = address.ToString(),
                    Transactions = new List <TransactionData>()
                };

                addresses.Add(newAddress);
                addressesCreated.Add(newAddress);
            }

            if (isChange)
            {
                this.InternalAddresses = addresses;
            }
            else
            {
                this.ExternalAddresses = addresses;
            }

            return(addressesCreated);
        }
コード例 #4
0
        public async Task <IAddressMainInfo> GetMainInfoAsync(string id)
        {
            if (BitcoinAddressHelper.IsBitcoinColoredAddress(id, _appSettings.BcnExploler.UsedNetwork()))
            {
                var result = new BitcoinColoredAddress(id, _appSettings.BcnExploler.UsedNetwork());

                return(new AddressMainInfo
                {
                    AddressId = id,
                    ColoredAddress = result.ToWif(),
                    UncoloredAddress = result.Address.ToString(),
                    IsColored = true
                });
            }

            if (BitcoinAddressHelper.IsBitcoinPubKeyAddress(id, _appSettings.BcnExploler.UsedNetwork()))
            {
                var result = new BitcoinPubKeyAddress(id, _appSettings.BcnExploler.UsedNetwork());

                return(new AddressMainInfo
                {
                    AddressId = id,
                    ColoredAddress = result.ToColoredAddress().ToWif(),
                    UncoloredAddress = result.ToString(),
                    IsColored = false
                });
            }

            if (BitcoinAddressHelper.IsBitcoinScriptAddress(id, _appSettings.BcnExploler.UsedNetwork()))
            {
                var result = new BitcoinScriptAddress(id, _appSettings.BcnExploler.UsedNetwork());

                return(new AddressMainInfo
                {
                    AddressId = id,
                    ColoredAddress = result.ToColoredAddress().ToWif(),
                    UncoloredAddress = result.ToString(),
                    IsColored = false
                });
            }

            return(null);
        }
コード例 #5
0
        public void PublicKeyAddressConversion()
        {
            foreach (var vector in TestVectorArray.Where(x => x.Type == Base58Type.PUBKEY_ADDRESS))
            {
                var addr = BitcoinAddress.Create(vector.Legacy, Network.Main);
                Assert.NotNull(addr);

                var legacyPubKey = new BitcoinPubKeyAddress(vector.Legacy);
                Assert.Equal(vector.Legacy, legacyPubKey.ToString());
                Assert.Equal(Network.Main, legacyPubKey.Network);
                Assert.Equal(vector.Hash, Encoders.Hex.EncodeData(legacyPubKey.Hash.ToBytes()));

                var cashAddrPubKey = new BitcoinPubKeyAddress(vector.CashAddr);
                Assert.Equal(vector.CashAddr, cashAddrPubKey.ToString());
                Assert.Equal(Network.Main, cashAddrPubKey.Network);
                Assert.Equal(vector.Hash, Encoders.Hex.EncodeData(cashAddrPubKey.Hash.ToBytes()));

                ValidateConversion <BitcoinPubKeyAddress>(vector, addr);
            }
        }
コード例 #6
0
        public void ExtractDepositsFromBlockShouldOnlyGetAmountsGreaterThanWithdrawalFee()
        {
            Block block = this.network.Consensus.ConsensusFactory.CreateBlock();

            BitcoinPubKeyAddress targetAddress = this.addressHelper.GetNewTargetChainPubKeyAddress();

            byte[] opReturnBytes = Encoding.UTF8.GetBytes(targetAddress.ToString());

            // Set amount to be less than deposit minimum
            long        depositAmount      = FederatedPegSettings.CrossChainTransferMinimum - 1;
            Transaction depositTransaction = this.transactionBuilder.BuildOpReturnTransaction(
                this.addressHelper.SourceChainMultisigAddress, opReturnBytes, depositAmount);

            block.AddTransaction(depositTransaction);
            this.opReturnDataReader.TryGetTargetAddress(depositTransaction, out string unused1).Returns(callInfo => { callInfo[1] = targetAddress.ToString(); return(true); });

            // Set amount to be exactly deposit minimum
            long        secondDepositAmount      = FederatedPegSettings.CrossChainTransferMinimum;
            Transaction secondDepositTransaction = this.transactionBuilder.BuildOpReturnTransaction(
                this.addressHelper.SourceChainMultisigAddress, opReturnBytes, secondDepositAmount);

            block.AddTransaction(secondDepositTransaction);
            this.opReturnDataReader.TryGetTargetAddress(secondDepositTransaction, out string unused2).Returns(callInfo => { callInfo[1] = targetAddress.ToString(); return(true); });

            // Set amount to be greater than deposit minimum
            long        thirdDepositAmount      = FederatedPegSettings.CrossChainTransferMinimum + 1;
            Transaction thirdDepositTransaction = this.transactionBuilder.BuildOpReturnTransaction(
                this.addressHelper.SourceChainMultisigAddress, opReturnBytes, thirdDepositAmount);

            block.AddTransaction(thirdDepositTransaction);
            this.opReturnDataReader.TryGetTargetAddress(thirdDepositTransaction, out string unused3).Returns(callInfo => { callInfo[1] = targetAddress.ToString(); return(true); });// Extract deposits
            int blockHeight = 12345;
            IReadOnlyList <IDeposit> extractedDeposits = this.depositExtractor.ExtractDepositsFromBlock(block, blockHeight);

            // Should only be two, with the value just over the withdrawal fee.
            extractedDeposits.Count.Should().Be(2);
            foreach (IDeposit extractedDeposit in extractedDeposits)
            {
                Assert.True(extractedDeposit.Amount >= FederatedPegSettings.CrossChainTransferMinimum);
            }
        }
コード例 #7
0
        public async Task ExtractLargeConversionDeposits_ReturnDeposits_AboveNormalThresholdAsync()
        {
            Block block = this.network.Consensus.ConsensusFactory.CreateBlock();

            // Create the target address.
            BitcoinPubKeyAddress targetAddress = this.addressHelper.GetNewTargetChainPubKeyAddress();

            byte[] opReturnBytes = Encoding.UTF8.GetBytes(targetAddress.ToString());

            // Set amount to be less than deposit minimum
            CreateDepositTransaction(targetAddress, block, FederatedPegSettings.CrossChainTransferMinimum - 1, opReturnBytes);

            // Set amount to be less than the small threshold amount.
            CreateDepositTransaction(targetAddress, block, this.federationSettings.SmallDepositThresholdAmount - 1, opReturnBytes);

            // Set amount to be exactly the normal threshold amount.
            CreateDepositTransaction(targetAddress, block, this.federationSettings.NormalDepositThresholdAmount, opReturnBytes);

            byte[] ethOpReturnBytes = Encoding.UTF8.GetBytes(InterFluxOpReturnEncoder.Encode(DestinationChain.ETH, TargetETHAddress));

            // Set amount to be equal to the normal threshold amount.
            CreateConversionTransaction(block, DepositValidationHelper.ConversionTransactionMinimum - 1, ethOpReturnBytes);

            // Set amount to be greater than the conversion deposit minimum amount.
            CreateConversionTransaction(block, DepositValidationHelper.ConversionTransactionMinimum + 1, ethOpReturnBytes);

            int blockHeight = 12345;
            IReadOnlyList <IDeposit> extractedDeposits = await this.depositExtractor.ExtractDepositsFromBlock(block, blockHeight, this.retrievalTypeConfirmations);

            // Should only be 1, with the value just over the withdrawal fee.
            IEnumerable <IDeposit> applicable = extractedDeposits.Where(d => d.RetrievalType == DepositRetrievalType.ConversionLarge);

            applicable.Count().Should().Be(1);
            foreach (IDeposit extractedDeposit in applicable)
            {
                Assert.True(extractedDeposit.Amount > DepositValidationHelper.ConversionTransactionMinimum);
                Assert.Equal(TargetETHAddress, extractedDeposit.TargetAddress);
            }
        }
コード例 #8
0
        static string[] ReadMsgTxn(string MsgData)
        {
            byte[] bts = MsgData.ToLower().HexToByteArray();

            string TxnHex      = WriteBts(bts, 0, 16).ToHex();
            string LinkedTxn   = WriteBts(bts, 16, 16).ToHex();
            string FromAddress = WriteBts(bts, 32, 20).ToHex();
            string Signature   = WriteBts(bts, 52, 65).ToHex();
            string Message     = WriteBts(bts, 117, bts.Length - 117).ToHex();

            if (!string.IsNullOrEmpty(LinkedTxn) && LinkedTxn.HexToByteArray().Length != 16)
            {
                return(null);
            }
            if (TxnHex.HexToByteArray().Length != 16)
            {
                return(null);
            }

            System.Security.Cryptography.MD5 sha1 = System.Security.Cryptography.MD5.Create();
            if (TxnHex != sha1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(FromAddress + Signature + Message)).ToHex())
            {
                return(null);
            }

            Network net = Network.Main;
            BitcoinPubKeyAddress bitcoinPubKeyAddress = new BitcoinPubKeyAddress(new KeyId(FromAddress.HexToByteArray()), net);

            Message     = System.Text.Encoding.UTF8.GetString(Message.HexToByteArray());
            Signature   = Convert.ToBase64String(Signature.HexToByteArray());
            FromAddress = bitcoinPubKeyAddress.ToString();

            if (bitcoinPubKeyAddress.VerifyMessage(Message, Signature) == false)
            {
                return(null);
            }

            return(new string[] { TxnHex, FromAddress, Signature, Message, LinkedTxn });
        }
コード例 #9
0
        public void BuildTransactionUsesGivenChangeAddress()
        {
            WalletTransactionHandlerTestContext testContext = SetupWallet();
            TransactionBuildContext             context     = CreateContext(this.Network, testContext.WalletReference, "password", testContext.DestinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0);

            var key = new Key();
            BitcoinPubKeyAddress address       = key.PubKey.GetAddress(this.Network);
            HdAddress            changeAddress = context.ChangeAddress = new HdAddress
            {
                Index        = 0,
                HdPath       = $"m/44'/0'/0'/0/0",
                Address      = address.ToString(),
                Pubkey       = key.PubKey.ScriptPubKey,
                ScriptPubKey = address.ScriptPubKey,
                //Transactions = new List<TransactionData>()
            };

            Transaction transactionResult = testContext.WalletTransactionHandler.BuildTransaction(context);

            Transaction result = this.Network.CreateTransaction(transactionResult.ToHex());

            Assert.Single(result.Inputs);
            Assert.Equal(testContext.AddressTransaction.Id, result.Inputs[0].PrevOut.Hash);

            Assert.Equal(2, result.Outputs.Count);
            TxOut output = result.Outputs[0];

            Assert.Equal((testContext.AddressTransaction.Amount - context.TransactionFee - 7500), output.Value);
            Assert.Equal(changeAddress.ScriptPubKey, output.ScriptPubKey);

            output = result.Outputs[1];
            Assert.Equal(7500, output.Value);
            Assert.Equal(testContext.DestinationKeys.PubKey.ScriptPubKey, output.ScriptPubKey);

            Assert.Equal(testContext.AddressTransaction.Amount - context.TransactionFee, result.TotalOut);
            Assert.NotNull(transactionResult.GetHash());
            Assert.Equal(result.GetHash(), transactionResult.GetHash());
        }
コード例 #10
0
        /// <summary>
        /// Interactive example that walks through creating, signing, and broadcasting a Dash transaction.
        /// Make sure you have Dash Core wallet running on TestNet for this example to work.
        /// </summary>
        public static void RunExample()
        {
            // Create a new HD extended private key
            ExtKey extKey = CreateExtKey();

            // Derive a child address so we can send it some coins
            var    extPubKey                  = extKey.Neuter().GetWif(_network);
            int    customerId                 = 1234567;
            string keyDerivationPath          = $"{customerId}/0";
            BitcoinPubKeyAddress childAddress = DeriveChildAddress(extPubKey.ToString(), keyDerivationPath);

            // Watch this address in your core wallet so that you can monitor it for funds
            RPCClient rpc = GetRpcClient();

            rpc.ImportAddress(childAddress, $"Customer {customerId}", false);

            // Send some coins manually to the address just created
            Console.WriteLine($"Now, go to another wallet and send some coins to address {childAddress}.");
            Console.WriteLine($"Wait a few minutes for it to confirm, then press ENTER to continue.");
            Console.ReadLine();

            // Create and sign a transaction that spends the coins received by the address above.
            Console.WriteLine($"Enter an address of yours to which you want to receive coins:");
            string toAddr = Console.ReadLine();

            Console.WriteLine($"Enter the amount to spend:");
            string spend = Console.ReadLine();

            decimal minerFee      = 0.00001m;
            decimal amountToSpend = Convert.ToDecimal(spend) - minerFee;

            Key privateKey = extKey.Derive(KeyPath.Parse(keyDerivationPath)).PrivateKey;

            var transaction = CreateAndSignTransaction(childAddress.ToString(), toAddr, amountToSpend, privateKey);

            // Finally, broadcast transaction to network
            rpc.SendRawTransaction(transaction);
        }
コード例 #11
0
        public void ExtractNormalDeposits_Should_Only_Find_Deposits_To_Multisig()
        {
            Block block = this.network.Consensus.ConsensusFactory.CreateBlock();

            BitcoinPubKeyAddress targetAddress = this.addressHelper.GetNewTargetChainPubKeyAddress();

            byte[] opReturnBytes = Encoding.UTF8.GetBytes(targetAddress.ToString());

            // Create a deposit above the small deposit threshold.
            Transaction depositTransaction = CreateDepositTransaction(targetAddress, block, Money.Coins(11), opReturnBytes);

            Transaction nonDepositTransactionToMultisig = this.transactionBuilder.BuildTransaction(this.addressHelper.SourceChainMultisigAddress);

            block.AddTransaction(nonDepositTransactionToMultisig);

            BitcoinPubKeyAddress otherAddress = this.addressHelper.GetNewSourceChainPubKeyAddress();

            otherAddress.ToString().Should().NotBe(this.addressHelper.SourceChainMultisigAddress.ToString(), "otherwise the next deposit should actually be extracted");
            Transaction depositTransactionToOtherAddress = this.transactionBuilder.BuildOpReturnTransaction(otherAddress, opReturnBytes);

            block.AddTransaction(depositTransactionToOtherAddress);

            Transaction nonDepositTransactionToOtherAddress = this.transactionBuilder.BuildTransaction(otherAddress);

            block.AddTransaction(nonDepositTransactionToOtherAddress);

            int blockHeight = 230;
            IReadOnlyList <IDeposit> extractedDeposits = this.depositExtractor.ExtractDepositsFromBlock(block, blockHeight, new[] { DepositRetrievalType.Normal });

            extractedDeposits.Count.Should().Be(1);
            IDeposit extractedTransaction = extractedDeposits[0];

            extractedTransaction.Amount.Satoshi.Should().Be(Money.Coins(11));
            extractedTransaction.Id.Should().Be(depositTransaction.GetHash());
            extractedTransaction.TargetAddress.Should().Be(targetAddress.ToString());
            extractedTransaction.BlockNumber.Should().Be(blockHeight);
            extractedTransaction.BlockHash.Should().Be(block.GetHash());
        }
コード例 #12
0
ファイル: ColoredCoinsTests.cs プロジェクト: georgepinca/src
        public void CanCreateAssetAddress()
        {
            //The issuer first generates a private key: 18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725.
            var key = new Key(TestUtils.ParseHex("18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725"));
            //He calculates the corresponding address: 16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM.
            BitcoinPubKeyAddress address = key.PubKey.Decompress().GetAddress(this.networkMain);

            Assert.Equal("16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM", address.ToString());

            //Next, he builds the Pay-to-PubKey-Hash script associated to that address: OP_DUP OP_HASH160 010966776006953D5567439E5E39F86A0D273BEE OP_EQUALVERIFY OP_CHECKSIG
            Script script = address.ScriptPubKey;

            Assert.Equal("OP_DUP OP_HASH160 010966776006953D5567439E5E39F86A0D273BEE OP_EQUALVERIFY OP_CHECKSIG", script.ToString().ToUpper());

            BitcoinScriptAddress oo = script.GetScriptAddress(this.networkMain);

            //The script is hashed: 36e0ea8e93eaa0285d641305f4c81e563aa570a2.
            Assert.Equal("36e0ea8e93eaa0285d641305f4c81e563aa570a2", script.Hash.ToString());

            Assert.Equal("36e0ea8e93eaa0285d641305f4c81e563aa570a2", key.PubKey.Decompress().Hash.ScriptPubKey.Hash.ToString());
            //Finally, the hash is converted to a base 58 string with checksum using version byte 23: ALn3aK1fSuG27N96UGYB1kUYUpGKRhBuBC.
            Assert.Equal("ALn3aK1fSuG27N96UGYB1kUYUpGKRhBuBC", script.Hash.ToAssetId().GetWif(this.networkMain).ToString());
        }
コード例 #13
0
        public async Task ExtractSmallDeposits_ReturnDeposits_BelowSmallThreshold_AboveMinimumAsync()
        {
            Block block = this.network.Consensus.ConsensusFactory.CreateBlock();

            // Create the target address.
            BitcoinPubKeyAddress targetAddress = this.addressHelper.GetNewTargetChainPubKeyAddress();

            byte[] opReturnBytes = Encoding.UTF8.GetBytes(targetAddress.ToString());

            // Set amount to be less than deposit minimum
            CreateDepositTransaction(targetAddress, block, FederatedPegSettings.CrossChainTransferMinimum - 1, opReturnBytes);

            // Set amount to be less than the small threshold amount.
            CreateDepositTransaction(targetAddress, block, this.federationSettings.SmallDepositThresholdAmount - 1, opReturnBytes);

            // Set amount to be exactly the small threshold amount.
            CreateDepositTransaction(targetAddress, block, this.federationSettings.SmallDepositThresholdAmount, opReturnBytes);

            // Set amount to be greater than the small threshold amount.
            CreateDepositTransaction(targetAddress, block, this.federationSettings.SmallDepositThresholdAmount + 1, opReturnBytes);

            // Set amount to be greater than the normal threshold amount.
            CreateDepositTransaction(targetAddress, block, this.federationSettings.NormalDepositThresholdAmount + 1, opReturnBytes);

            int blockHeight = 12345;
            IReadOnlyList <IDeposit> extractedDeposits = await this.depositExtractor.ExtractDepositsFromBlock(block, blockHeight, this.retrievalTypeConfirmations);

            IEnumerable <IDeposit> applicable = extractedDeposits.Where(d => d.RetrievalType == DepositRetrievalType.Small);

            // Should only be two, with the value just over the withdrawal fee.
            applicable.Count().Should().Be(2);
            foreach (IDeposit extractedDeposit in applicable)
            {
                Assert.True(extractedDeposit.Amount <= this.federationSettings.SmallDepositThresholdAmount);
            }
        }
コード例 #14
0
        public async Task <Transaction> GetTransaction(string id)
        {
            var tx = await _client.GetRawTransactionAsync(id);

            if (tx == null)
            {
                return(null);
            }
            var transaction = new Transaction
            {
                Blockhash       = tx.Blockhash,
                TransactionId   = tx.Txid,
                Size            = tx.Size,
                TransactionIn   = new List <In>(),
                TransactionsOut = new List <Out>(),
            };

            // this fails b/c no input validation
            // Debug.Assert(id == transaction.TransactionId);

            int index = 0;

            foreach (var rpcIn in tx.Vin)
            {
                var inp = new In {
                    Index = index
                };

                if (rpcIn.Coinbase == null)
                {
                    string hexScript                 = rpcIn.ScriptSig.Hex;
                    byte[] decodedScript             = Encoders.Hex.DecodeData(hexScript);
                    Script script                    = new Script(decodedScript);
                    PayToPubkeyHashTemplate template = new PayToPubkeyHashTemplate();


                    PayToPubkeyHashScriptSigParameters param = template.ExtractScriptSigParameters(script);
                    if (param != null)
                    {
                        PubKey pubKey = param.PublicKey;
                        BitcoinPubKeyAddress address = pubKey.GetAddress(NetworkSpec.ObsidianMain());

                        inp.Address = address.ToString();
                    }
                    else
                    {
                        inp.Address = "none";
                    }

                    inp.TransactionId = rpcIn.Txid;
                    inp.VOut          = (int)rpcIn.Vout;
                    inp.Sequence      = rpcIn.Sequence;
                    inp.ScriptSigHex  = rpcIn.ScriptSig.Hex;
                }
                else
                {
                    inp.Coinbase = rpcIn.Coinbase;
                    inp.Sequence = rpcIn.Sequence;
                }

                transaction.TransactionIn.Add(inp);
            }

            if (transaction.TransactionIn[0].Coinbase != null)
            {
                //Debug.Assert(transaction.TransactionIn.Count == 1);
                transaction.IsCoinBase = true;
            }

            index = 0;
            foreach (var output in tx.Vout)
            {
                var @out = new Out
                {
                    TransactionId = transaction.TransactionId,
                    Value         = output.Value,
                    Quantity      = output.N,
                    AssetId       = null,
                    Index         = index++
                };
                if (output.ScriptPubKey.Addresses != null)                 // Satoshi 14.2
                {
                    @out.Address = output.ScriptPubKey.Addresses.FirstOrDefault();
                }
                else
                {
                    string hexScript = output.ScriptPubKey.Hex;

                    if (!string.IsNullOrEmpty(hexScript))
                    {
                        byte[] decodedScript         = Encoders.Hex.DecodeData(hexScript);
                        Script script                = new Script(decodedScript);
                        var    pubKey                = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(script);
                        BitcoinPubKeyAddress address = pubKey.GetAddress(NetworkSpec.ObsidianMain());
                        @out.Address = address.ToString();
                    }
                    else
                    {
                        @out.Address = "none";
                    }
                }

                transaction.TransactionsOut.Add(@out);
            }



            return(transaction);
        }
コード例 #15
0
        public BaseRsp <string> Publish(Models.ContractPublichModel model)
        {
            var resault = new BaseRsp <string>();
            var net     = model.Net == "test" ? NBitcoin.Wicc.Wicc.Instance.Testnet : NBitcoin.Wicc.Wicc.Instance.Mainnet;
            var apiUrl  = "http://rpc.5.me/jsonrpc/" + model.Net;

            BitcoinPubKeyAddress address = null;

            try
            {
                var secret = new BitcoinSecret(model.PrivKey, net);
                address = secret.GetAddress();
            }
            catch
            {
                resault.data = "提供的私钥有误, 请检查私钥或网络";
                return(resault);
            }

            if (model.Contract.Length > 64 * 1024)
            {
                resault.data = "合约代码长度超过64KB";
                return(resault);
            }

            var accountInfo = HttpGet(apiUrl + "/GetAccountInfo/" + address.ToString());

            if (accountInfo == null)
            {
                resault.data = "RPC钱包服务暂时不可用";
                return(resault);
            }

            var regId = accountInfo.data.regID?.ToString();

            if (string.IsNullOrEmpty(regId))
            {
                resault.data = "该地址未激活";
                return(resault);
            }
            else if (long.Parse(accountInfo.data.balance.ToString()) < long.Parse(model.Fee))
            {
                resault.data = "该地址当前余额不足以支付手续费";
                return(resault);
            }

            WalletServiceApi.Wallet wt = new WalletServiceApi.Wallet()
            {
                Network = net,
                Prikey  = model.PrivKey,
                UserId  = new UserId(uint.Parse(regId.Split('-')[0]), uint.Parse(regId.Split('-')[1]))
            };

            var height = HttpGet(apiUrl + "/GetBlockCount");

            try
            {
                var sign = wt.GetRegisteAppRaw(string.Empty, model.Contract, ulong.Parse(model.Fee), uint.Parse(height.data.ToString()));

                var submittx = HttpPost <dynamic>(apiUrl + "/SubmitTx", "\"" + sign + "\"");

                if (!submittx.success)
                {
                    resault.data = "上链失败: " + submittx.msg;
                    return(resault);
                }
                else
                {
                    resault.data    = "交易哈希: " + submittx.data.hash;
                    resault.success = true;
                    return(resault);
                }
            }
            catch (Exception ex)
            {
                resault.data = "签名失败: " + ex.Message;
                return(resault);
            }


            resault.success = false;
            resault.data    = "发布失败";

            return(resault);
        }
コード例 #16
0
        public BaseRsp <string> DynLoad(Models.ContractDynLoadModel model)
        {
            var resault = new BaseRsp <string>();
            var apiUrl  = "http://rpc.5.me/jsonrpc/test";

            BitcoinPubKeyAddress address = null;

            try
            {
                var secret = new BitcoinSecret(model.PrivKey, NBitcoin.Wicc.Wicc.Instance.Testnet);
                address = secret.GetAddress();
            }
            catch
            {
                resault.data = "提供的私钥有误, 请检查私钥或网络";
                return(resault);
            }

            var accountInfo = HttpGet(apiUrl + "/GetAccountInfo/" + address.ToString());

            if (accountInfo == null)
            {
                resault.data = "RPC钱包服务暂时不可用";
                return(resault);
            }

            var regId = accountInfo.data.regID?.ToString();

            if (string.IsNullOrEmpty(regId))
            {
                resault.data = "该地址未激活";
                return(resault);
            }
            else if (long.Parse(accountInfo.data.balance.ToString()) < long.Parse(model.Fee))
            {
                resault.data = "该地址当前余额不足以支付手续费";
                return(resault);
            }

            WalletServiceApi.Wallet wt = new WalletServiceApi.Wallet()
            {
                Network = NBitcoin.Wicc.Wicc.Instance.Testnet,
                Prikey  = model.PrivKey,
                UserId  = new UserId(uint.Parse(regId.Split('-')[0]), uint.Parse(regId.Split('-')[1]))
            };

            var height = HttpGet(apiUrl + "/GetBlockCount");

            try
            {
                List <byte> codes = new List <byte>()
                {
                    0xdd, 0xdd
                };
                codes.AddRange(Encoding.UTF8.GetBytes(model.Contract));

                var sign = wt.CreateContractTxRaw("74505-1", codes.ToArray(), ulong.Parse(model.Fee), uint.Parse(height.data.ToString()));

                var submittx = HttpPost <dynamic>(apiUrl + "/SubmitTx", "\"" + sign + "\"");

                if (!submittx.success)
                {
                    resault.data = submittx.msg;
                    return(resault);
                }
                else
                {
                    resault.data    = "交易哈希: " + submittx.data.hash;
                    resault.success = true;
                    return(resault);
                }
            }
            catch (Exception ex)
            {
                resault.data = "签名失败: " + ex.Message;
                return(resault);
            }


            resault.success = false;
            resault.data    = "发布失败";

            return(resault);
        }
コード例 #17
0
        public async Task <Transaction> GetTransaction(string id)
        {
            try
            {
                GetRawTransactionRpcModel tx = await RpcClient.GetRawTransactionAsync(id);

                if (tx == null)
                {
                    return(null);
                }

                TransactionType transactiontype = GetTransactionType(tx);

                var transaction = new Transaction
                {
                    OriginalJson    = tx.OriginalJson,
                    TransactionType = transactiontype,
                    Blockhash       = tx.Blockhash,
                    TransactionId   = tx.Txid,
                    Size            = tx.Size,
                    TransactionIn   = new List <VIn>(),
                    TransactionsOut = new List <Out>(),
                    Time            = tx.GetTime()
                };


                int index = 0;
                foreach (var rpcIn in tx.Vin)
                {
                    var vIn = new VIn
                    {
                        Index        = index,
                        Coinbase     = rpcIn.Coinbase,
                        Sequence     = rpcIn.Sequence,
                        ScriptSigHex = rpcIn.ScriptSig?.Hex,
                        AssetId      = null,
                        // pointer to previous tx/vout:
                        PrevTxIdPointer = rpcIn.Txid,
                        PrevVOutPointer = (int)rpcIn.Vout,
                        // we'll try to fetch this id possible
                        PrevVOutFetchedAddress = null,
                        PrevVOutFetchedValue   = 0
                    };

                    if (rpcIn.Txid != null)
                    {
                        // Retrieve the origin address by retrieving the previous transaction and extracting the receive address and value
                        var previousTx = await RpcClient.GetRawTransactionAsync(rpcIn.Txid);

                        if (previousTx != null)
                        {
                            var n = rpcIn.Vout;
                            Debug.Assert(n == previousTx.Vout[n].N);
                            vIn.PrevVOutFetchedAddress = previousTx.Vout[n].ScriptPubKey.Addresses.First();
                            vIn.PrevVOutFetchedValue   = previousTx.Vout[n].Value;
                        }
                    }
                    transaction.TransactionIn.Add(vIn);
                }



                index = 0;
                foreach (var output in tx.Vout)
                {
                    var @out = new Out
                    {
                        TransactionId = transaction.TransactionId,
                        Value         = output.Value,
                        Quantity      = output.N,
                        AssetId       = null,
                        Index         = index++,
                    };

                    if (output.ScriptPubKey.Addresses != null)                     // Satoshi 14.2
                    {
                        @out.Address = output.ScriptPubKey.Addresses.FirstOrDefault();
                    }
                    else
                    {
                        string hexScript = output.ScriptPubKey.Hex;

                        if (!string.IsNullOrEmpty(hexScript))
                        {
                            byte[] decodedScript = Encoders.Hex.DecodeData(hexScript);
                            Script script        = new Script(decodedScript);
                            var    pubKey        = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(script);
                            if (pubKey != null)
                            {
                                BitcoinPubKeyAddress address = pubKey.GetAddress(NetworkSpec.ObsidianMain());
                                @out.Address = address.ToString();
                            }
                            else
                            {
                                @out.Address = script.ToString();
                            }
                        }
                        else
                        {
                            Debug.Assert(output.ScriptPubKey.Type == NonStandardAddress);
                            @out.Address = output.ScriptPubKey.Type;
                        }
                    }
                    transaction.TransactionsOut.Add(@out);
                }

                return(transaction);
            }
            catch { }
            return(null);
        }
コード例 #18
0
        public string GenerateIdentity()
        {
            // Generate a fixed identity.
            string recoveryPhrase = "mystery problem faith negative member bottom concert bundle asthma female process twelve";
            var    mnemonic       = new Mnemonic(recoveryPhrase);
            ExtKey masterNode     = mnemonic.DeriveExtKey();

            ExtPubKey walletRoot   = masterNode.Derive(new KeyPath("m/44'")).Neuter();
            ExtKey    identityRoot = masterNode.Derive(new KeyPath("m/302'"));

            ExtKey identity0 = identityRoot.Derive(0, true);
            ExtKey identity1 = identityRoot.Derive(1, true);

            BitcoinPubKeyAddress identity0Address = identity0.PrivateKey.PubKey.GetAddress(profileNetwork);
            BitcoinPubKeyAddress identity1Address = identity1.PrivateKey.PubKey.GetAddress(profileNetwork);

            string identity0Id = identity0Address.ToString(); // PTe6MFNouKATrLF5YbjxR1bsei2zwzdyLU
            string identity1Id = identity1Address.ToString(); // PAcmQwEMW2oxzRBz7u6oFQMtYPSYqoXyiw

            // Create an identity profile that should be signed and pushed.
            IdentityModel identityModel = new IdentityModel
            {
                Id        = identity0Id,
                Name      = "This is a person",
                ShortName = "None of yoru concern",
                Alias     = "JD",
                Title     = "President of the World",
                Email     = "*****@*****.**"
            };

            byte[] entityBytes = MessagePackSerializer.Serialize(identityModel);

            // Testing to only sign the name.
            string signature = identity0.PrivateKey.SignMessage(entityBytes);

            IdentityDocument identityDocument = new IdentityDocument
            {
                Owner     = identityModel.Id,
                Body      = identityModel,
                Signature = signature
            };

            string json = JsonConvert.SerializeObject(identityDocument);

            RestClient client = CreateClient();

            // Get the identity, if it exists.
            var request = new RestRequest($"/identity/{identityModel.Id}");
            IRestResponse <string> response = client.Get <string>(request);

            //if (response.StatusCode != System.Net.HttpStatusCode.OK)
            //{
            //   throw new ApplicationException(response.ErrorMessage);
            //}

            string data = response.Data;

            // Persist the identity.
            var request2 = new RestRequest($"/identity/{identityModel.Id}");

            request2.AddJsonBody(identityDocument);
            IRestResponse <string> response2 = client.Put <string>(request2);

            if (response2.StatusCode != System.Net.HttpStatusCode.OK)
            {
                throw new ApplicationException(response2.ErrorMessage);
            }

            return(identity0Id);
        }
コード例 #19
0
        private async Task FinishOutputs(Guid transactionId, Transaction tr, BitcoinPubKeyAddress hotWallet)
        {
            await _broadcastedOutputRepository.InsertOutputs(tr.Outputs.AsCoins()
                                                             .Where(o => o.ScriptPubKey.GetDestinationAddress(_connectionParams.Network).ToString() == hotWallet.ToString())
                                                             .Select(o => new BroadcastedOutput(o, transactionId, _connectionParams.Network)));

            await _broadcastedOutputRepository.SetTransactionHash(transactionId, tr.GetHash().ToString());

            await _spentOutputService.SaveSpentOutputs(transactionId, tr);
        }
コード例 #20
0
        public void ExtractDepositsFromBlock_Should_Create_One_Deposit_Per_Transaction_To_Multisig()
        {
            Block block = this.network.Consensus.ConsensusFactory.CreateBlock();

            BitcoinPubKeyAddress targetAddress = this.addressHelper.GetNewTargetChainPubKeyAddress();

            byte[]      opReturnBytes      = Encoding.UTF8.GetBytes(targetAddress.ToString());
            long        depositAmount      = Money.COIN * 3;
            Transaction depositTransaction = this.transactionBuilder.BuildOpReturnTransaction(
                this.addressHelper.SourceChainMultisigAddress, opReturnBytes, depositAmount);

            block.AddTransaction(depositTransaction);

            this.opReturnDataReader.TryGetTargetAddress(depositTransaction)
            .Returns(targetAddress.ToString());

            //add another deposit to the same address
            long        secondDepositAmount      = Money.COIN * 2;
            Transaction secondDepositTransaction = this.transactionBuilder.BuildOpReturnTransaction(
                this.addressHelper.SourceChainMultisigAddress, opReturnBytes, secondDepositAmount);

            block.AddTransaction(secondDepositTransaction);
            this.opReturnDataReader.TryGetTargetAddress(secondDepositTransaction)
            .Returns(targetAddress.ToString());

            //add another deposit to a different address
            string newTargetAddress = this.addressHelper.GetNewTargetChainPubKeyAddress().ToString();

            byte[]      newOpReturnBytes        = Encoding.UTF8.GetBytes(newTargetAddress);
            long        thirdDepositAmount      = Money.COIN * 34;
            Transaction thirdDepositTransaction = this.transactionBuilder.BuildOpReturnTransaction(
                this.addressHelper.SourceChainMultisigAddress, newOpReturnBytes, thirdDepositAmount);

            block.AddTransaction(thirdDepositTransaction);

            this.opReturnDataReader.TryGetTargetAddress(thirdDepositTransaction)
            .Returns(newTargetAddress);

            int blockHeight = 12345;
            IReadOnlyList <IDeposit> extractedDeposits = this.depositExtractor.ExtractDepositsFromBlock(block, blockHeight);

            extractedDeposits.Count.Should().Be(3);
            extractedDeposits.Select(d => d.BlockNumber).Should().AllBeEquivalentTo(blockHeight);
            extractedDeposits.Select(d => d.BlockHash).Should().AllBeEquivalentTo(block.GetHash());

            IDeposit extractedTransaction = extractedDeposits[0];

            extractedTransaction.Amount.Satoshi.Should().Be(depositAmount);
            extractedTransaction.Id.Should().Be(depositTransaction.GetHash());
            extractedTransaction.TargetAddress.Should()
            .Be(targetAddress.ToString());

            extractedTransaction = extractedDeposits[1];
            extractedTransaction.Amount.Satoshi.Should().Be(secondDepositAmount);
            extractedTransaction.Id.Should().Be(secondDepositTransaction.GetHash());
            extractedTransaction.TargetAddress.Should()
            .Be(targetAddress.ToString());

            extractedTransaction = extractedDeposits[2];
            extractedTransaction.Amount.Satoshi.Should().Be(thirdDepositAmount);
            extractedTransaction.Id.Should().Be(thirdDepositTransaction.GetHash());
            extractedTransaction.TargetAddress.Should().Be(newTargetAddress);
        }
コード例 #21
0
        public string GenerateRandomIdentity()
        {
            // Generate a random seed and new identity.
            var mnemonic = new Mnemonic(Wordlist.English, WordCount.Twelve);

            // string recoveryPhrase = "";
            // var mnemonic = new Mnemonic(recoveryPhrase);

            ExtKey masterNode = mnemonic.DeriveExtKey();

            ExtPubKey walletRoot   = masterNode.Derive(new KeyPath("m/44'")).Neuter();
            ExtKey    identityRoot = masterNode.Derive(new KeyPath("m/302'"));

            ExtKey identity0 = identityRoot.Derive(0, true);
            ExtKey identity1 = identityRoot.Derive(1, true);

            BitcoinPubKeyAddress identity0Address = identity0.PrivateKey.PubKey.GetAddress(profileNetwork);
            BitcoinPubKeyAddress identity1Address = identity1.PrivateKey.PubKey.GetAddress(profileNetwork);

            string identity0Id = identity0Address.ToString();

            // Create an identity profile that should be signed and pushed.
            //Identity identityModel = new Identity
            //{
            //   Identifier = identity0Id,
            //   Name = "Blockcore Hub",
            //   Email = "*****@*****.**",
            //   Url = "https://city.hub.liberstad.com",
            //   Image = "https://www.blockcore.net/assets/blockcore-256x256.png"
            //};

            //Identity identityModel = new Identity
            //{
            //   Identifier = identity0Id,
            //   Name = "Liberstad Hub",
            //   Email = "*****@*****.**",
            //   Url = "https://city.hub.liberstad.com",
            //   Image = "https://file.city-chain.org/liberstad-square-logo.png"
            //};

            string key        = identity0Address.ToString();
            string identifier = "did:is:" + key;

            var identity = new Identity
            {
                Identifier = identifier,
                Name       = "John Doe",
                ShortName  = "John",
                Alias      = "JD",
                Title      = "Gone missing",
                Type       = "identity",
                Timpestamp = ToUnixEpochDate(new DateTime(2020, 2, 2))
            };

            //JsonWebKey key = new JsonWebKey();
            //key.KeyId = identity0Id;

            var header = new Dictionary <string, object>();

            header.Add("typ", "JWT");
            header.Add("kid", key);

            string token = JWT.Encode(identity, identity0.PrivateKey, JwsAlgorithm.ES256K, header);
            // This should crash with exception: "Blockcore.Jose.JoseException: Payload is missing required signature".

            Message message = new Message()
            {
                Version = 4,
                Content = token
            };

            RestClient client = CreateClient();

            // Persist the identity.
            var request2 = new RestRequest($"/api/identity");

            request2.AddJsonBody(message);
            IRestResponse <string> response2 = client.Put <string>(request2);

            if (response2.StatusCode != System.Net.HttpStatusCode.OK)
            {
                throw new ApplicationException(response2.ErrorMessage);
            }

            return(identity0Id);
        }
コード例 #22
0
        private async Task GenerateAssetOutputs()
        {
            await _logger.WriteInfoAsync("GenerateOutputsFunction", "GenerateAssetOutputs", null, "Start process");

            var hotWallet = new BitcoinPubKeyAddress(_baseSettings.HotWalletForPregeneratedOutputs, _connectionParams.Network);
            var assets    = (await _assetRepository.GetBitcoinAssets()).Where(o => !string.IsNullOrEmpty(o.AssetAddress) &&
                                                                              !o.IsDisabled &&
                                                                              o.IssueAllowed).ToList();

            foreach (var asset in assets)
            {
                try
                {
                    if (asset.DefinitionUrl == null)
                    {
                        await _logger.WriteWarningAsync("GenerateOutputsFunction", "GenerateAssetOutputs", $"Asset: {asset.Id} has no DefinitionUrl", "");

                        continue;
                    }
                    var queue = _pregeneratedOutputsQueueFactory.Create(asset.BlockChainAssetId);
                    while (await queue.Count() < _baseSettings.MinPregeneratedAssetOutputsCount)
                    {
                        var coins = await _bitcoinOutputsService.GetUncoloredUnspentOutputs(hotWallet.ToString());

                        TransactionBuilder builder = new TransactionBuilder();

                        builder.AddCoins(coins);
                        for (var i = 0; i < _baseSettings.GenerateAssetOutputsBatchSize; i++)
                        {
                            builder.Send(new BitcoinPubKeyAddress(asset.AssetAddress, _connectionParams.Network), _dustSize);
                        }
                        builder.SetChange(hotWallet);

                        builder.SendFees(await _feeProvider.CalcFeeForTransaction(builder));
                        var signedHex = await _signatureApiProvider.SignTransaction(builder.BuildTransaction(true).ToHex());

                        var signedTr      = new Transaction(signedHex);
                        var transactionId = Guid.NewGuid();
                        await _bitcoinClient.BroadcastTransaction(signedTr, transactionId);

                        await queue.EnqueueOutputs(signedTr.Outputs.AsCoins()
                                                   .Where(o => o.ScriptPubKey.GetDestinationAddress(_connectionParams.Network).ToString() == asset.AssetAddress &&
                                                          o.TxOut.Value == _dustSize).ToArray());

                        await FinishOutputs(transactionId, signedTr, hotWallet);
                    }
                }
                catch (Exception e)
                {
                    await _logger.WriteWarningAsync("GenerateOutputsFunction", "GenerateAssetOutputs", $"Asset {asset.Id}", e);
                }
            }
            await _logger.WriteInfoAsync("GenerateOutputsFunction", "GenerateAssetOutputs", null, "End process");
        }