Giter VIP home page Giter VIP logo

nbitcoin's People

Contributors

andbene72 avatar augustoproiete avatar bitcoinbrisbane avatar dabura667 avatar dalijolijo avatar dangershony avatar denuoweb avatar dthorpe avatar dugongsoftware avatar eabz avatar gruve-p avatar joemphilips avatar knocte avatar kodxana avatar kukks avatar liquid369 avatar lontivero avatar nicolasdorier avatar nopara73 avatar onvej-sl avatar osagga avatar romanornr avatar sgryphon avatar soma42 avatar thepok avatar thesin- avatar torx-cz avatar veqtrus avatar xeniacx avatar yahiheb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nbitcoin's Issues

IColoredCoin.Amount comingles non-BTC with BTC quantities

IColoredCoin inherits Amount property from ICoin. In the general case, using an ICoin variable, ICoin.Amount maps to the BTC quantity in a transaction output. However, if you assign a colored coin implementation to that ICoin variable, ICoin.Amount then returns the quantity of the asset (books or ships or shares of stock), which is not BTC.

Case in point: TransactionBuilder.Verify contains this line:

spent += coin is IColoredCoin ? ((IColoredCoin)coin).Bearer.Amount : coin.Amount;

This test will have to be repeated in every situation where code wants to tally the BTC in a transaction, and only the BTC. This is code maintenance land mine.

I suggest inverting the IColoredCoin.Bearer relationship such that IColoredCoin.Amount is always the BTC value and some new property (AssetQuantity?) indicates the quantity of the colored asset. Something like this:

interface IColoredCoin: ICoin
{
    long AssetQuantity { get;}
}

script template instances

Why does TransactionBuilder construct its own instances of the script templates, instead of using the static .Instance properties of the template classes?

For example:

readonly static PayToScriptHashTemplate payToScriptHash = new PayToScriptHashTemplate();

Which could instead be

readonly static PayToScriptHashTemplate payToScriptHash = PayToScriptHashTemplate.Instance;

Or replace the local static fields in TransactionBuilder with the Instance properties.

RNGCryptoServiceProvider Dispose

Hi @NicolasDorier

Reading the RNGCryptoServiceProvider documentation on MSDN, it says:

This type implements the IDisposable interface. When you have finished using the type, you should dispose of it either directly or indirectly.

It is a common suggestion to use the Dispose() method to free memory with sensitive information immediately.

NBitcoin keeps only one long-life RNGCryptoServiceProvider instance. Do you think it worth changing that?

As a side question, can I add you to skype? I would like to have a less bureaucratic mean for this kind of questions/suggestions.

HD Master Key seed length?

Not so much as an issue but a question. Is there a min or max length the byte array needs to be in the ExtKey constructor?

If so, Ill add to the comments and perhaps a check / exception throw if not correct in a pull request.

public ExtKey(byte[] seed)

Segwit address calculation for different networks

Hello,

Thanks for adding support for SegWit.

As I have tested

For pubkey: 02ef43bcd42dd7dd37015e8bc76312e4c52c2d3920c16cab185499f12b02740458
1- GetSegwitAddress(Network.Main) returns p2xtf4PnGQFMtEgRREb3UcNLDHx3YwzdNjLW
2- GetSegwitAddress(Network.TestNet) returns p2xtf4PnGQFMtEgRREb3UcNLDHx3YwzdNjLW
3- GetSegwitAddress(Network.SegNet) returns QWywvQ6dAwCfEM8yRJew4Z98X7SgtCcUoxZN

As I understand from https://github.com/bitcoin/bips/blob/master/bip-0142.mediawiki the return values should be:
1- GetSegwitAddress(Network.Main): p2xtf4PnGQFMtEgRREb3UcNLDHx3YwzdNjLW
2- GetSegwitAddress(Network.TestNet): QWywvQ6dAwCfEM8yRJew4Z98X7SgtCcUoxZN

Mono.Nat modifications

Hi Nicolas, I can see you have modified Mono.Nat to use only Upnp (no PMP) and to be able to cancel the searching process. Questions:

  1. Why not PMP?
  2. Why do you search for available ports? I mean, if there is already an opened port and it is exactly the same NBitcoin needs (same Ext.Port, Int.Port and Int.IP), why does it fails? why not just use it?

Mono.Nat had no maintenance for several years however, nowaday, it has. There is a guy maintaining it in he's own fork with the same name (Mono.Nat) and I am also working in my own fork (Open.NAT) fixing defects, improving performance, improving tracing and also adding features like those that you did by yourself (renew mappings, release all mappings on disposal, etc).

The point is that even when it is water clear that Mono.Nat is not the most important piece of code in NBitcoin, I think it could have some benefits to take Mono.Nat away of the solution and use a Nuget package. Basically because there are people working hard on it, fixing defects, etc. For example, NBitcoin cannot open my NAT device because it only supports permanent leases time, there are a lot of people around the world with the same kind of inexpensive NATs and they won't be able to run a bitcoin node developed with NBitcoin.

So, please answer my questions and then I will be able to know if those particular changes can be included in Open.NAT.

thx and good job.

Portable library missing parts

I've decided to collect all missing parts and to-dos into one big issue so that it can be solved step-by-step.

  • NBitcoin namespace
    • Account
      • Needs removal of Spending, Unspent, etc. Portable exclusions
    • TODO
  • Payment namespace
    • BitcoinUriBuilder, UriHelper, HttpUtility, HttpEncoder ( #54 )
    • PaymentRequest, PaymentACK, Proto
      • Needs protobuf-net with Profile111 instead of Profile136
  • Protocol namespace
    • Payload, BitcoinSerializablePayload, UnknownPayload, TxPayload, PayloadAttribute ( #55 )
    • InventoryVector ( #55 )
    • NetworkAddress
      • Needs IPEndPoint (not available in WinRT?)
    • UPnPLease
      • Needs IPEndPoint, NodeServer
    • NodeServer, NodeListener, Node
      • Needs Socket
    • Peer, PeerTable, PeerTableRepository
      • Needs NetworkAddress, IPEndPoint
    • ProtocolTrace
      • System.Diagnostics.Trace is now less exposed than public
    • Payloads
      • AddrPayload
        • Needs Sockets
      • AlertPayload, BlockPayload, GetAddrPayload, GetBlocksPayload, GetDataPayload, GetHeadersPayload, HeadersPayload, InvPayload, MempoolPayload, PingPayload, PongPayload, VerAckPayload ( #55 )
      • VersionPayload
        • Needs Sockets
  • RPC namespace
  • Scanning namespace (TODO)

IColoredCoin lacks AssetId

There's no way to tell from an IColoredCoin interface what kind of colored coin you have.

Suggest:

interface IColoredCoin: ICoin
{
    AssetId AssetId {get;}
}

X509Certificate2 dependency removal

It was an good idea to remove dependency to X509Certificate2 because of multi-platform support, but after this certificate cannot be kept in Windows Certificate Store as not exportable.

In my opinion, for Windows there should be some extension which still will receive X509Certificate2 for signing.

TransactionBuilder doesn't select the targetCoin in the fastest path

@NicolasDorier

In the TransactionBuilder class, the Select method performs a reference comparison and then the targetCoin object is always null. You can see this behaviour running the CanSelectCoin test.

        public IEnumerable<ICoin> Select(IEnumerable<ICoin> coins, IMoney target)
        {
            var zero = target.Sub(target);
            var targetCoin = coins
                            .FirstOrDefault(c => c.Amount == target);   //<---- HERE
public void CanSelectCoin()
        {
            var selector = new DefaultCoinSelector(0);
            Assert.NotNull(selector.Select(new ICoin[] { CreateCoin("10.0") }, Money.Parse("10.0")));

Testnet Encrypted ExtKey

Hi, I am having trouble generating an ExtKey, encrypting it, then restoring it - specifically with Testnet. I can successfully get it to work with Main as shown here:

Network network = Network.Main;

ExtKey extKey = new ExtKey();
string extPubKey = extKey.Neuter().GetWif(network).ToWif();
// xpub661MyMwAqRbcFbAZaNJrgn2fBgjkFCWoBjUAnMisnMtt4qvtqNNESfAwusT31U4Eb43z8YdA36zrpf7vcsKvH5yi9vaYzMzftHZC7gb44n5
string extPrivateKey = extKey.GetWif(network).ToWif();
// xprv9s21ZrQH143K3766ULmrKe5vdeuFqjnwpWYZyyKGE2MuC3bkHq3ytrrU4biSM1nxfUDkXo4gopNSCkG4SnLf5TGd5m4mJ1FCqKHphSjUTa6
string encryptedPrivateKey = extKey.Key.GetEncryptedBitcoinSecret("abc123", network).ToWif();
// 6PYW7angZfaQ3SZdhDm8CsmzM9Gaue7LYxXwLCFXqgLEa96CeKTQMeNBfH

Key key = Key.Parse(encryptedPrivateKey, "abc123", network);
ExtKey extKey2 = new ExtKey(ExtPubKey.Parse(extPubKey), key);
string extPrivateKey2 = extKey2.GetWif(network).ToWif();
// xprv9s21ZrQH143K3766ULmrKe5vdeuFqjnwpWYZyyKGE2MuC3bkHq3ytrrU4biSM1nxfUDkXo4gopNSCkG4SnLf5TGd5m4mJ1FCqKHphSjUTa6

As you can see the private key's are the same. However when changing the network to Network.TestNet I get the following error:

System.FormatException: Invalid network
at NBitcoin.Network.CreateFromBase58Data(String base58, Network expectedNetwork) in Network.cs:line 372
at NBitcoin.Network.CreateFromBase58Data[T](String base58, Network expectedNetwork) in Network.cs:line 381
at NBitcoin.Key.Parse(String wif, String password, Network network) in Key.cs:line 24

I'm not sure if I am doing something wrong in the above code, please advise.

Cheers

Avoiding decimal type?

Any particular reason why the Money class completely avoids the CLR decimal numeric type? Decimal has plenty of precision and range (28 digits) to handle even satoshi scale numerics.

Just curious.

Deleting INodeBehavior

I am not an expert at all, but only a person very interested in NBitcoin.
Perhaps this is idiot, but don't you think that "INodeBehavior" Interface is redundant?
(It seems to me that we only need to delete it and make minor changes in the abstract class NodeBehavior and in NodeBehaviorsCollection)

Partial Signing and sigHash sketch

Here's a sketch of how a partial signature transaction scenario might flow between multiple actors.

Carla is buying from Alice. Bob is acting as a mediator between Alice and Carla.

Most mediated sale examples use a 2 of 3 multisig between Alice, Bob, and Carla. This one doesn't, since in some situations Carla's contribution cannot be pinned down until later, after Alice is no longer available to participate.

For this exercise we will assume we know the address to send to Carla, but we don't yet know an address or transaction to source Carla's payment into the transaction. Assume that none of the actors know any of the other actors' private keys.

This example uses a 2 of 2 multisig between Alice and Bob, so that Alice can sign off early and Bob can complete the sale later on Alice's behalf. Alice's signature uses sigHash_ALL | sighHash_AnyoneCanPay so that the outputs are locked, preventing Bob from taking Alice's funds. Carla's inputs can be added to the transaction later without invalidating Alice's signature.

        public class PartialSigningTest
        {
            private BitcoinSecret aliceKey;
            private BitcoinSecret bobKey;
            private BitcoinSecret carlaKey;
            private Script aliceBobRedeemScript;

            public PartialSigningTest()
            {
                aliceKey = new Key().GetBitcoinSecret(NBitcoin.Network.TestNet);
                bobKey = new Key().GetBitcoinSecret(NBitcoin.Network.TestNet);
                carlaKey = new Key().GetBitcoinSecret(NBitcoin.Network.TestNet);

                // Alice + Bob 2 of 2 multisig "wallet"
                aliceBobRedeemScript = PayToMultiSigTemplate.Instance.GenerateScriptPubKey(2, new PubKey[] { aliceKey.Key.PubKey, bobKey.Key.PubKey });
            }

            public NBitcoin.Transaction FundWallet()
            {
                // Fund wallet
                var tb = new TransactionBuilder();
                tb.AddCoins(GetCoinSources(aliceKey));
                tb.Send(aliceBobRedeemScript.ID, Money.Coins(0.01m));
                tb.SetChange(aliceKey.GetAddress());
                tb.SendFees(NBitcoin.Transaction.nMinTxFee);
                tb.AddKeys(aliceKey);

                var fundingTx = tb.BuildTransaction(true);

                if (!tb.Verify(fundingTx))
                {
                    throw new Exception("pay to Alice+Bob wallet Verify failed");
                }

                return fundingTx;
            }

            public NBitcoin.Transaction BobCreatesSaleTx(NBitcoin.Transaction fundingTx)
            {
                // spend from the Alice+Bob wallet to Carla, and Carla pays Alice
                // first Bob constructs the TX
                var tb = new TransactionBuilder();
                tb.AddCoins(new ScriptCoin(fundingTx, fundingTx.Outputs.To(aliceBobRedeemScript.ID).First(), aliceBobRedeemScript));
                tb.Send(carlaKey.GetAddress(), Money.Coins(0.01m));
                tb.Then();
                // we don't know yet what utxos Carla will spend from, so just fill in a dummy source
                tb.AddCoins(new Coin(new OutPoint(), new TxOut(Money.Coins(0.01m), new Script())));
                tb.Send(aliceKey.GetAddress(), Money.Coins(0.01m));

                // Bob does not sign anything yet
                var unsignedTx = tb.BuildTransaction(false);

                return unsignedTx;
            }

            public NBitcoin.Transaction AliceSignsTx(NBitcoin.Transaction fundingTx, NBitcoin.Transaction unsignedTx)
            {
                var tb = new TransactionBuilder();
                tb.AddKeys(aliceKey);

                // This signs all inputs where the given key(s) are applicable with the ALL + AnyoneCanPay sighash flags
                return tb.SignTransaction(unsignedTx, SigHash.All | SigHash.AnyoneCanPay);
            }

            public NBitcoin.Transaction CarlaFillsInAndSignsTx(NBitcoin.Transaction aliceSignedTx)
            {
                var carlaSourceTx = new NBitcoin.Transaction(); // fill in

                // Replace the dummy input with Carla's input
                // Note that we cannot issue change in this tx because the outputs are locked by 
                // Alice's All + AnyoneCanPay sig
                // so Carla will need to spend the exact amount into
                // an intermediate tx (which can send change back to Carla), 
                // and then use that intermediate tx as the source to spend into this tx.

                var tx = aliceSignedTx;
                var txIn = aliceSignedTx.Inputs.First(r => r.PrevOut.IsNull);
                txIn.PrevOut = new OutPoint(carlaSourceTx.GetHash(), 0);
                txIn.ScriptSig = carlaSourceTx.Outputs[0].ScriptPubKey;

                var tb = new TransactionBuilder();
                tb.AddKeys(carlaKey);
                return tb.SignTransaction(tx);  // Carla signs with sigHash_ALL
            }

            public void Run()
            {
                var fundingTx = FundWallet();

                var unsignedTx = BobCreatesSaleTx(fundingTx);

                var aliceSignedTx = AliceSignsTx(fundingTx, unsignedTx);

                // ...time passes...  Alice goes on vacation

                // Carla fills in her inputs and signs them
                var inputsCompleteTx = CarlaFillsInAndSignsTx(aliceSignedTx);

                // Bob reviews everything is ok and then signs the tx
                var tb = new TransactionBuilder();
                tb.AddKeys(bobKey);

                var signedTx = tb.SignTransaction(inputsCompleteTx);  // Bob signs with sigHash_ALL

                if (!tb.Verify(signedTx))
                {
                    throw new Exception("verification failure");
                }
            }
        }

a porting for namecoin/huntercoin?

hi!

I posted namecoin/huntercoin on the subject because huntercoin hinerit from namecoin, but my real interest is just huntercoin

This is not an issue, i just wanted to get in touch with you about this request

I'm a C# developer and i'd like to see a port like your, for namecoin/huntercoin
I'd like to collaborate if needed, but I lack proficiency with cryptography and its involved math.

I'm the developer of the "unofficial" huntercoin game client http://www.mithrilman.com/Huntercoin
All my work around huntercoin has been done from scratch, using XNA as the game engine and exchanging infos using huntercoind.exe RPC service (similar to BTC) and I'd like to get rid of that daemon so i could ship easily my client as an optimized node with a pruned sort of wallet

actually the huntercoin blockchain (started at February) takes already ~ 13GB, so from a gamer perspective, waiting to synchronize before playing could take literally days/week

I'd like your help to setup thing in order to implement huntercoin in your bitcoinlib so any inputs would be welcome

i could create my forked version of the lib and do pull-request, but i don't have a clue about where putting my hands on, so this is why i'm asking here

I can't be more specific about namecoin/huntercoin internals

huntercoin repository is this: https://github.com/chronokings/huntercoin
namecoin repository is this: https://github.com/namecoin/namecoin

My aim, at the end, is to have a C# full huntercoin node and i'm wondering if you could help with that, we could start a side project if you are interested, or other more interesting things!

RPCClient authorization fails against Bitcoin Core v0.11+

All NBitcoin RPCClient requests now fail with a server response of 401 - Not Authorized.

Bitcoin core recently changed its RPC authorization code slightly. FTP username/password in the URI is no longer supported, for one thing, but there may be other behavioral changes. I think this started with release v0.11 or so.

I tried adding

webRequest.PreAuthenticate = true;

to RPCClient.SendCommandAsync, but that didn't fix it.

Not buildable

A NuGet package is not committed to GitHub. See pull request #95. Lets get a build server?

Re-target to PCL

NBitcoin currently only targets regular .Net 4.5 - which is great for desktop apps and so, but completely useless for the new WinRT platform.

It would be great if the project would be re-targeted for Windows Universal apps PCL, even as a separate branch, it would make it easier to finally have a wallet app on WP/W8.1.

P2SH CheckScriptSig succeeds for P2PKH

PayToScriptHashTemplate.Instance.CheckScriptSig returns TRUE when given a public key hash scriptsig.

Similarly, PayToScriptHashTemplate.Instance.ExtractScriptSigParameters() returns a non-null sigparams result which has garbage data (nonsense RedeemScript)

This doesn't create a problem within NBitcoin because just about everywhere inside NBitcoin that operates on scriptsigs consistently tests for P2PKH before P2SH.

But if a (naively written) app just wants to do a "quick" test of whether a script is a P2SH scriptsig, the P2SH template functions don't work - that is, the P2SH functions don't fail or reject P2PKH scripts.

I can't be sure, but this feels like a change in behavior from builds of NBitcoin several months ago. I recently updated to the latest NBitcoin build after several months on a static branch, and now suddenly my P2SH checks are running amok.

I can work around this issue by testing for P2PKH before testing for P2SH, but this feels like a kludge. Can't the PayToScriptHashTemplate.Instance.CheckScriptSig and related functions be more authoritative about whether a script is / appears to be a well-formed script hash script?

Questions about tests

Hi @NicolasDorier

Unit tests run and pass perfectly well. However I found some friction in a very few. I would like to know if some of these suggestions make sense for you.

  • NBitcoin.Tests.Benchmark.BlockDownloadFromNetwork
    using(var node = Node.Connect(Network.Main, "192.168.0.7", new NodeConnectionParameters())
    You are running a bitcoin node in 192.168.0.7 but I think most devs don't.
    Could that be replace by?:
    var node_ip = Environment.ExpandEnvironmentVariables("bitcoin_node_ip"); node_ip = string.IsNullOrEmpty(node_id) ? "127.0.0.1" : node_ip;

I assume someone who download the NBitcoin source code could be running a node in 127.0.0.1. And even when that could be not true, it is more probable to have a node in localhost than in 192.168.0.7.
So, You could define the "bitcoin_node_ip" with 192.168.0.7 to reduce just a bit the friction for new devs.

  • NBitcoin.Tests.Benchmark.BlockDirectoryScanSpeed
    NBitcoin.Tests.Benchmark.BenchmarkBlockIndexing
    NBitcoin.Tests.Benchmark.BenchmarkCreateChainFromBlocks
    NBitcoin.Tests.Benchmark.BenchmarkTemplate

    BlockStore store = new BlockStore(@"**(Z|E)**:\Bitcoin\blocks", Network.Main);
    Could that be replaced by?:
    var blocksFolder = Environment.ExpandEnvironmentVariables("%appdata%\\Bitcoin\\blocks\\");
  • NBitcoin.Tests.MnemonicReference_tests.CanCreateBrainAddressFromNetwork
    Needs a node running in the default porr 8333. Other tests fail with:
    throw new InvalidOperationException("No bitcoin-qt or bitcoinq process running with rpc server on test net (\"bitcoin-qt.exe\" -testnet -server -rpcuser=NBitcoin -rpcpassword=NBitcoinPassword )");
    I think it was a good idea and this test could fail with the same kind message.
  • NBitcoin.Tests.MnemonicReference_tests.CanCreateBrainAddress
    Result Message: NBitcoin.InvalidBrainAddressException : This block does not exists
    (I didn't check why, yet)

Redundant overflow validation

@NicolasDorier, in Transaction class you can remove the overflow validation.

public Money Value
{
    get
    {
        ......
    }
    set
    {
        if(value == null)
            throw new ArgumentNullException("value");
        if(value.Satoshi > long.MaxValue || value.Satoshi < long.MinValue)
            throw new ArgumentOutOfRangeException("value", "satoshi's value should be between Int64.Max and Int64.Min");
        _MoneyValue = value;
        this.value = (long)_MoneyValue.Satoshi;
    }

Cannot extract public key of specific transactions

When trying to determine for instance the address of the first output of transaction 71bbaef28e09d8d6fadd41f053db7768dbb5fa4570f06b961dfc29db3dc00b1d, there is a null result. This is caused by a FormatException in NBitcoin.BouncyCastle.Math.EC.ECcure.cs line 423.

Appearently the BouncyCastle code considers a public key with a type value of 158 invalid, and it may be right (I have no knowledge on this).

However, blockchain.info does show a valid output of the transction, and so does the BitcoinTool c# library. So I wonder if the handling of this transaction in NBitcoin is correct.

(btw: thanks Nicolas for this great library!!)

Code to reproduce:

        var hexScript = "419e000000416e6f7468657220746578742077617320656d62656464656420696e746f2074686520626c6f636b20636861696e2e20546865207374616e6461726420ac";
        var bytes = NBitcoin.DataEncoders.Encoders.Hex.DecodeData(hexScript);
        var scriptPubKey = new Script(bytes);
        var template = scriptPubKey.FindTemplate();
        // template.Type is now TX_PUBKEY

        var pubKey = ((PayToPubkeyTemplate)template).ExtractScriptPubKeyParameters(scriptPubKey);
        // pubKey is now null

Bouncycastle 1.8.1

Hi Nicolas,

I have verified the differences between BC 1.8 and 1.8.1 and I think it's worth to replace with new source code.
The main reason is a better support of portability

  • PORTABLE conditional compilation symbol was added
  • things like StartsWith are centralized in Platform class
    Also there is some performance optimization.

Currently I have already a version that fully compile, I have winmerged it and now I'm testing it.
Before committing it, I would like to know where is the change you have implemented to emulate OpenSSL bugs. I have tried to look for it in previous commit but I don't find a specific commit and the early one of 6 nov are pretty big to find something without knowing which file contains this "bug". https://github.com/MetacoSA/NBitcoin/commits/master/NBitcoin.BouncyCastle

Also have you considered to change the bouncycastle project in a shared project ? In this way we have only one project (valid for portable and not) and one dll as result.

Andrea

Signature verification fails with P2SH GetScriptAddress() and script.ID

The following code constructs a 2 of 2 multisig transaction ("wallet") and spends 0.01 BTC into it from a normal public key hash address source. It then constructs a transaction to spend the output of the first transaction, spending from the P2SH output.

This code works if BTC is spent to the p2sh.ScriptPubKey.GetDestinationAddress(..), but fails to verify if the BTC is spent to p2sh.ScriptPubKey.ID or p2sh.ScriptPubKey.GetScriptAddress(..).

Is this expected? In skype chat you mentioned that ID or GetScriptAddress should work, but I can't figure out how. The hashes in the scripts generated from ID or GetScriptAddress() are different from the hash in the script generated from GetDestinationAddress(). Only the hash in the script generated from GetDestinationAddress() matches the hash of the redeemScript.

        public void P2SHTest()
        {
            // Address: mfvwjiVWEVTfcQ11o2h8hm8Z6F7zD8ewpU
            var aliceKey = new BitcoinSecret("cS5gTUznmvyhhMbwLZhnyFWdgUusHQpEHeUzBqTFD6wBQamw9Wyr", NBitcoin.Network.TestNet);

            // Address: mjqRznR16DY3cjpt2wDRCinEifEMoxwWZz
            var bobKey = new BitcoinSecret("cQNb2dSpVaxHJ3hNUeQKRTA4d5pFE9KFNRC3YTUzaRCYBNtTkp4N", NBitcoin.Network.TestNet);

            // Address: moH7jAsD2BWhviBN4dy4LByKqE7bZzUwaa
            var carlaKey = new BitcoinSecret("cPNT8vQwj57SA9NXn7MqUkfh1JhDhABzWZnxKFiUAHX3yoGZEcc9", NBitcoin.Network.TestNet);

            // Alice + Bob 2 of 2 multisig "wallet"
            var redeemScript = PayToMultiSigTemplate.Instance.GenerateScriptPubKey(2, 
                             new PubKey[] { aliceKey.Key.PubKey, bobKey.Key.PubKey });
            var scriptPubKey = PayToScriptHashTemplate.Instance.GenerateScriptPubKey(redeemScript);
            var address = scriptPubKey.GetDestinationAddress(NBitcoin.Network.TestNet);


            // Fund wallet
            var tb = new TransactionBuilder();
            tb.AddCoins(GetCoinSources(btcSourceKey));
//!! 1          tb.Send(scriptPubKey.ID, Money.Coins(0.01m));
//!! 2          tb.Send(scriptPubKey.GetScriptAddress(NBitcoin.Network.TestNet), Money.Coins(0.01m));
            tb.Send(scriptPubKey.GetDestinationAddress(NBitcoin.Network.TestNet), Money.Coins(0.01m));
            tb.SetChange(btcSourceKey.GetAddress());
            tb.SendFees(NBitcoin.Transaction.nMinTxFee);
            tb.AddKeys(btcSourceKey);

            var fundingTx = tb.BuildTransaction(true);

            if (!Script.VerifyScript(fundingTx.Inputs[0].ScriptSig, fundingTx.Outputs[0].ScriptPubKey, fundingTx, 0))
            {
                throw new Exception("pay to multisig wallet VerifyScript failed");
            }


            // spend from the Alice+Bob wallet to Carla
            tb = new TransactionBuilder();
//!! 1          var outputIndex = (int)fundingTx.Outputs.FindIndex(r => r.IsTo(scriptPubKey.ID));
//!! 2          var outputIndex = (int)fundingTx.Outputs.FindIndex(r => r.IsTo(scriptPubKey.GetScriptAddress(NBitcoin.Network.TestNet)));
            var outputIndex = (int)fundingTx.Outputs.FindIndex(r => r.IsTo(scriptPubKey.GetDestinationAddress(NBitcoin.Network.TestNet)));
            tb.AddCoins(new ScriptCoin(new OutPoint(fundingTx, outputIndex), fundingTx.Outputs[outputIndex], redeemScript));
            tb.Send(carlaKey.GetAddress(), Money.Coins(0.01m));
            tb.AddKeys(aliceKey, bobKey);

            var tx = tb.BuildTransaction(true);

            Console.WriteLine(tx.ToString(RawFormat.BlockExplorer, NBitcoin.Network.TestNet));

            if (!Script.VerifyScript(tx.Inputs[0].ScriptSig, fundingTx.Outputs[outputIndex].ScriptPubKey, tx, 0))
            {
                throw new Exception("spend from multisig wallet VerifyScript failed");
            }
        }

Incorrect (or obsolete) project name in NBitcoin.sln

Visual studio complains about being unable to find 'Build.csproj' when building.

Form NBitcoin.sln

Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Build", "Build\Build.csproj", "{FCD2502B-440B-4C39-8DD5-1052DEBBB0E3}"
EndProject

There is a Build\Deploy.csproj. I was unsure if solution should be pointed to Build\Deploy.csproj or just delete the project and reference in the solution. I did the later and it built fine.

Transaction.ToString() has side effects

Just a general warning / heads up that Transaction.ToString() has side effects - it can change the internal state of the object.

Specifically, ToString() winds up computing a hash of the transaction, which involves streaming the transaction object to bytes, and the ReadWrite pattern of streaming fills in null properties with default instances even when writing the object out.

Example:

            var tx = new NBitcoin.Transaction();
            var txIn = new TxIn(new OutPoint(new uint256(source.TransactionHash), source.OutputIndex));
            tx.AddInput(txIn);
            txIn.ScriptSig = null;

            var hex = Encoders.Hex.EncodeData(tx.ToBytes());

// txIn.ScriptSig != null now

Where this has the greatest impact is while debugging the code, because the debugger uses ToString() to get a text representation of every variable in the local scope. Stepping through code in the debugger can change the internal state of the transaction object if the Locals tab is visible.

Fully Validating Node

Not an issue per se; rather, a question. NBitcoin is advertised as a Bitcoin library for the .NET platform. Any plans on turning it into a fully validating client, ala Bitcoin Core P2P layer?

Weird target address in transaction

Hi Nicolas ...

First of all: I really really love your work on the NBitcoin library!! (A donation will follow soon ;) )

While processing transactions from the blockchain I stumbled upon somethin weird.

Transaction with id '8ebe1df6ebf008f7ec42ccd022478c9afaec3ca0444322243b745aa2e317c272' has an invalid target addres, when decoded with NBitcoin: '76a9146300bf4c5c2a724c280b893807afb976ec78a92b88ac61' ...
I validated this first against blockr.io (https://btc.blockr.io/tx/info/db3f14e43fecc80eb3e0827cecce85b3499654694d12272bf91b1b2b8c33b5cb), where this address was defined as 'NONSTANDARD', so at first I thought these btc simply were destroyed.

But ...

On a later transaction with id 'db3f14e43fecc80eb3e0827cecce85b3499654694d12272bf91b1b2b8c33b5cb' this output was referenced as a (valid!) input for a transaction. Again I looked it up in blockr.io (https://btc.blockr.io/tx/info/8ebe1df6ebf008f7ec42ccd022478c9afaec3ca0444322243b745aa2e317c272) and again it showed up as 'NONSTANDARD'

The weird this is that I decided to also validate this against an other blockchain explorer and there it was mentioned correctly (address: 1A2UnusrwYr7DbiFbFesRKrbQMiYkj6E84):
http://blockexplorer.com/tx/db3f14e43fecc80eb3e0827cecce85b3499654694d12272bf91b1b2b8c33b5cb
http://blockexplorer.com/tx/8ebe1df6ebf008f7ec42ccd022478c9afaec3ca0444322243b745aa2e317c272

I'm confused now. What's going on here?

BIP-0021 Payment URI builder

As far as I'm aware there's currently no builder that allows us to generate BIP-0021 payment URIs (please point it out if I'm wrong, I haven't found it though). Is there any interest for this? I'd like to fork the project and submit a PaymentUriBuilder as a pull request.

Transaction rejected?

I'm having trouble submitting transactions created with NBitcoin. I think I'm missing a step, but I don't know what.

Here's the gist of it:

var tx = new NBitcoin.Transaction();
var txIn = new TxIn(new OutPoint(new uint256(source.TransactionHash), source.OutputIndex));
tx.AddInput(txIn);

var destAddress = "mnDQg9yvKQv3u88favjCfGtDhfD5tpq9wa";
var payment = new Money(2000000);
var change = new Money((ulong)source.Amount) - payment - new Money(1000);
tx.AddOutput(payment, new BitcoinAddress(destAddress));
tx.AddOutput(change, new BitcoinAddress(sourceAddress));
tx.SignAll(key);

var txRawHex = Encoders.Hex.EncodeData(tx.ToBytes());

Submitting that txRawHex to the Testnet network results in a rejection error "invalid transaction". I've tried rpcClient.SendRawTransaction(tx) to my local bitcoind as well as multiple API services such as tbtc.Blockr.io and testnet3.toshi.io.

Is there an additional step that needs to be done to the transaction after tx.SignAll() before broadcasting it to the network?

Forensic details:
source transaction: http://tbtc.blockr.io/tx/info/cf9c8e5f1c16797804412cadf0be1a15ab873f19fdb20b7a02f170c32e9c0704
source address: http://tbtc.blockr.io/address/info/mobq38AbD1mwPxqKKXpgbNEfV7ezdsx6QR
Key is the private key from which the source address was generated.
new transaction raw hex value:

010000000104079c2ec370f1027a0bb2fd193f87ab151abef0ad2c41047879161c5f8e9ccf010000006a473044022023baf359cf181a82d42c6355ff6b31513d7f16f14ab4c4e578226b3c46f3bc61022017d864ba551ed01aa39dccd1458495ed8c5ca279e1a2085bf65e031f33a2300901210346c834e355953c78c41eb6fc9a7d1a36c3ddb59ab3035c74d6376631b53595cbffffffff0280841e00000000001976a91449776a3be69fa71e2d12d14d0d7d696c28fd395e88ac18ef6f06000000001976a91458ad072475467f2bd9480d5591222214206c204588ac00000000

Thanks,
-Danny

Remove BouncyCastle

@NicolasDorier, I've been working hard for days now trying to remove BC but I hit the wall because I didn't follow a refactoring plan and it was a lot harder than what I thought. However, I think it could worth the effort (I really don't like to have two projects: BC and BC portable in NBitcoin).

There is a very little library that we could use: Secp256k1 It has all what NBitcoin needs.

Do you think it is a good idea and worth? If so, do you have any idea about how could we start the refactoring?

Using foreach with Collections

Would it make sense to use foreach with collections instead of the old-school for loops i.e.:
foreach(var i in tx.Inputs) instead of for(int i = 0 ; i < tx.Inputs.Count ; i++)?

Question regarding signature verification

Hi,

I'm trying to implement Trezor Connect on my blog. For that, I need to verify a signature of a message to check that it was generated by a given Trezor device (thus, private key).

I have tried to use the parameters provided for testing from here: https://github.com/trezor/connect/blob/gh-pages/examples/server.py

And my (stripped down) code as follows:

string visual_challenge = "2015-03-23 17:39:22";
string random_challenge = "cd8552569d6e4509266ef137584d1e62c7579b5b8ed69bbafa4b864c6521e7c2";
string signature = "20f2d1a42d08c3a362be49275c3ffeeaa415fc040971985548b9f910812237bb41770bf2c8d488428799fbb7e52c11f1a3404011375e4080e077e0e42ab7a5ba02";

SHA256 sha = SHA256Managed.Create();
var hiddenChallenge_Sha = BitConverter.ToString((sha.ComputeHash(TrezorUtils.HexStringToByteArray(random_challenge)))).Replace("-", "").ToLower();
var visualChallenge_Sha = BitConverter.ToString((sha.ComputeHash(new ASCIIEncoding().GetBytes(visual_challenge)))).Replace("-", "").ToLower();

string message = hiddenChallenge_Sha + visualChallenge_Sha;
var m2 = TrezorUtils.HexStringToByteArray(message);
PubKey pubKey = new PubKey("023a472219ad3327b07c18273717bb3a40b39b743756bf287fbd5fa9d263237f45"); //new PubKey(ConfigurationManager.AppSettings["TrezorPublicKey"]);
bool verified = pubKey.VerifyMessage(new ASCIIEncoding().GetString(m2), TrezorUtils.ConvertHexStringToBase64(signature));

The call to pubKey.VerifyMessage always returns false with this code. I have verified that the SHA256's returned are identical to what the Python code generates for the same values, as well as the base64 of the signature. So all the input to the VerifyMethod is the same as in the Python example. However, verification of the signature still fails.

Any ideas?

An item with the same key has already been added

I am getting the following crash in Linux and OSX

Ademars-MacBook-Pro:Debug ademar$ mono testing.exe

Unhandled Exception:
System.TypeInitializationException: The type initializer for 'NBitcoin.Network' threw an exception. ---> System.TypeInitializationException: The type initializer for 'NBitcoin.Op' threw an exception. ---> System.ArgumentException: An item with the same key has already been added.
  at System.ThrowHelper.ThrowArgumentException (ExceptionResource resource) <0x1950820 + 0x00036> in <filename unknown>:0 
  at System.Collections.Generic.Dictionary`2[TKey,TValue].Insert (System.Collections.Generic.TKey key, System.Collections.Generic.TValue value, Boolean add) <0x7d6898 + 0x000f3> in <filename unknown>:0 
  at System.Collections.Generic.Dictionary`2[TKey,TValue].Add (System.Collections.Generic.TKey key, System.Collections.Generic.TValue value) <0x7d6860 + 0x00027> in <filename unknown>:0 
  at NBitcoin.Op..cctor () <0x70c3b0 + 0x002bb> in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at NBitcoin.Network.CreateGenesisBlock (UInt32 nTime, UInt32 nNonce, UInt32 nBits, Int32 nVersion, NBitcoin.Money genesisReward) <0x70bff0 + 0x0004f> in <filename unknown>:0 
  at NBitcoin.Network.InitMain () <0x707018 + 0x0032f> in <filename unknown>:0 
  at NBitcoin.Network..cctor () <0x6ff050 + 0x051bb> in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at testing.MainClass.Main (System.String[] args) <0x6feec8 + 0x0000b> in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeInitializationException: The type initializer for 'NBitcoin.Network' threw an exception. ---> System.TypeInitializationException: The type initializer for 'NBitcoin.Op' threw an exception. ---> System.ArgumentException: An item with the same key has already been added.
  at System.ThrowHelper.ThrowArgumentException (ExceptionResource resource) <0x1950820 + 0x00036> in <filename unknown>:0 
  at System.Collections.Generic.Dictionary`2[TKey,TValue].Insert (System.Collections.Generic.TKey key, System.Collections.Generic.TValue value, Boolean add) <0x7d6898 + 0x000f3> in <filename unknown>:0 
  at System.Collections.Generic.Dictionary`2[TKey,TValue].Add (System.Collections.Generic.TKey key, System.Collections.Generic.TValue value) <0x7d6860 + 0x00027> in <filename unknown>:0 
  at NBitcoin.Op..cctor () <0x70c3b0 + 0x002bb> in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at NBitcoin.Network.CreateGenesisBlock (UInt32 nTime, UInt32 nNonce, UInt32 nBits, Int32 nVersion, NBitcoin.Money genesisReward) <0x70bff0 + 0x0004f> in <filename unknown>:0 
  at NBitcoin.Network.InitMain () <0x707018 + 0x0032f> in <filename unknown>:0 
  at NBitcoin.Network..cctor () <0x6ff050 + 0x051bb> in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at testing.MainClass.Main (System.String[] args) <0x6feec8 + 0x0000b> in <filename unknown>:0 

Using reference comparison for value type - problem

@NicolasDorier, LockTime is a value type and that means it can never be null. For that same reason (LockTime is not a reference type) the reference comparison is always false

Please check the following code:

        public override bool Equals(object obj)
        {
            LockTime item = obj is LockTime ? (LockTime)obj : default(LockTime);
            if(item == null)       //  <----------- HERE (always false)
                return false;
            return _value.Equals(item._value);
        }
        public static bool operator ==(LockTime a, LockTime b)
        {
            if(System.Object.ReferenceEquals(a, b))  // <------- HERE (this is always false)
                return true;
            if(((object)a == null) || ((object)b == null)) //  <----------- HERE (always false)
                return false;     
            return a._value == b._value;
        }

Recursive BuildTransaction for change

Why does TransactionBuilder.BuildTransaction call itself recursively after the change amount has been determined? The recursive call repeats the coin selection process, but (should) always arrive at the same result (same coin selection) as the first call.

Support for Mnemonic keys?

I was looking through but could not find so I might have missed it. But is there support for mnemonic keys like what is done in bitcore.io. You enter 12 words, hex generated and used for the seed? I know there is a seed option for the extKey. But is there built-in support for the mnemonic phrases?

Thanks

Why do we have a DeterministicECDSA class?

NBitcoin includes BouncyCastle as part of its code base and BC already allows us to get a deterministic K value as part of the ECDsaSigner.

Basically, the ECDsaSigner class has ctor that accept an IDsaKCalculator as parameter which has two implementations, one of those implementations is the HMacDsaKCalculator class that prodives deterministic K values using HMac.

It seems we don't need the DeterministicECDSA class because the funtionality is already provided by BC.

@NicolasDorier: Is this correct? or, is there some reason to have our own implementation?

BIP39 not supported on portable lib

BIP39 relies on the KD form of UTF8 strings.
String.Normalize does not exist in portable library.

The easiest way seems to generate a substitution table and ship it into the portable lib.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.