Litecoin Core Wallet Did Not Generate Public Key

Posted on by
Litecoin Core Wallet Did Not Generate Public Key Rating: 4,5/5 4256 votes

This should be done in the next few weeks, but if you're in a hurry to move those funds, I recommend exporting your private key from Litevault and importing it into Litecoin Core or Electrum (the official one, be careful with the fakes!). Hello fellow hodlrs. I am trying to make use of loafwallet, I Currently hodl my litecoins in the litecoin core wallet on windows. I see an option within loafwallet to import a private key, which brings up a camera intent to scan a QR Code. This page contains sample addresses and/or private keys. Do not send bitcoins to or import any sample keys; you will lose your money. Before reading this page, users should note that messing with ECDSA private keys is very dangerous and can result in losing bitcoins, even long after the import. Oct 10, 2016  Now, in order to import its balance on to my PC, I need to know a private key, which you may find printed on the wallet alongside of its public key. All I need to do is scan this code with a QR reader and it will reveal the private key to me just like that. We are going to present this process both on Electrum and Litecoin Core. Mar 27, 2018  I encrypted both and just realized that I have only one Seed Phrase set written down for the Daedalus wallet but not for the Litecoin Core wallet. It was late at night and I honestly dont recall writing down my recovery phrase for the Litecoin Core wallet, let alone being prompted to do so. Importing private keys requires you to create a new wallet file that will only contain the imported private keys. Start new electrum wallet file by following this short guide. Then come back here and proceed to step 2. Click on next to see the wallet type selection window: As you can see Electrum supports.

  1. Litecoin Core Wallet Did Not Generate Public Key West
  2. What Is Litecoin Core
  3. Litecoin Core Wallet Did Not Generate Public Key In Linux
  4. Litecoin Core Wallet Did Not Generate Public Keyboard

In cryptocurrencies, a private key allows a user to gain access to their wallet. The person who holds the private key fully controls the coins in that wallet. For this reason, you should keep it secret. And if you really want to generate the key yourself, it makes sense to generate it in a secure way.

Here, I will provide an introduction to private keys and show you how you can generate your own key using various cryptographic functions. I will provide a description of the algorithm and the code in Python.

Do I need to generate a private key?

In cryptocurrencies, a private key allows a user to gain access to their wallet. The person who holds the private key fully controls the coins in that wallet. For this reason, you should keep it secret. And if you really want to generate the key yourself, it makes sense to generate it in a secure way. Here, I will provide an introduction to private keys and show you how you can generate your.

Most of the time you don’t. For example, if you use a web wallet like Coinbase or Blockchain.info, they create and manage the private key for you. It’s the same for exchanges.

Mobile and desktop wallets usually also generate a private key for you, although they might have the option to create a wallet from your own private key.

So why generate it anyway? Here are the reasons that I have:

  • You want to make sure that no one knows the key
  • You just want to learn more about cryptography and random number generation (RNG)

What exactly is a private key?

Formally, a private key for Bitcoin (and many other cryptocurrencies) is a series of 32 bytes. Now, there are many ways to record these bytes. It can be a string of 256 ones and zeros (32 * 8 = 256) or 100 dice rolls. It can be a binary string, Base64 string, a WIF key, mnemonic phrase, or finally, a hex string. For our purposes, we will use a 64 character long hex string.

Why exactly 32 bytes? Great question! You see, to create a public key from a private one, Bitcoin uses the ECDSA, or Elliptic Curve Digital Signature Algorithm. More specifically, it uses one particular curve called secp256k1.

Now, this curve has an order of 256 bits, takes 256 bits as input, and outputs 256-bit integers. And 256 bits is exactly 32 bytes. So, to put it another way, we need 32 bytes of data to feed to this curve algorithm.

There is an additional requirement for the private key. Because we use ECDSA, the key should be positive and should be less than the order of the curve. The order of secp256k1 is FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141, which is pretty big: almost any 32-byte number will be smaller than it.

Naive method

So, how do we generate a 32-byte integer? The first thing that comes to mind is to just use an RNG library in your language of choice. Python even provides a cute way of generating just enough bits:

Looks good, but actually, it’s not. You see, normal RNG libraries are not intended for cryptography, as they are not very secure. They generate numbers based on a seed, and by default, the seed is the current time. That way, if you know approximately when I generated the bits above, all you need to do is brute-force a few variants.

When you generate a private key, you want to be extremely secure. Remember, if anyone learns the private key, they can easily steal all the coins from the corresponding wallet, and you have no chance of ever getting them back.

So let’s try to do it more securely.

Cryptographically strong RNG

Along with a standard RNG method, programming languages usually provide a RNG specifically designed for cryptographic operations. This method is usually much more secure, because it draws entropy straight from the operating system. The result of such RNG is much harder to reproduce. You can’t do it by knowing the time of generation or having the seed, because there is no seed. Well, at least the user doesn’t enter a seed — rather, it’s created by the program.

In Python, cryptographically strong RNG is implemented in the secrets module. Let’s modify the code above to make the private key generation secure!

That is amazing. I bet you wouldn’t be able to reproduce this, even with access to my PC. But can we go deeper?

Specialized sites

There are sites that generate random numbers for you. We will consider just two here. One is random.org, a well-known general purpose random number generator. Another one is bitaddress.org, which is designed specifically for Bitcoin private key generation.

Can random.org help us generate a key? Definitely, as they have service for generating random bytes. But two problems arise here. Random.org claims to be a truly random generator, but can you trust it? Can you be sure that it is indeed random? Can you be sure that the owner doesn’t record all generation results, especially ones that look like private keys? The answer is up to you. Oh, and you can’t run it locally, which is an additional problem. This method is not 100% secure.

Now, bitaddress.org is a whole different story. It’s open source, so you can see what’s under its hood. It’s client-side, so you can download it and run it locally, even without an Internet connection.

So how does it work? It uses you — yes, you — as a source of entropy. It asks you to move your mouse or press random keys. You do it long enough to make it infeasible to reproduce the results.

Are you interested to see how bitaddress.org works? For educational purposes, we will look at its code and try to reproduce it in Python.

Quick note: bitaddress.org gives you the private key in a compressed WIF format, which is close to the WIF format that we discussed before. For our purposes, we will make the algorithm return a hex string so that we can use it later for a public key generation.

Bitaddress: the specifics

Bitaddress creates the entropy in two forms: by mouse movement and by key pressure. We’ll talk about both, but we’ll focus on the key presses, as it’s hard to implement mouse tracking in the Python lib. We’ll expect the end user to type buttons until we have enough entropy, and then we’ll generate a key.

Bitaddress does three things. It initializes byte array, trying to get as much entropy as possible from your computer, it fills the array with the user input, and then it generates a private key.

Bitaddress uses the 256-byte array to store entropy. This array is rewritten in cycles, so when the array is filled for the first time, the pointer goes to zero, and the process of filling starts again.

The program initiates an array with 256 bytes from window.crypto. Then, it writes a timestamp to get an additional 4 bytes of entropy. Finally, it gets such data as the size of the screen, your time zone, information about browser plugins, your locale, and more. That gives it another 6 bytes.

After the initialization, the program continually waits for user input to rewrite initial bytes. When the user moves the cursor, the program writes the position of the cursor. When the user presses buttons, the program writes the char code of the button pressed.

Finally, bitaddress uses accumulated entropy to generate a private key. It needs to generate 32 bytes. For this task, bitaddress uses an RNG algorithm called ARC4. The program initializes ARC4 with the current time and collected entropy, then gets bytes one by one 32 times.

This is all an oversimplification of how the program works, but I hope that you get the idea. You can check out the algorithm in full detail on Github.

Doing it yourself

Pki private-key generate rsa. For our purposes, we’ll build a simpler version of bitaddress. First, we won’t collect data about the user’s machine and location. Second, we will input entropy only via text, as it’s quite challenging to continually receive mouse position with a Python script (check PyAutoGUI if you want to do that).

That brings us to the formal specification of our generator library. First, it will initialize a byte array with cryptographic RNG, then it will fill the timestamp, and finally it will fill the user-created string. After the seed pool is filled, the library will let the developer create a key. Actually, they will be able to create as many private keys as they want, all secured by the collected entropy.

Initializing the pool

Here we put some bytes from cryptographic RNG and a timestamp. __seed_int and __seed_byte are two helper methods that insert the entropy into our pool array. Notice that we use secrets.

Seeding with input

Here we first put a timestamp and then the input string, character by character.

Generating the private key

This part might look hard, but it’s actually very simple.

First, we need to generate 32-byte number using our pool. Unfortunately, we can’t just create our own random object and use it only for the key generation. Instead, there is a shared object that is used by any code that is running in one script.

What does that mean for us? It means that at each moment, anywhere in the code, one simple random.seed(0) can destroy all our collected entropy. We don’t want that. Thankfully, Python provides getstate and setstate methods. So, to save our entropy each time we generate a key, we remember the state we stopped at and set it next time we want to make a key.

Second, we just make sure that our key is in range (1, CURVE_ORDER). This is a requirement for all ECDSA private keys. The CURVE_ORDER is the order of the secp256k1 curve, which is FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141.

Finally, for convenience, we convert to hex, and strip the ‘0x’ part.

In action

Let’s try to use the library. Actually, it’s really simple: you can generate a private key in three lines of code!

You can see it yourself. The key is random and totally valid. Moreover, each time you run this code, you get different results.

Conclusion

As you can see, there are a lot of ways to generate private keys. They differ in simplicity and security.

Generating a private key is only a first step. The next step is extracting a public key and a wallet address that you can use to receive payments. The process of generating a wallet differs for Bitcoin and Ethereum, and I plan to write two more articles on that topic.

If you want to play with the code, I published it to this Github repository.

I am making a course on cryptocurrencies here on freeCodeCamp News. The first part is a detailed description of the blockchain.

I also post random thoughts about crypto on Twitter, so you might want to check it out.

Bitcoin can be coldly unforgiving of mistakes, and nowhere is this better demonstrated than with change addresses. Although change addresses provide a key privacy tool, they can also lead to confusion, loss, or theft when not understood.

This article explains how to safely use one of Bitcoin’s least understood features. It ends with a list of common pitfalls and ways to avoid them.

This article was first published in March 2014. Since then, wallet software has improved, eliminating some of the threats described below. Specifically cases (1) and (4) should only be encountered when using older, unsupported software.

Imagine paying for groceries with a debit card. The checker totals the amount due and you swipe your card as usual. However, you notice the payment terminal is asking for all of the money in your account.

The checker smiles, explaining that this is part of your bank’s new rewards program. You have three options: (1) send the change back to your current account; (2) send the change to a newly-created bank account; or (3) say nothing and send the change to the payment terminal company.

Counterintuitive? Confusing? Alarming? Many Bitcoin users are surprised to find eerie similarities between this diabolical debit card and the way transactions seem to work.

Thinking about Bitcoin in terms of past experiences with online banking and debit cards can lead to problems. Fortunately, an older payment method offers better insights into how Bitcoin works.

The similarities between Bitcoin and cash run deep. In his whitepaper, Satoshi Nakamoto even described Bitcoin as an “electronic cash system.” Understanding the close connection between Bitcoin and physical cash is the key to understanding change addresses.

Imagine needing to track different pools of paper bills, maybe as part of a collection drive. You might use envelopes to keep the bills physically separate from each other — a “cash envelope”.

A Bitcoin address can be thought of as the digital equivalent of a cash envelope.

Like a cash envelope, an address can hold zero or more units of electronic cash. Instead of paper bills, Bitcoin uses the electronic equivalent: “unspent outputs”. To find the balance of any address, we sum the values of each associated unspent output. In a similar way, the amount held in a cash envelope can be found by totaling the values of all its bills.

A Bitcoin transaction transfers the ownership of one or more unspent outputs. To continue with the paper example, a transaction would teleport one or more bills from one or more envelopes into one or more envelopes. Like many Bitcoin analogies, however, this one doesn’t capture the entire situation. A more accurate statement would be to say that bills can be rematerialized in any set of denominations provided that the sum of their values is less than or equal to the value of the dematerialized bills. A more detailed explanation may be helpful when reading this article.

Imagine that Alice, who controls an address containing one unspent output worth 10 bitcoin (BTC), wants to pay Bob 10 bitcoin. Alice does so with a transaction sending her single unspent output to Bob’s empty address. In doing so, Alice’s address balance falls to zero and Bob’s address balance rises to 10 bitcoin.

After the transaction, Bob can give the unspent output he received from Alice to someone else. However, Alice will neither be allowed to take back the unspent output she transferred, nor will she be able to spend it again.

A few days later, Alice wants to pay Bob 5 BTC from an address containing a single output valued at 10 BTC. Alice has a problem: she needs to pay Bob, but she doesn’t want to give him the entire 10 BTC. Alice wouldn’t be allowed to rip a $10 bill in half to pay Bob $5. Likewise, Bitcoin requires Alice to spend the entire value of her 10 BTC.

To resolve this dilemma, Alice uses a transaction that splits her payment, a feature fully supported by Bitcoin. One part of the transaction sends 5 BTC to Bob’s address and the other returns 5 BTC back to her own. In a similar way, Alice could break a $10 bill at the bank into two $5 bills, giving one to Bob and keeping one for herself.

Over time, Alice’s address accumulates unspent outputs from people who have paid her. Her address now contains unspent outputs valued at 20 BTC, 10 BTC, and 5 BTC.

Once again, it’s time for Alice to pay Bob - this time 8 BTC. Alice creates a transaction that splits her 10 BTC unspent output, sending 8 BTC to Bob’s address and returning 2 BTC to her own as change. Alice’s address balance falls to 27 BTC and Bob’s address balance rises to 8 BTC.

In the previous examples, Alice directed change into the same address she spent from. Although this decision simplified accounting, it unfortunately reduced Bob’s privacy as well as her own.

By design, every Bitcoin transaction remains permanently viewable in a global public log called the “block chain.” Privacy depends on the strict separation between addresses and personal identities, a model referred to as pseudonymity.

Any observer capable of linking Bitcoin addresses to personal identities can begin to draw conclusions about money transfers between people. Users make this job more difficult by sending change to newly-created addresses.

To see why, imagine a transaction that sends funds from Address A to Address B. If change is returned to Address A, the block chain reveals that the person controlling Address A paid the person controlling Address B. The same reasoning holds if two or more addresses are involved. Any transaction involving Address A as a sender reveals the receiving address unambiguously.

Gta 5 xbox 360 license key generator no survey. Should the identity of the person controlling either receiving or payment addresses become known, the identities of the other parties could become known as well.

Now imagine that Address A initiates a payment to B, but this time directs change to a newly-generated change address C. Without knowing which address receives change, all we can deduce is that a transaction split Address A’s balance between Addresses B and C. The identity of the person controlling Addresses B or C may or may not be the same as the identity of the person controlling Address A. Given another transaction from Address C, the picture becomes even murkier. Which of the transfers represent payments and which represent the receipt of change?

Litecoin Core Wallet Did Not Generate Public Key West

An observer trying to link personal identities to addresses must gather more secondary information and expend more resources when all parties send change to newly-created addresses.

Coordinating multiple addresses is a complicated task. Wallet software frees the user from the need to do this manually.

Litecoin core wallet did not generate public key workNot

Although change addresses play a key role in improving privacy, wallet developers can implement this feature in a number of ways. Four strategies are currently in use, each with its own implications for privacy and security.

  • Single-Address Wallets use a single address to receive both payments and change. Additional addresses may added when a receiving address is manually added, or a private key is imported. An example is the now-unsupported MultiBit Classic.
  • Random Address Pool Wallets use a fixed-size pool of randomly-generated addresses. Change is sent to the next available empty address, causing the creation of a new empty address to take its place. The best-known example was Bitcoin-Qt, until its key-handling functionality was upgraded.
  • Deterministic Address Pool Wallets contain a practically infinite pool of deterministically-generated addresses. A subset of this pool contains addresses reserved for receiving change. Examples include Electrum and Armory.
  • Hybrid Wallets use multiple strategies, depending on context. MultiBit, Mycelium, and Electrum are examples.

Let’s now consider some ways that misunderstanding change addresses, combined with semi-manual address management, can lead to loss or theft of funds.

Incorrect use of Bitcoin change addresses account for many cases of loss or theft of funds. Here are some disaster scenarios and ways to avoid them.

1. Backup Failure

Alice uses an old version of Bitcoin-Qt. Understanding the importance of backups, she created an encrypted wallet backup long ago and stored it in a safe place. After making dozens of transactions with Bitcoin-Qt, Alice’s hard drive crashed.

Alice bought a new hard drive and then re-installed Bitcoin-Qt on it. She then restored her wallet backup. To her horror, Alice discovered the restored wallet was empty.

Explanation: Alice generated enough change addresses to overflow the original pool of 100. On the 100th spending transaction, Bitcoin-Qt moved Alice’s change (which happend to be her entire balance) into an address not in the backup. Restoring the backup only restored empty addresses.

Recovery: Even if a hard drive can’t boot an operating system, individual files can still be recovered. Using data recovery tools, Alice may be able to salvage the Bitcoin-Qt wallet from the faulty hard drive, and with it her lost funds.

Prevention:

  • Count the number of manually-created addresses and spending transactions since your last backup. If this number is greater than about 80, back up again. Weekly backups might be enough for most users.
  • Set a very high value (e.g., 10,000) for the -keypool option, either as a command line parameter, or in the bitcoin.conf file.
  • Switch to a deterministic wallet.

2. Failure to Monitor Change Address

Bob uses Electrum to send infrequent bitcoin payments. Worried about possible theft, he wanted a way to keep an eye on his bitcoin balance from one of his many devices.

Bob decided on blockchain.info to monitor address activity. Bob’s Electrum wallet contained several addresses, but only one of them held bitcoin (0.3 BTC). Assuming this was the only address he’d be using, Bob pasted it into the blockchain.info search window and bookmarked the resulting page.

A few weeks later, Bob made a 0.2 BTC payment to Overstock from his Electrum wallet. After receiving his merchandise, Bob decided to check his balance with blockchain.info.

Disturbingly, Bob discovered that part of his Overstock payment was transferred to an unknown address. Thinking that his computer running Electrum had been compromised, Bob re-formated the hard drive.

Explanation: Although it may look to Bob as if an eavesdropper changed his transaction before it was sent to Overstock, he’s instead seeing the result of normal wallet operation. Electrum sent the change from Bob’s transaction to one of its deterministically-generated change addresses. This cleared the balance from the sending address, the only one Bob was monitoring.

Recovery: Electrum encourages the storage of its 12-word address generation seed in a safe location. Should Bob still have access to the seed, he can re-generate his old wallet and recover the change from the Overstock transaction.

Prevention:

  • If using a deterministic wallet, create a watching-only wallet to monitor addresses.
  • If using Bitcoin-Qt, manually update your list of watch addresses after every payment, or switch to a deterministic wallet.

3. Spending from a Paper Wallet

Carlos is a saver. Awhile back he bought 20 bitcoins at $10 apiece, and then transferred them to a paper wallet he created at bitaddress.org. He didn’t do anything with Bitcoin since then.

One day Carlos noticed a deal on new laptops at Overstock and decided to pay using one of his saved bitcoins. But Carlos had a problem: he needed to get his paper wallet into a software wallet to pay Overstock.

Carlos downloaded MultiBit and imported his paper wallet’s private key. After paying Overstock, he exited the program.

Carlos was worried about leaving any trace of his private key on his computer, so he securely deleted MultiBit and its data directory. He then returned his paper wallet to its safe location.

After a few weeks, Carlos checked his paper wallet’s balance. To his shock, the balance read zero. Nineteen bitcoins were sent to an unfamiliar address on the same day as the Overstock payment.

Explanation: Carlos suspects foul play, but he’s actually seeing the result of normal wallet behavior. The 19 missing bitcoins were sent to a change address, leaving his paper wallet empty.

Recovery: In securely deleting the MultiBit data directory, Carlos lost any chance of recovering the missing funds.

Prevention:

  • Before deleting any hot wallet with an imported paper wallet private key, send the remaining balance back to a paper wallet.
  • Use a software wallet that will return change back to the paper wallet. One example is Mycelium. Another is Blockchain.info through the “custom spend” option. Both approaches would return change to the paper wallet, although doing so degrades privacy.

4. Sharing a Wallet

Dave runs Bitcoin-Qt on two computers, a laptop and a desktop in his garage. Wanting to use both computers to make payments, Dave copied a clean wallet.dat backup file from the laptop to the desktop.

After making many payments without a problem from both computers, Dave noticed something odd one day. His laptop wallet showed a zero balance, but his desktop wallet showed the correct balance.

Explanation: Dave’s computer network was not compromised, nor did he uncover a bug in Bitcoin-Qt. Instead, his copy of Bitcoin-Qt running on the desktop used the last available pool address held jointly with the laptop. On his last transaction, Dave’s change was sent to an address generated on the desktop, but unknown to the wallet.

Recovery: Back up the wallets on both the laptop and the desktop. Export all private keys from both computers, and sweep them into a new wallet. If sharing wallets is critical, don’t continue using Bitcoin-Qt.

Prevention:

  • Don’t use old versions of Bitcoin-Qt to share wallets among multiple computers. Use Electrum or a more recent version of Bitcoin Core, which were designed specifically with this use case in mind.

5. Theft from an Imported Paper Wallet

Frank received a paper wallet containing 2 BTC as a gift at a company event. Eager to see how Bitcoin works, he installed MultiBit and imported the paper wallet’s private key. Not seeing a need to keep the paper wallet, Frank threw it into the recycling bin at his office.

Over time, Frank depleted his Bitcoin funds. To re-fund his wallet, Frank bought an additional 2 BTC from Coinbase and then transferred them into his MultiBit wallet.

Shortly thereafter, Frank bought a set of sheets from Overstock for 0.1 BTC. Although this payment confirmed without issue, Frank noticed something odd. Without his approval, a second withdrawal was made to an unknown address, emptying his wallet of the remaining 1.9 BTC.

Explanation: Although Frank was the victim of theft, the route of attack was not his computer or network. It was the paper wallet he threw into the recycling bin.

Unknown to Frank, the paper wallet was taken from the recycling bin by Eve, a dishonest coworker. Eve added the private key to a custom program that automatically detects deposits into a list of watched addresses, and then withdraws them immediately.

MultiBit, working as designed, used the imported paper wallet address to receive 1.9 BTC in change from Frank’s Overstock payment. Eve’s program noticed the transfer and immediately withdrew the funds.

Eve pulled off her heist without access to Frank’s computer, or even knowledge of Frank’s identity. The plan worked because Eve know one of the private keys being used to receive change in Frank’s MultiBit wallet.

Recovery: Frank cannot recover the funds, nor is he likely to determine the identity of the thief.

What Is Litecoin Core

Prevention:

  • Sweeping a paper wallet generates a transaction moving all unspent outputs into a wallet address, depleting the paper wallet. The paper wallet private key is never again used by the wallet software. Unless you have a compelling reason to do otherwise, sweep paper wallets instead of importing them. This is especially important for paper wallets that you did not generate yourself securely.

Although the examples in the previous section resulted in complete loss of funds, the same mechanisms also allow for partial loss. These conditions were assumed, which may or may not hold at the time a change address problem arises:

  1. The entire balance of a wallet resides at a single address.
  2. This single address contains one unspent output.

For example, a single address that receives multiple payments will contain multiple unspent outputs. Likewise, wallet balances can become distributed across multiple change addresses as the user spends funds.

Imagine Alice’s wallet contains two addresses, Address 1 and Address 2, with a total value of 15 BTC. To make a 6 BTC payment, the wallet chooses a 7 BTC unspent output from Address 1, receiving 1 BTC change into Address 2. As expected, her wallet balance decreases to 9 BTC.

Then disaster strikes - Alice’s hard drive fails. After installing a new hard drive and restoring her wallet backup, Alice notices something odd. Before the hard drive crash, her wallet balance was 9 BTC. But the balance only read 8 BTC after recovering the backup. Why does 1 BTC seem to be missing?

Alice was using a random address pool wallet, in which Address 2 was not contained in her original backup. Restoring the backup gave the appearance that Address 2 had “disappeared”, and along with it the 1 BTC spent output it contained.

Litecoin Core Wallet Did Not Generate Public Key In Linux

In a sense, Alice was lucky because she could have lost her entire wallet balance. On the other hand, without understanding change addresses, Alice would likely be very confused about what happened to the missing 1 BTC. The same mistake could happen again.

Litecoin Core Wallet Did Not Generate Public Keyboard

When used correctly, directing change to a newly-generated address promotes privacy. But with this capability comes the potential for loss and theft. To avoid potentially costly mistakes, familiarize yourself with change addresses and how your wallet software implements them.

I’m grateful to members of the Bitcoin Subreddit who helped clarify two key technical points in the original version of this article.