Google-apper
Hovedmeny

Post a Comment On: Ken Shirriff's blog

"Bitcoins the hard way: Using the raw Bitcoin protocol"

88 Comments -

1 – 88 of 88
Blogger Unknown said...

Good article. I did this exercise myself for largely the same purpose. In addition, I also wanted to see how multisig transactions would work for an escrow service and at the time no wallets had implemented them. It took a long time and lots of debugging to make the rather simple transactions work :)

February 1, 2014 at 10:15 AM

Comment deleted

This comment has been removed by a blog administrator.

February 1, 2014 at 12:25 PM

Anonymous michagogo said...

In note 1, I'd suggest you replace Armory with Electrum -- Armory actually does participate, as it runs an instance of bitcoind in the background.

February 1, 2014 at 12:43 PM

Anonymous Anonymous said...

Please also publish your article to http://www.codeproject.com/

Thank you!
Regards,
TomazZ

February 1, 2014 at 1:04 PM

Anonymous Anonymous said...

Thank you for doing this!!!

Great job!

February 1, 2014 at 2:03 PM

Anonymous Anonymous said...

Fantastic article. I look forward to the future mining article.

February 1, 2014 at 3:18 PM

Anonymous Anonymous said...

RIPEMD-160 is used instead of SHA-256 for address hashing because it generates a shorter ascii address string (after base58 conversion)

February 1, 2014 at 4:27 PM

Blogger Jordan Baucke said...

Read your article with great enthusiasm. Excellent explanations of some of the very nuanced parts of the network that only the core developers seem to understand.

February 1, 2014 at 6:17 PM

Anonymous Anonymous said...

great article keep em coming!
btc gladly donated (c85e4153b2a8b254015d41c1f94cd6f7b3d31b3d5057b01ccfc995dadc789aaa-000)

February 1, 2014 at 6:25 PM

Anonymous sombody said...

FYI that random number generator you are using for making the private keys in the very first gist is not secure enough for crypto. Electrum uses python ecdsa which uses os.urandom.

February 1, 2014 at 9:34 PM

Anonymous Julien said...

Great article. Do you also have a Dogecoin address? I'd like to donate, but currently don't have an accessible Bitcoin wallet with enough balance.

February 2, 2014 at 5:42 AM

Blogger Unknown said...

The mining process is very interesting, but I'll leave that for a future article


what time ? I waiting for this .

February 2, 2014 at 6:53 AM

Anonymous Anonymous said...

Very nice.

Small comment: you only mention the old uncompressed format for public keys. There is a much shorter one, namely 0x02 or 0x03 followed by only the X coordinate, 0x03 in case of odd y and 0x02 in case of even. This encoding is preferred because it takes less space in the blockchain and network.

February 2, 2014 at 8:15 AM

Blogger Ken Shirriff said...

Thanks everyone for the comments. Julien: my Dogecoin address is DAJVsKTtM2QsstemCZVzn5oZAiSywDgDiS

February 2, 2014 at 10:02 PM

Anonymous Anonymous said...

Sent!

February 3, 2014 at 10:19 AM

Blogger Ken Shirriff said...

Wow. Much dogecoin donation. Very generous. So thanks.

And thank you everyone for the Bitcoin donations too. It's all going for wells in Africa.

February 3, 2014 at 8:09 PM

Blogger Unknown said...

Ken, how many transactions are in a typical block? I'm wondering about the relative value of the new bitcoins created via mining a block vs. the fees associated with the transactions in the block.

February 4, 2014 at 5:21 AM

Anonymous Anonymous said...

Ken,

Such a great article, and I love that you included the code. Still, I'm having trouble getting through the python. I imported ecdsa just fine, but I still can't 'compile' my way through lines like

return utils.base58CheckEncode(0x80, key_hex.decode('hex'))

you seem to reference a library and set of modules i can't find. Even keyUtils etc bring up errors both in python 2.7 and 3.3


February 9, 2014 at 4:53 AM

Blogger Ken Shirriff said...

Hi John! There are lots of stats at https://blockchain.info/stats

Doing some math on the past 24 hours: 158 blocks, 68748 transactions, 13.65463 bitcoins total fees, 3950 bitcoins mining reward, 435 transactions per block, 12 cents per transaction fee, $34 per transaction for mining.

Conclusion: the fee per transaction is small but not trivial, and the mining cost per block is insanely large.

Comment for Anonymous trying to use the code: the full code is at https://github.com/shirriff/bitcoin-code

Disclaimer: my code is just for experimentation; use a real library if you're doing anything important.

February 11, 2014 at 10:35 PM

Anonymous Anonymous said...

Great article, it was a very clear explanation for a newbie like me.
Donation sent to the cause, also very nice initiative :)

February 16, 2014 at 2:31 AM

Blogger JamesWinn said...

Good Job on the article. I went through the same process of building a tx from scratch, but you've gone the extra mile and documented it nicely.

February 24, 2014 at 11:45 PM

Anonymous Anonymous said...

what stops a person like you from making a bitcoin?can someone create what looks to be a bitcoin and fool the network?

February 26, 2014 at 9:33 AM

Anonymous Anonymous said...

Fantastic article! Great technical info in one place...thanks!

February 27, 2014 at 5:48 PM

Anonymous alkubayr said...

Excellent article! I am a bitcoin enthusiast who go interested in this field exactly three days ago! It was the MtGox collapse that triggered my interest. And right now, bitcoin protocol research is taking all my time.

Anyway, I have couple of questions which I hope you would be able to answer.

1. What bitcoin protocol message goes out on the wire when a miner successfully solves a block and releases it into the wild?

2. Given a bitcoin address, which I DO NOT own, is it possible to compute the balance of bitcoins held in it? (Assuming I have the entire block chain on my laptop.)

3. I know CPU mining is not economical any more. But can I still try it as a long shot lottery? I mean, if I am running a CPU miner on a ordinary laptop, can it get lucky and solve a block before those special purpose hardware units. Or is CPU mining simply impossible because of some theoretical limits?

March 3, 2014 at 8:16 PM

Anonymous Anonymous said...

What happend to your github repo?

shirriff/bitcoin-code

March 4, 2014 at 6:55 PM

Blogger Doof said...

Where do the values PUSHDATA 47, 14 come from?

Cant see them here https://en.bitcoin.it/wiki/Script

March 12, 2014 at 11:34 PM

Blogger Doof said...

@alkubayr you could hit a block on the first attempt, just very very unlikely.

if you want cheap mining, buy a block erruptor 2ghs off ebay for ~$50. About 1000x the speed of a laptop cpu, and very little power consumption.

March 12, 2014 at 11:36 PM

Blogger Doof said...

"what stops a person like you from making a bitcoin?can someone create what looks to be a bitcoin and fool the network?"

Each bitcoin is just a summation of previous inputs and outputs.

Each of those inputs references a previous input, and so on. So unless you generate a fork from the first transaction, then you cannot fool the network.

March 12, 2014 at 11:38 PM

Anonymous Anonymous said...

YOU! are my hero! at last! someone prepared to unravel the obfuscation of the current "priesthood of coders"; one hankers for somethink akin to some bitcoin equivalent to "tcpip illustrated"! please write the ... book!

March 21, 2014 at 3:52 PM

Blogger Philip Jones said...

Good thoughts. But lately bitcoin seems more speculative than ever, which results in too much fluctuation in value. The Mt. Gox heist also adds panic to most believers that anytime, transaction malleability attack might arise. Mining isn't that profitable at all that's why bitcoiners are turning into bitcoin gambling where they can multiply their coins easily.

April 7, 2014 at 2:20 AM

Anonymous Brendan E. Mahon said...

Thanks for the thorough overview. Much appreciated. I'm considering a few bitcoin projects and this kind of documentation is a huge help. It'd also be appreciated if you could repost your python code to github (although the disclaimer that it's almost certainly not secure for significant use is understood). I'd love to play around with it on the testnet. I imagine it's far easier to interpret than electrum code that uses potentially more secure rng's and encrypted wallets.

April 10, 2014 at 1:30 PM

Blogger Unknown said...

Thank you so much for this great and detailed breakdown of structure of a transaction, and how to script it.

May 1, 2014 at 5:28 AM

Anonymous Anonymous said...

I really hope you decide to repost your code to GitHub. I think I could make the snippets from the article work, but tracking down all the appropriate libraries would just be a pain.

May 15, 2014 at 7:18 PM

Blogger Neeraj of Borg said...

Hi Ken.

Awesome article! I printed the whole thing out.

Please let me know where I can get "utils". You make a bunch of references to it, namely for netaddr and varstr, but I cannot find these anywhere in my system, so I suspect these are in some library "utils" you have?

Thanks!

May 27, 2014 at 7:46 PM

Anonymous MP said...

Any reason why you took the code down?

I'd love to play with it if you made it available again.

Thanks!

June 6, 2014 at 8:24 AM

Blogger Konstantin Zertsekel said...

The Shirrif's python code may be found here:

https://github.com/gferrin/bitcoin-code

--- KostaZ

August 9, 2014 at 10:26 PM

Anonymous Bryce Neal said...

In the post you mention hash type as one of the steps that tripped you up. You go on to mention that SIGHASH_ALL (0x00000001) as being temporarily appended to the raw transaction, however, in code example below for makeSignedTransaction, it looks like you refer to this hash code as 0x01000000.

Is this a mistake, or is the hash code different from the hash type?

Thanks for the insightful post.

October 1, 2014 at 10:44 PM

Anonymous Bryce Neal said...

Ignore my previous post. I just realized it is because this hash code is represented in little endian form.

October 1, 2014 at 10:46 PM

Anonymous Anonymous said...

This is amazing, but what are "L12sL4s" and "<LQQ26s26sQsL"?

October 2, 2014 at 10:25 AM

Blogger Ken Shirriff said...

Bryce: yes, you figured it out. Bitcoin mixes big-endian and little-endian values, which makes things confusing.

Anonymous: "L12sL4s" indicates how the Python code should pack the data into bytes. L indicates unsigned long, 12s indicates string of 12 characters, etc.
See struct documentation.

October 2, 2014 at 10:59 AM

Anonymous S. Bishop said...

Hi Ken,
I'm learning Python (mainly because of how versatile it is as this blog shows!) to facilitate exactly what your post here is doing: learning to send a Bitcoin (testnet) Tx without the client

Would you kindly advise a couple things:
1. Python version 2.x (2.7.8 x64 Win7 in my case) is what's used for your code I'm assuming? Not 3.x?
2. I've really put in the time to trying to implement the code but am getting stuck. It will run and say "8 tests passed" but I'm hoping ym small donation can clarify how to implement the github code you've provided

Thanks you so much for such an informative blog post, Ken!

October 7, 2014 at 9:44 PM

Anonymous Andrey said...

Function in MininmalSendTxn link to msgUtils.getTxMsg, but msgUtils haven't function getTxMsg...
It makes me stupid...

October 15, 2014 at 11:00 AM

Anonymous DaDo said...

Great explained! You have the gift! ;))

Have more questions. Anybody knows how my wallet client will sum up my wallet amount?

Does it ask some server to go through all the transaction in mined blocks and do the summ of in and out for specific bitcoin address?

Thanks guys

October 23, 2014 at 3:51 AM

Anonymous Anonymous said...

Excellent article!
Thank you so much

November 15, 2014 at 12:29 PM

Comment deleted

This comment has been removed by the author.

November 23, 2014 at 11:36 AM

Anonymous Anonymous said...

Excellent blog! I've found more info here than many wikis and articles that I'd read

April 9, 2015 at 9:43 AM

Anonymous Anonymous said...

Thank you for a great explanation. But there is I always one question for which I can never ferret out the answer. At the most primitive level I'm pretty sure Bitcoin is a 4-step operation. A. Users create Transactions and broadcast them into the network. B. Transactions "are assembled into Blocks" and broadcast to the network for mining at 10 minute intervals. C. Miners find Blocks and compete to validate them. D. The length of time required to validate a Block's worth of Transactions – and therefore for a Transaction to be validated -- is controlled by the number of leading 0s required for validation. A and C seem straightforward. But I can never figure out Exactly who or what has the authority to create and broadcast a Block for mining. And like for D, I can't see anyway control over either function can be distributed/shared among network node peers. What am I missing?

May 13, 2015 at 3:24 PM

Blogger Ken Shirriff said...

Anonymous: good question. The blocks aren't assembled on the network (there is no step B), but by the miners, who can choose whatever transactions they want. So miners are typically to mine slightly different blocks. As for D, every client uses the same algorithm to determine the difficulty by looking at the blockchain history. So the difficulty doesn't need to be broadcast by a central authority. Details here.

May 13, 2015 at 7:06 PM

Anonymous Anonymous said...

Hello. I am new to learning with Bitcoin. But I was reading your generating the private key section. I not you said the private key is 256-bit. however, in the python code, you are generating a string with length 64. Isn't that 512-bit?

August 17, 2015 at 8:59 AM

Anonymous Anonymous said...

Awesome article. I am following along for my Python uni project but I am a little bit confused. When I capture packets from an official BTC Wallet I can see the Version command to have a total of 192 bytes yet your code produces 187 bytes and Wireshark see's Version as "Unknown Command". I suspect some endianness issue on Mac OS X 10.10. Any ideas?

August 20, 2015 at 6:51 PM

Blogger Unknown said...

Thank you Ken Shirriff for your article, it is very interesting !


To better understand bitcoin protocol, I have started to write a Scapy extension to sniff and craft Bitcoin packets.
All types of messages are implemented but I did not test all of them.
https://github.com/jbcayrou/scapy-bitcoin

December 30, 2015 at 4:55 AM

Anonymous Anonymous said...

An excellent and informative article. Just a few nitpicks:


Another annoying thing about the Bitcoin protocol is that the signature and public key are both 512-bit elliptic curve values

Not so. The public key is indeed a point on the elliptic curve, but the signature is an ordered pair of integers, usually denoted (r,s). It is not a point on the curve.


Inconveniently, the Bitcoin protocol adds a prefix of 04 to the public key.

This is the standard way to represent a public key defined in section 4.3.6 of X9.63 and many other places. There is also a shorter "compressed representation" beginning 02 or 03. This latter method is unfortunately patented, but seems to be widely used, including elsewhere in the Bitcoin specs (I'm sure Satoshi Nakamoto has paid to license it :-)


The Elliptic Curve DSA algorithm generates a 512-bit public key from the private key.

Strictly not so. The Elliptic Curve DSA algorithm (ECDSA) is just a means to generate a signature. The public key is derived using standard elliptic curve arithmetic. And the public key is still considered to be a 256 bit key like the private key, it just has two parts.

February 11, 2016 at 11:28 PM

Blogger Unknown said...

Hi,
This is a very useful and valuable article. I would like to know how to run this python code. I am new to python. Please help me. Thanks.

May 2, 2016 at 8:18 PM

Anonymous Anonymous said...

Prof.
I am a newbie with bitcoins (1st year computer science student). Just read a book, want to understand it better.
Can you please explain again the function def derSigToHexSig(s) please?
Rgds

June 6, 2016 at 10:32 AM

Anonymous Anonymous said...

great article. Thank you. I am following your article.

I have some question. In scriptSig, what is The first X, Y and latter X, Y?

July 5, 2016 at 2:26 AM

Blogger Ken Shirriff said...

Anonymous: the X and Y values in scriptSig are the elliptic curve signatures. The first (X,Y) pair is the signature for the transaction and the second (X,Y) pair is the public key for the Bitcoin address. Note that the public key is the full 512 byte public key generated from the elliptic curve algorithm, not the much shorter Bitcoin address.

derSigToHexSig takes a signature encoded in the DER format used by Bitcoin, and converts it to a hex signature. Basically it just strips out the length fields.

July 5, 2016 at 7:49 AM

Anonymous Anonymous said...

Great article as always, Ken! Great stuff.

July 7, 2016 at 10:40 AM

Anonymous Anonymous said...

Great blog Ken,

I started making a toy Bitcoin client in C#, this came very much in handy.
I was trying to get the public key generation right, I noticed I could not reproduce your public key from your private key (the ones in the image). Is that possible?

I verified my code with another known key pair and there I did get a match.

December 14, 2016 at 8:59 AM

Blogger Ken Shirriff said...

Anonymous: the keys in the image should be reproducible. The private key isf19c523315891e6e15ae0608a35eec2e00ebd6d1984cf167f46336dabd9b2de4 so check that's the value you have. I reproduced the 512-bit public key successfully with a different algorithm so it should work for you.

December 14, 2016 at 9:51 AM

Anonymous Anonymous said...

In signing the transaction it looks as though you are doing something with the private key, namely, sk = ecdsa.SigningKey.from_string(privateKey.decode('hex'), curve=ecdsa.SECP256k1). I was under the impression that you sign with the private key. Can you tell me what you are doing in creating a signing key? I have code that creates a raw tx, and code that passes tests for creating signatures, but I think this little bit is tripping me up. I wrote my own secp256k1 library, so I can generate public keys, but is this SigningKey functionality different from creating public keys? Do you know of any resource that could help me in regard to coding up this SigningKey algorithm?

January 29, 2017 at 10:20 PM

Blogger ನಾಗೇಶ್ said...

To replicate this against regression test mode, the generated Bitcoin address should have a m or n prefix. Can you please suggest how to change the keyToAddr() function in keyUtils.py. Changing '1' to 'm' in utils.base58CheckEncode didn't help.

February 4, 2017 at 10:51 AM

Blogger ನಾಗೇಶ್ said...

The network version should also be used in key generation. The pubKeyToAddr() function in keyUtils.py uses 0 for main network. That needs to be set to 111 for regtest mode. I am getting proper addresses now. Here is a list of prefixes: https://en.bitcoin.it/wiki/List_of_address_prefixes

February 4, 2017 at 8:52 PM

Blogger Darko Maksimovic said...

Wow, this is one of the best or possibly best technical blog I've seen. I love your detailed style. Thanks a million, I'm gonna browse more of your works.

February 15, 2017 at 1:25 PM

Blogger nagu said...

Hey,

Very well explained, Interested to know How did you find out your transaction is the junk of mined block?

Regards,
Nagu

May 18, 2017 at 12:22 AM

Blogger Galib Jaffery said...

Do i have to download the block chain to make a txn?

June 8, 2017 at 8:45 AM

Blogger Joan said...

Brillant article !! How long did it take to write it?

Many thanks!!!!

August 4, 2017 at 12:33 AM

Anonymous Anonymous said...

Very good article.
I'm interested in the script you used to push the raw tx to the bitcoin network.
I tried to run the script linked, but i got the message "No module named msgUtils"
Where can i find that module?

August 5, 2017 at 4:11 AM

Blogger RandomName said...

https://github.com/shirriff/bitcoin-code/
python code of yours is by far the fastest ever i have came accross to generate bitcoin address and private keys

but i would like to know ..

is the code still valid and maintained ?

i mean does it gives correct output of

keyUtils.privateKeyToWif
keyUtils.keyToAddr

as of today ?

August 18, 2017 at 6:47 AM

Blogger Ken Shirriff said...

Hi RandomName! The code is still valid, although I'm not actively maintaining it. However, I do not recommend using it to generate bitcoin addresses. The random number generator in Python is not cryptographically strong, so there's a small risk of someone figuring out your key. You're much better off using a cryptographic random number generator (which is also slower).

Anonymous: the msgUtils code is on github at https://github.com/shirriff/bitcoin-code/

August 19, 2017 at 11:37 AM

Anonymous Anonymous said...

Hi, i tried to use the minimalSendTxn.py to send a tx but seems it's not working (i tried both "real" bitcoin network and testnet, with many nodes), even if i don't get an explicit error message.
Did someone managed to send a tx using this script? It can be useful because it's not easy to send a tx to a specific node using "traditional" bitcoin softwares.

August 25, 2017 at 1:48 PM

Anonymous crusyn said...

Hello.

Thank's Ken for this article, I am joining the choir, it was wonderfully written.

I recently wrote an article after having gone through the exercise of trying to understand bitcoin transactions myself. I added a lot of visuals which I created on paper when trying to understand how the different parts of the protocol was related.

https://crusyn.com/2017/08/28/bitcoin-transactions-visual-guide-json/

I hope this is helpful. Let me know what you all think.

Chris

September 1, 2017 at 9:05 AM

Anonymous Dominik said...

Hello Ken,

thanks for your article! I want to create "custom transactions" myself in order to outsource the signing process to external crypto-hardware that securely stores the private key but I am having troubles executing the code. Where can I get the libraries?

Best regards,
Dominik

October 5, 2017 at 7:53 PM

Anonymous Anonymous said...

Hello Ken,

Thanks for your great article. I had many questions regarding blockchain protocol and bitcoin. This article with all the codes clears all of my doubts. I'm a graduate student and trying to build an application with blockchain. Can I please use your libraries and few functions for just educational and research purpose only (of course, with proper reference to your article)?

Thanks again.

October 30, 2017 at 4:17 AM

Blogger Ken Shirriff said...

Anonymous: sure, go ahead and use my libraries. Honestly, though, it would probably be easier to use a different library. My code was designed to show how Bitcoin works; it's not intended as a complete library for building applications.

October 30, 2017 at 10:54 AM

Blogger Emmy said...

Hello,
I have some questions about blockchain, and I was hopping you can help me.
When runing a multisig transaction, if the signature order is not right is the blockchain network which gives the error? or it is the bitcoin protocol? or it is the library?
Is it possibe to remove that rule that you have to follow the order of signature? if yes do you know how?
if the peer to peer network reject your transaction, can you know it and how?
Thank you

November 3, 2017 at 6:06 AM

Blogger Emmy said...

Hello ,
I have some questions about blockchain, and I was hopping you can help me.
When runing a multisig transaction, if the signature order is not right is the blockchain network which gives the error? or it is the bitcoin protocol? or it is the library?
Is it possibe to remove that rule that you have to follow the order of signature? if yes do you know how?
if the peer to peer network reject your transaction, can you know it and how?
Thank you

November 3, 2017 at 6:07 AM

Blogger David said...

I guess this is outdated after segwit isnt it?

December 20, 2017 at 10:38 PM

Blogger David said...


I followed you tutorial and now I'm trying to spend 3 unspent transactions of the same address and send them to another
Can you help me verifying if this is correct?

This is what I intend it to be:

version
0x1

input count
0x3

input no. 0x0
previous transaction output (reversed)
827359081e1e8c11cbef481e1ba0faeeaafc73534b9b56a353c4b31a0ba0d6ba
previous output index
0x4
script length
0xd6
scriptSig (unlocking script)
483045022100bd0f8ea1c6ad9caa7bd28d6dbcddd994083db4d383566a635eaa543e01520c75022023038537f8fa9ebaa9cc2d007c40b977a2ffd7b981c79ba323f5987ec2d6584b012103e6c17514d014d89adc38348567be3deb445ad6d81b285a53bb97be5e45bba7ef
sequence
0xffffffff
input no. 0x1
previous transaction output (reversed)
ab1d445ed1a17a6eca5fd93fba174904721dc6b013ef82886d790a4dc7edb3e0
previous output index
0x1
script length
0xd6
scriptSig (unlocking script)
483045022100bd0f8ea1c6ad9caa7bd28d6dbcddd994083db4d383566a635eaa543e01520c75022023038537f8fa9ebaa9cc2d007c40b977a2ffd7b981c79ba323f5987ec2d6584b012103e6c17514d014d89adc38348567be3deb445ad6d81b285a53bb97be5e45bba7ef
sequence
0xffffffff
input no. 0x2
previous transaction output (reversed)
4df764a4beb6d6be306cc0e150848c83e094c409f2f0351725894d3d3ffc5d63
previous output index
0x1
script length
0xd6
scriptSig (unlocking script)
483045022100bd0f8ea1c6ad9caa7bd28d6dbcddd994083db4d383566a635eaa543e01520c75022023038537f8fa9ebaa9cc2d007c40b977a2ffd7b981c79ba323f5987ec2d6584b012103e6c17514d014d89adc38348567be3deb445ad6d81b285a53bb97be5e45bba7ef
sequence
0xffffffff

output count
0x1

output no. 0x0
value
2145755 satoshis
script length
0x32
scriptPubKey (locking script for single p2pkh)
raw
76a914b5fb23fcee19cb21e185b0b48b8db8584cdf7a7488ac
destination address
1HbEAGviKPRZqP2bjGFrXfGiafyWBSxmke

block lock time
0x0


0100000003827359081e1e8c11cbef481e1ba0faeeaafc73534b9b56a353c4b31a0ba0d6ba040000006b483045022100bd0f8ea1c6ad9caa7bd28d6dbcddd994083db4d383566a635eaa543e01520c75022023038537f8fa9ebaa9cc2d007c40b977a2ffd7b981c79ba323f5987ec2d6584b012103e6c17514d014d89adc38348567be3deb445ad6d81b285a53bb97be5e45bba7efffffffffab1d445ed1a17a6eca5fd93fba174904721dc6b013ef82886d790a4dc7edb3e0010000006b483045022100bd0f8ea1c6ad9caa7bd28d6dbcddd994083db4d383566a635eaa543e01520c75022023038537f8fa9ebaa9cc2d007c40b977a2ffd7b981c79ba323f5987ec2d6584b012103e6c17514d014d89adc38348567be3deb445ad6d81b285a53bb97be5e45bba7efffffffff4df764a4beb6d6be306cc0e150848c83e094c409f2f0351725894d3d3ffc5d63010000006b483045022100bd0f8ea1c6ad9caa7bd28d6dbcddd994083db4d383566a635eaa543e01520c75022023038537f8fa9ebaa9cc2d007c40b977a2ffd7b981c79ba323f5987ec2d6584b012103e6c17514d014d89adc38348567be3deb445ad6d81b285a53bb97be5e45bba7efffffffff01dbbd2000000000001976a914b5fb23fcee19cb21e185b0b48b8db8584cdf7a7488ac00000000

December 22, 2017 at 1:57 AM

Anonymous Gonzalo Gasca MEza said...

Hi Ken,
Your work is inspiring, innovative, and after reading the bitcoin articles, I have learn so much from you. Can I translate it to Spanish and provide reference to your article?

December 23, 2017 at 8:53 AM

Blogger Ken Shirriff said...

Hi Gonzalo . Thanks for asking; yes go ahead.

Ken

December 23, 2017 at 11:04 AM

Comment deleted

This comment has been removed by a blog administrator.

March 9, 2018 at 12:51 AM

Blogger LRG said...

Thank you so much Ken. It is really written. It explains the step very clearly.

June 2, 2018 at 10:08 PM

Anonymous Anonymous said...

Just want to say thank you so so much. As a hobbyist python programmer. This resource is still highly relevant in 2018! (Exactly what I was looking for to understand the nuts and bolts and see if I can create some basic scripts)

- SIMPLY AMAZING

Thank you

July 5, 2018 at 7:45 AM

Blogger Unknown said...

Great article

August 9, 2018 at 10:56 PM

Anonymous Anonymouse said...

Hi Ken,
Thanks for the great article and sample code! I was able to generate transactions with my own coins that seem to decode correctly using https://live.blockcypher.com/btc/decodetx/, however I receive an error when transmitting it to the network.
Anyway, for those interested in reproducing the results, here are a few things that I discovered that may help you:
1. This code is written in Python 2, so don't try using it with Python 3. Print statements and encode/decode methods are some of the issues I encountered.
2. This code requires that you use uncompressed private keys and uncompressed public addresses. You can use the "Wallet Details" feature at bitaddress.org to convert compressed values.

August 28, 2019 at 8:08 PM

Anonymous Anonymous said...

"B's public key must correspond to B's address in the previous transaction" but why?!

December 7, 2019 at 6:37 PM

Anonymous georgyboy said...

Thanks so much for this article Ken. I read some higher level explanations of bitcoin, but seeing the step by step through working code was so helpful!

January 24, 2021 at 4:04 PM

Anonymous Anonymous said...

Great article!
Thank you

April 1, 2021 at 4:45 AM

You can use some HTML tags, such as <b>, <i>, <a>

Comment moderation has been enabled. All comments must be approved by the blog author.

You will be asked to sign in after submitting your comment.
Please prove you're not a robot