diff --git a/02intro.asciidoc b/02intro.asciidoc index b852a20ab..dbc01fb44 100644 --- a/02intro.asciidoc +++ b/02intro.asciidoc @@ -251,7 +251,7 @@ You can explore the transaction history of any address. Take a look at the trans ((("Ethereum (generally)","and EVM")))((("EVM (Ethereum Virtual Machine)","as world computer")))((("world computer, Ethereum as")))You've now created a wallet and sent and received ether. So far, we've treated Ethereum as a cryptocurrency. But Ethereum is much, much more. In fact, the cryptocurrency function is subservient to Ethereum's function as a decentralized world computer. ((("smart contracts","ether and")))Ether is meant to be used to pay for running _smart contracts_, which are computer programs that run on an emulated computer called the _Ethereum Virtual Machine_ (EVM). -The EVM is a global singleton, meaning that it operates as if it were a global, single-instance computer, running everywhere. Each node on the Ethereum network runs a local copy of the EVM to validate contract execution, while the Ethereum blockchain records the changing _state_ of this world computer as it processes transactions and smart contracts. We'll discuss this in much greater detail in <>. +The EVM is a global singleton, meaning that it operates as if it were a global, single-instance computer, running everywhere. Each node on the Ethereum network runs a local copy of the EVM to validate contract execution, while the Ethereum blockchain records the changing _state_ of this world computer as it processes transactions and smart contracts. We'll discuss this in much greater detail in xref:13evm.asciidoc#evm_chapter[evm_chapter]. [[EOA_contracts]] === Externally Owned Accounts (EOAs) and Contracts @@ -267,7 +267,7 @@ In the next few sections, we will write our first contract. You will then learn [[simple_contract_example]] === A Simple Contract: A Test Ether Faucet -((("contract accounts","creating", seealso="Faucet.sol contract", id="ix_02intro-asciidoc10", range="startofrange")))((("Faucet.sol contract (test example)","creating", id="ix_02intro-asciidoc11", range="startofrange")))Ethereum has many different high-level languages, all of which can be used to write a contract and produce EVM bytecode. You can read about many of the most prominent and interesting ones in <>. One high-level language is by far the dominant choice for smart contract programming: Solidity. ((("Wood, Dr. Gavin","and Solidity")))Solidity was created by Dr. Gavin Wood, the coauthor of this book, and has become the most widely used language in Ethereum (and beyond). We'll use Solidity to write our first contract. +((("contract accounts","creating", seealso="Faucet.sol contract", id="ix_02intro-asciidoc10", range="startofrange")))((("Faucet.sol contract (test example)","creating", id="ix_02intro-asciidoc11", range="startofrange")))Ethereum has many different high-level languages, all of which can be used to write a contract and produce EVM bytecode. You can read about many of the most prominent and interesting ones in xref:07smart-contracts-solidity.asciidoc#high_level_languages[high_level_languages]. One high-level language is by far the dominant choice for smart contract programming: Solidity. ((("Wood, Dr. Gavin","and Solidity")))Solidity was created by Dr. Gavin Wood, the coauthor of this book, and has become the most widely used language in Ethereum (and beyond). We'll use Solidity to write our first contract. ((("Solidity","faucet.sol and")))For our first example (<>), we will write a contract that controls a _faucet_. You've already used a faucet to get test ether on the Ropsten test network. A faucet is a relatively simple thing: it gives out ether to any address that asks, and can be refilled periodically. You can implement a faucet as a wallet controlled by a human or a web server. @@ -542,4 +542,6 @@ Next, you wrote a faucet contract in Solidity. You used the Remix IDE to compile It may not seem like much, but you've just successfully interacted with software that controls money on a decentralized world computer. -We will do a lot more smart contract programming in <> and learn about best practices and security considerations in <>.(((range="endofrange", startref="ix_02intro-asciidoc0"))) +We will do a lot more smart contract programming in xref:07smart-contracts-solidity.asciidoc[smart_contracts_chapter] +and learn about best practices and security considerations in xref:09smart-contracts-security.asciidoc[smart_contract_security].(((range="endofrange", +startref="ix_02intro-asciidoc0"))) diff --git a/03clients.asciidoc b/03clients.asciidoc index 258bfbb31..eae317fb7 100644 --- a/03clients.asciidoc +++ b/03clients.asciidoc @@ -5,7 +5,7 @@ Ethereum is an open source project, and the source code for all the major clients is available under open source licenses (e.g., LGPL v3.0), free to download and use for any purpose. _Open source_ means more than simply free to use, though. It also means that Ethereum is developed by an open community of volunteers and can be modified by anyone. More eyes means more trustworthy code. -((("Yellow Paper specification")))Ethereum is defined by a formal specification called the "Yellow Paper" (see <>). +((("Yellow Paper specification")))Ethereum is defined by a formal specification called the "Yellow Paper" (see xref:01what-is.asciidoc#references[references]). ((("Bitcoin","Ethereum definition compared to")))This is in contrast to, for example, Bitcoin, which is not defined in any formal way. Where Bitcoin's "specification" is the reference implementation Bitcoin Core, Ethereum's specification is documented in a paper that combines an English and a mathematical (formal) specification. This formal specification, in addition to various Ethereum Improvement Proposals, defines the standard behavior of an Ethereum pass:[client]. The Yellow Paper is periodically updated as major changes are made to pass:[Ethereum]. diff --git a/04keys-addresses.asciidoc b/04keys-addresses.asciidoc index 24a8deb9f..60e258c00 100644 --- a/04keys-addresses.asciidoc +++ b/04keys-addresses.asciidoc @@ -12,13 +12,13 @@ In this chapter we will introduce some of the cryptography used in Ethereum: nam ((("cryptography","keys and addresses")))((("EOA (Externally Owned Account)","keys and addresses")))((("keys and addresses")))As we saw earlier in the book, Ethereum has two different types of accounts: _externally owned accounts_ (EOAs) and _contracts_. Ownership of ether by EOAs is established through digital _private keys_, _Ethereum addresses_, and _digital signatures_. ((("private keys", seealso="keys and addresses")))The private keys are at the heart of all user interaction with Ethereum. In fact, account addresses are derived directly from private keys: a private key uniquely determines a single Ethereum address, also known as an _account_. -Private keys are not used directly in the Ethereum system in any way; they are never transmitted or stored on Ethereum. That is to say that private keys should remain private and never appear in messages passed to the network, nor should they be stored on-chain; only account addresses and digital signatures are ever transmitted and stored on the Ethereum system. For more information on how to keep private keys safe and secure, see <> and <>. +Private keys are not used directly in the Ethereum system in any way; they are never transmitted or stored on Ethereum. That is to say that private keys should remain private and never appear in messages passed to the network, nor should they be stored on-chain; only account addresses and digital signatures are ever transmitted and stored on the Ethereum system. For more information on how to keep private keys safe and secure, see xref:02intro.asciidoc#control_responsibility[control_responsibility] and xref:05wallets.asciidoc[wallets_chapter]. ((("digital signatures")))Access and control of funds is achieved with digital signatures, which are also created using the private key. Ethereum transactions require a valid digital signature to be included in the blockchain. Anyone with a copy of a private key has control of the corresponding account and any ether it holds. Assuming a user keeps their private key safe, the digital signatures in Ethereum transactions prove the true owner of the funds, because they prove ownership of the private key. ((("key pairs")))In public key cryptography–based systems, such as that used by Ethereum, keys come in pairs consisting of a private (secret) key and a public key. Think of the public key as similar to a bank account number, and the private key as similar to the secret PIN; it is the latter that provides control over the account, and the former that identifies it to others. The private keys themselves are very rarely seen by Ethereum users; for the most part, they are stored (in encrypted form) in special files and managed by Ethereum wallet software. -In the payment portion of an Ethereum transaction, the intended recipient is represented by an Ethereum address, which is used in the same way as the beneficiary account details of a bank transfer. As we will see in more detail shortly, an Ethereum address for an EOA is generated from the public key portion of a key pair. However, not all Ethereum addresses represent public–private key pairs; they can also represent contracts, which, as we will see in <>, are not backed by private keys. +In the payment portion of an Ethereum transaction, the intended recipient is represented by an Ethereum address, which is used in the same way as the beneficiary account details of a bank transfer. As we will see in more detail shortly, an Ethereum address for an EOA is generated from the public key portion of a key pair. However, not all Ethereum addresses represent public–private key pairs; they can also represent contracts, which, as we will see in xref:07smart-contracts-solidity.asciidoc[smart_contracts_chapter], are not backed by private keys. In the rest of this chapter, we will first explore basic cryptography in a bit more detail and explain the mathematics used in Ethereum. Then we will look at how keys are generated, stored, and managed. Finally, we will review the various encoding formats used to represent private keys, public keys, and addresses. @@ -50,7 +50,7 @@ Take a look at the following resources if you're interested in reading more abou * http://bit.ly/2zfeKCP[Elliptic curve cryptography] ==== -In Ethereum, we use public key cryptography (also known as asymmetric cryptography) to create the public–private key pair we have been talking about in this chapter. They are considered a "pair" because the public key is derived from the private key. Together, they represent an Ethereum account by providing, respectively, a publicly accessible account handle (the address) and private control over access to any ether in the account and over any authentication the account needs when using smart contracts. ((("digital signatures","private key and")))The private key controls access by being the unique piece of information needed to create _digital signatures_, which are required to sign transactions to spend any funds in the account. Digital signatures are also used to authenticate owners or users of contracts, as we will see in <>. +In Ethereum, we use public key cryptography (also known as asymmetric cryptography) to create the public–private key pair we have been talking about in this chapter. They are considered a "pair" because the public key is derived from the private key. Together, they represent an Ethereum account by providing, respectively, a publicly accessible account handle (the address) and private control over access to any ether in the account and over any authentication the account needs when using smart contracts. ((("digital signatures","private key and")))The private key controls access by being the unique piece of information needed to create _digital signatures_, which are required to sign transactions to spend any funds in the account. Digital signatures are also used to authenticate owners or users of contracts, as we will see in xref:07smart-contracts-solidity.asciidoc[smart_contracts_chapter]. [TIP] ==== @@ -631,4 +631,4 @@ The capitalization of the address we input doesn't match the checksum just calcu [[keys-addresses-conclusions]] === Conclusions -In this chapter we provided a brief survey of public key cryptography and focused on the use of public and private keys in Ethereum and the use of cryptographic tools, such as hash functions, in the creation and verification of Ethereum addresses. We also looked at digital signatures and how they can demonstrate ownership of a private key without revealing that private key. In <>, we will put these ideas together and look at how wallets can be used to manage collections of keys.(((range="endofrange", startref="ix_04keys-addresses-asciidoc0"))) +In this chapter we provided a brief survey of public key cryptography and focused on the use of public and private keys in Ethereum and the use of cryptographic tools, such as hash functions, in the creation and verification of Ethereum addresses. We also looked at digital signatures and how they can demonstrate ownership of a private key without revealing that private key. In xref:05wallets.asciidoc[wallets_chapter], we will put these ideas together and look at how wallets can be used to manage collections of keys.(((range="endofrange", startref="ix_04keys-addresses-asciidoc0"))) diff --git a/05wallets.asciidoc b/05wallets.asciidoc index 2f7c7a5ae..607bc3a09 100644 --- a/05wallets.asciidoc +++ b/05wallets.asciidoc @@ -5,7 +5,7 @@ At a high level, a wallet is a software application that serves as the primary user interface to Ethereum. The wallet controls access to a user's money, managing keys and addresses, tracking the balance, and creating and signing transactions. In addition, some Ethereum wallets can also interact with contracts, such as ERC20 tokens. -((("wallets","defined")))More narrowly, from a programmer's perspective, the word _wallet_ refers to the system used to store and manage a user's keys. Every wallet has a key-management component. For some wallets, that's all there is. Other wallets are part of a much broader category, that of _browsers_, which are interfaces to Ethereum-based decentralized applications, or _DApps_, which we will examine in more detail in <>. There are no clear lines of distinction between the various categories that are conflated under the term wallet. +((("wallets","defined")))More narrowly, from a programmer's perspective, the word _wallet_ refers to the system used to store and manage a user's keys. Every wallet has a key-management component. For some wallets, that's all there is. Other wallets are part of a much broader category, that of _browsers_, which are interfaces to Ethereum-based decentralized applications, or _DApps_, which we will examine in more detail in xref:12dapps.asciidoc[decentralized_applications_chap]. There are no clear lines of distinction between the various categories that are conflated under the term wallet. In this chapter we will look at wallets as containers for private keys, and as systems for managing these keys. @@ -419,4 +419,4 @@ Because BIP-44 was created originally for Bitcoin, it contains a "quirk" that is === Conclusions -Wallets are the foundation of any user-facing blockchain application. They allow users to manage collections of keys and addresses. Wallets also allow users to demonstrate their ownership of ether, and authorize transactions, by applying digital signatures, as we will see in <>.(((range="endofrange", startref="ix_05wallets-asciidoc0"))) +Wallets are the foundation of any user-facing blockchain application. They allow users to manage collections of keys and addresses. Wallets also allow users to demonstrate their ownership of ether, and authorize transactions, by applying digital signatures, as we will see in xref:06transactions.asciidoc[tx_chapter].(((range="endofrange", startref="ix_05wallets-asciidoc0"))) diff --git a/06transactions.asciidoc b/06transactions.asciidoc index 602294752..b765a51d6 100644 --- a/06transactions.asciidoc +++ b/06transactions.asciidoc @@ -37,7 +37,7 @@ For example, you may notice there is no “from” data in the address [[tx_nonce]] === The Transaction Nonce -((("nonces", id="ix_06transactions-asciidoc1", range="startofrange")))((("transactions","nonces", id="ix_06transactions-asciidoc2", range="startofrange")))The nonce is one of the most important and least understood components of a transaction. The definition in the Yellow Paper (see <>) reads: +((("nonces", id="ix_06transactions-asciidoc1", range="startofrange")))((("transactions","nonces", id="ix_06transactions-asciidoc2", range="startofrange")))The nonce is one of the most important and least understood components of a transaction. The definition in the Yellow Paper (see xref:01what-is.asciidoc#references[references]) reads: ____ +nonce+: A scalar value equal to the number of transactions sent from this address or, in the case of accounts with associated code, the number of contract-creations made by this account. @@ -166,13 +166,13 @@ In the end, these concurrency problems, on top of the difficulty of tracking acc [[tx_gas]] === Transaction Gas -((("gas","transactions and", id="ix_06transactions-asciidoc3", range="startofrange")))((("transactions","gas", id="ix_06transactions-asciidoc4", range="startofrange")))We talked about gas a little in earlier chapters, and we discuss it in more detail in <>. However, let's cover some basics about the role of the +gasPrice+ and +gasLimit+ components of a transaction. +((("gas","transactions and", id="ix_06transactions-asciidoc3", range="startofrange")))((("transactions","gas", id="ix_06transactions-asciidoc4", range="startofrange")))We talked about gas a little in earlier chapters, and we discuss it in more detail in xref:13evm.asciidoc#gas[gas]. However, let's cover some basics about the role of the +gasPrice+ and +gasLimit+ components of a transaction. Gas is the fuel of Ethereum. Gas is not ether—it's a separate virtual currency with its own exchange rate against ether. Ethereum uses gas to control the amount of resources that a transaction can use, since it will be processed on thousands of computers around the world. The open-ended (Turing-complete) computation model requires some form of metering in order to avoid denial-of-service attacks or inadvertently resource-devouring transactions. Gas is separate from ether in order to protect the system from the volatility that might arise along with rapid changes in the value of ether, and also as a way to manage the important and sensitive ratios between the costs of the various resources that gas pays for (namely, computation, memory, and storage). -((("gasPrice field")))The +gasPrice+ field in a transaction allows the transaction originator to set the price they are willing to pay in exchange for gas. The price is measured in wei per gas unit. For example, in the sample transaction in <> your wallet set the +gasPrice+ to 3 gwei (3 gigawei or 3 billion wei). +((("gasPrice field")))The +gasPrice+ field in a transaction allows the transaction originator to set the price they are willing to pay in exchange for gas. The price is measured in wei per gas unit. For example, in the sample transaction in xref:01what-is.asciidoc[intro_chapter], your wallet set the +gasPrice+ to 3 gwei (3 gigawei or 3 billion wei). [TIP] ==== @@ -224,7 +224,7 @@ Ethereum does no further validation of this field. Any 20-byte value is consider The Ethereum protocol does not validate recipient addresses in transactions. You can send to an address that has no corresponding private key or contract, thereby "burning" the ether, rendering it forever unspendable. Validation should be done at the user interface level. ==== -((("ether burn")))Sending a transaction to the wrong address will probably _burn_ the ether sent, rendering it forever inaccessible (unspendable), since most addresses do not have a known private key and therefore no signature can be generated to spend it. It is assumed that validation of the address happens at the user interface level (see <>). In fact, there are a number of valid reasons for burning ether—for example, as a disincentive to cheating in payment channels and other smart contracts—and since the amount of ether is finite, burning ether effectively distributes the value burned to all ether holders (in proportion to the amount of ether they hold). +((("ether burn")))Sending a transaction to the wrong address will probably _burn_ the ether sent, rendering it forever inaccessible (unspendable), since most addresses do not have a known private key and therefore no signature can be generated to spend it. It is assumed that validation of the address happens at the user interface level (see xref:04keys-addresses.asciidoc#EIP55[EIP55]). In fact, there are a number of valid reasons for burning ether—for example, as a disincentive to cheating in payment channels and other smart contracts—and since the amount of ether is finite, burning ether effectively distributes the value burned to all ether holders (in proportion to the amount of ether they hold). [[tx_value_data]] === Transaction Value and Data @@ -325,7 +325,7 @@ A function selector:: The first 4 bytes of the Keccak-256 hash of the function's The function arguments:: The function's arguments, encoded according to the rules for the various elementary types defined in the ABI specification. -In <>, we defined a function for withdrawals: +In xref:02intro.asciidoc#solidity_faucet_example[solidity_faucet_example], we defined a function for withdrawals: [[withdraw_function_src]] [source,solidity] @@ -389,7 +389,7 @@ Any ether sent to the designated burn address will become unspendable and be los A contract creation transaction need only contain a data payload that contains the compiled bytecode which will create the contract. The only effect of this transaction is to create the contract. You can include an ether amount in the +value+ field if you want to set the new contract up with a starting balance, but that is entirely optional. If you send a value (ether) to the contract creation address without a data payload (no contract), then the effect is the same as sending to a burn address—there is no contract to credit, so the ether is lost. -As an example, we can create the _Faucet.sol_ contract used in <> by manually creating a transaction to the zero address with the contract in the data payload. The contract needs to be compiled into a bytecode representation. This can be done with the Solidity compiler: +As an example, we can create the _Faucet.sol_ contract used in xref:02intro.asciidoc#solidity_faucet_example[intro_chapter] by manually creating a transaction to the zero address with the contract in the data payload. The contract needs to be compiled into a bytecode representation. This can be done with the Solidity compiler: ++++
@@ -482,7 +482,7 @@ image::images/published_contract_transactions.png["Etherscan showing the transac
 [[ecdsa]]
 ==== The Elliptic Curve Digital Signature Algorithm
 
-((("digital signatures","ECDSA and")))((("Elliptic Curve Digital Signature Algorithm (ECDSA)","about")))The digital signature algorithm used in Ethereum is the _Elliptic Curve Digital Signature Algorithm_ (ECDSA). It's based on elliptic curve private–public key pairs, as described in <>.
+((("digital signatures","ECDSA and")))((("Elliptic Curve Digital Signature Algorithm (ECDSA)","about")))The digital signature algorithm used in Ethereum is the _Elliptic Curve Digital Signature Algorithm_ (ECDSA). It's based on elliptic curve private–public key pairs, as described in xref:04keys-addresses.asciidoc#elliptic_curve[elliptic_curve].
 
 A digital signature serves three purposes in Ethereum (see the following sidebar). First, the signature proves that the owner of the private key, who is by implication the owner of an Ethereum account, has _authorized_ the spending of ether, or execution of a contract. ((("non-repudiation")))Secondly, it guarantees _non-repudiation_: the proof of authorization is undeniable. Thirdly, the signature proves that the transaction data has not been and _cannot be modified_ by anyone after the transaction has been signed.
 
@@ -577,7 +577,7 @@ The signature verification algorithm takes the message (i.e., a hash of the tran
 
 ((("ephemeral private key")))The signature algorithm first generates an _ephemeral_ (temporary) private key in a cryptographically secure way. This temporary key is used in the calculation of the _r_ and _s_ values to ensure that the sender's actual private key can't be calculated by attackers watching signed transactions on the Ethereum network.
 
-As we know from <>, the ephemeral private key is used to derive the corresponding (ephemeral) public key, so we have:
+As we know from xref:04keys-addresses.asciidoc#pubkey[pubkey], the ephemeral private key is used to derive the corresponding (ephemeral) public key, so we have:
 
 * A cryptographically secure random number _q_, which is used as the ephemeral private key
 * The corresponding ephemeral public key _Q_, generated from _q_ and the elliptic curve generator point _G_
@@ -774,9 +774,9 @@ Within just a few seconds, an Ethereum transaction propagates to all the Ethereu
 [[chain_record]]
 === Recording on the Blockchain
 
-((("blockchain","recording transactions on")))((("miners")))((("mining farms")))((("transactions","recording on the blockchain")))While all the nodes in Ethereum are equal peers, some of them are operated by _miners_ and are feeding transactions and blocks to _mining farms_, which are computers with high-performance graphics processing units (GPUs). The mining computers add transactions to a candidate block and attempt to find a _proof of work_ that makes the candidate block valid. We will discuss this in more detail in <>.
+((("blockchain","recording transactions on")))((("miners")))((("mining farms")))((("transactions","recording on the blockchain")))While all the nodes in Ethereum are equal peers, some of them are operated by _miners_ and are feeding transactions and blocks to _mining farms_, which are computers with high-performance graphics processing units (GPUs). The mining computers add transactions to a candidate block and attempt to find a _proof of work_ that makes the candidate block valid. We will discuss this in more detail in xref:14consensus.asciidoc[consensus].
 
-Without going into too much detail, valid transactions will eventually be included in a block of transactions and, thus, recorded in the Ethereum blockchain. Once mined into a block, transactions also modify the state of the Ethereum singleton, either by modifying the balance of an account (in the case of a simple payment) or by invoking contracts that change their internal state. These changes are recorded alongside the transaction, in the form of a transaction _receipt_, which may also include _events_. We will examine all this in much more detail in <>.
+Without going into too much detail, valid transactions will eventually be included in a block of transactions and, thus, recorded in the Ethereum blockchain. Once mined into a block, transactions also modify the state of the Ethereum singleton, either by modifying the balance of an account (in the case of a simple payment) or by invoking contracts that change their internal state. These changes are recorded alongside the transaction, in the form of a transaction _receipt_, which may also include _events_. We will examine all this in much more detail in xref:13evm.asciidoc[evm_chapter].
 
 A transaction that has completed its journey from creation through signing by an EOA, propagation, and finally mining has changed the state of the singleton and left an indelible mark on the blockchain.
 
diff --git a/07smart-contracts-solidity.asciidoc b/07smart-contracts-solidity.asciidoc
index 1a252144c..4b24f201c 100644
--- a/07smart-contracts-solidity.asciidoc
+++ b/07smart-contracts-solidity.asciidoc
@@ -1,7 +1,7 @@
 [[smart_contracts_chapter]]
 == Smart Contracts and Solidity
 
-((("smart contracts", id="ix_07smart-contracts-solidity-asciidoc0", range="startofrange")))As we discussed in <>, there are two different types of accounts in Ethereum: ((("EOA (Externally Owned Account)","contract accounts compared to")))externally owned accounts (EOAs) and contract accounts. EOAs are controlled by users, often via software such as a wallet application that is external to the Ethereum platform. ((("contract accounts","EOAs compared to")))((("smart contracts","EOAs compared to")))In contrast, contract accounts are controlled by program code (also commonly referred to as “smart contracts”) that is executed by the Ethereum Virtual Machine. In short, EOAs are simple accounts without any associated code or data storage, whereas contract accounts have both associated code and data storage. EOAs are controlled by transactions created and cryptographically signed with a private key in the "real world" external to and independent of the protocol, whereas contract accounts do not have private keys and so "control themselves" in the predetermined way prescribed by their smart contract code. Both types of accounts are identified by an Ethereum address. In this chapter, we will discuss contract accounts and the program code that controls them.
+((("smart contracts", id="ix_07smart-contracts-solidity-asciidoc0", range="startofrange")))As we discussed in xref:02intro.asciidoc#EOA_contracts[intro_chapter], there are two different types of accounts in Ethereum: ((("EOA (Externally Owned Account)","contract accounts compared to")))externally owned accounts (EOAs) and contract accounts. EOAs are controlled by users, often via software such as a wallet application that is external to the Ethereum platform. ((("contract accounts","EOAs compared to")))((("smart contracts","EOAs compared to")))In contrast, contract accounts are controlled by program code (also commonly referred to as “smart contracts”) that is executed by the Ethereum Virtual Machine. In short, EOAs are simple accounts without any associated code or data storage, whereas contract accounts have both associated code and data storage. EOAs are controlled by transactions created and cryptographically signed with a private key in the "real world" external to and independent of the protocol, whereas contract accounts do not have private keys and so "control themselves" in the predetermined way prescribed by their smart contract code. Both types of accounts are identified by an Ethereum address. In this chapter, we will discuss contract accounts and the program code that controls them.
 
 [[smart_contracts_definition]]
 === What Is a Smart Contract?
@@ -28,7 +28,7 @@ The EVM runs as a local instance on every Ethereum node, but because all instanc
 [[smart_contract_lifecycle]]
 === Life Cycle of a Smart Contract
 
-((("smart contracts","life cycle of")))Smart contracts are typically written in a high-level language, such as Solidity. But in order to run, they must be compiled to the low-level bytecode that runs in the EVM. Once compiled, they are deployed on the Ethereum platform using a special _contract creation_ transaction, which is identified as such by being sent to the special contract creation address, namely +0x0+ (see <>). Each contract is identified by an Ethereum address, which is derived from the contract creation transaction as a function of the originating account and nonce. The Ethereum address of a contract can be used in a transaction as the recipient, sending funds to the contract or calling one of the contract’s functions. Note that, unlike with EOAs, there are no keys associated with an account created for a new smart contract. As the contract creator, you don't get any special privileges at the protocol level (although you can explicitly code them into the smart contract). You certainly don't receive the private key for the contract account, which in fact does not exist—we can say that smart contract accounts own themselves.
+((("smart contracts","life cycle of")))Smart contracts are typically written in a high-level language, such as Solidity. But in order to run, they must be compiled to the low-level bytecode that runs in the EVM. Once compiled, they are deployed on the Ethereum platform using a special _contract creation_ transaction, which is identified as such by being sent to the special contract creation address, namely +0x0+ (see xref:06transactions.asciidoc#contract_reg[contract_reg]). Each contract is identified by an Ethereum address, which is derived from the contract creation transaction as a function of the originating account and nonce. The Ethereum address of a contract can be used in a transaction as the recipient, sending funds to the contract or calling one of the contract’s functions. Note that, unlike with EOAs, there are no keys associated with an account created for a new smart contract. As the contract creator, you don't get any special privileges at the protocol level (although you can explicitly code them into the smart contract). You certainly don't receive the private key for the contract account, which in fact does not exist—we can say that smart contract accounts own themselves.
 
 ((("transactions","smart contracts and")))Importantly, contracts _only run if they are called by a transaction_. All smart contracts in Ethereum are executed, ultimately, because of a transaction initiated from an EOA. A contract can call another contract that can call another contract, and so on, but the first contract in such a chain of execution will always have been called by a transaction from an EOA. Contracts never run “on their own” or “in the background.” Contracts effectively lie dormant until a transaction triggers execution, either directly or indirectly as part of a chain of contract calls. It is also worth noting that smart contracts are not executed "in parallel" in any sense—the Ethereum world computer can be considered to be a single-threaded machine.
 
@@ -39,7 +39,7 @@ The EVM runs as a local instance on every Ethereum node, but because all instanc
 [[high_level_languages]]
 === Introduction to Ethereum High-Level Languages
 
-((("EVM (Ethereum Virtual Machine)","and Ethereum high-level languages", id="ix_07smart-contracts-solidity-asciidoc1", range="startofrange")))((("smart contracts","and Ethereum high-level languages", id="ix_07smart-contracts-solidity-asciidoc2", range="startofrange")))The EVM is a virtual machine that runs a ((("EVM bytecode")))special form of code called _EVM bytecode_, analogous to your computer's CPU, which runs machine code such as x86_64. We will examine the operation and language of the EVM in much more detail in <>. In this section we will look at how smart contracts are written to run on the EVM.
+((("EVM (Ethereum Virtual Machine)","and Ethereum high-level languages", id="ix_07smart-contracts-solidity-asciidoc1", range="startofrange")))((("smart contracts","and Ethereum high-level languages", id="ix_07smart-contracts-solidity-asciidoc2", range="startofrange")))The EVM is a virtual machine that runs a ((("EVM bytecode")))special form of code called _EVM bytecode_, analogous to your computer's CPU, which runs machine code such as x86_64. We will examine the operation and language of the EVM in much more detail in xref:13evm.asciidoc#evm_chapter[evm_chapter]. In this section we will look at how smart contracts are written to run on the EVM.
 
 While it is possible to program smart contracts directly in bytecode, EVM bytecode is rather unwieldy and very difficult for programmers to read and understand. Instead, most Ethereum developers use a high-level language to write programs, and a compiler to convert them into bytecode.
 
@@ -72,7 +72,7 @@ As you can see, there are many languages to choose from. However, of all of thes
 
 The main "product" of the Solidity project is the Solidity compiler, +solc+, which converts programs written in the Solidity language to EVM bytecode. The project also manages the important application binary interface (ABI) standard for Ethereum smart contracts, which we will explore in detail in this chapter. Each version of the Solidity compiler corresponds to and compiles a specific version of the Solidity pass:[language].
 
-To get started, we will download a binary executable of the Solidity compiler. Then we will develop and compile a simple contract, following on from the example we started with in <>.
+To get started, we will download a binary executable of the Solidity compiler. Then we will develop and compile a simple contract, following on from the example we started with in xref:02intro.asciidoc#solidity_faucet_example[intro_chapter].
 
 ==== Selecting a Version of Solidity
 
@@ -82,7 +82,7 @@ At the time of writing, Solidity is at version 0.6.4.  The rules for major versi
 
 The 0.5 major version release of Solidity is anticipated imminently.
 
-As you saw in <>, your Solidity programs can contain a pragma directive that specifies the minimum and maximum versions of Solidity that it is compatible with, and can be used to compile your contract.
+As you saw in xref:02intro.asciidoc#solidity_faucet_example[intro_chapter], your Solidity programs can contain a pragma directive that specifies the minimum and maximum versions of Solidity that it is compatible with, and can be used to compile your contract.
 
 Since Solidity is rapidly evolving, it is often better to install the latest release.
 
@@ -124,7 +124,7 @@ Use the tools that make you productive. In the end, Solidity programs are just p
 
 ==== Writing a Simple Solidity Program
 
-((("Solidity","writing a simple program in")))In <>, we wrote our first Solidity program.  When we first built the +Faucet+ contract, we used the Remix IDE to compile and deploy the contract. In this section, we will revisit, improve, and embellish +Faucet+.
+((("Solidity","writing a simple program in")))In xref:02intro.asciidoc#solidity_faucet_example[intro_chapter], we wrote our first Solidity program.  When we first built the +Faucet+ contract, we used the Remix IDE to compile and deploy the contract. In this section, we will revisit, improve, and embellish +Faucet+.
 
 Our first attempt looked like <>.
 
@@ -216,7 +216,7 @@ Adding a version pragma is a best practice, as it avoids problems with mismatche
 
 === Programming with Solidity
 
-((("Solidity","programming with", id="ix_07smart-contracts-solidity-asciidoc10", range="startofrange")))In this section, we will look at some of the capabilities of the Solidity language. As we mentioned in <>, our first contract example was very simple and also flawed in various ways. We'll gradually improve it here, while exploring how to use Solidity. This won't be a comprehensive Solidity tutorial, however, as Solidity is quite complex and rapidly evolving. We'll cover the basics and give you enough of a foundation to be able to explore the rest on your own. The documentation for Solidity can be found
+((("Solidity","programming with", id="ix_07smart-contracts-solidity-asciidoc10", range="startofrange")))In this section, we will look at some of the capabilities of the Solidity language. As we mentioned in xref:02intro.asciidoc#solidity_faucet_example[intro_chapter], our first contract example was very simple and also flawed in various ways. We'll gradually improve it here, while exploring how to use Solidity. This won't be a comprehensive Solidity tutorial, however, as Solidity is quite complex and rapidly evolving. We'll cover the basics and give you enough of a foundation to be able to explore the rest on your own. The documentation for Solidity can be found
 https://solidity.readthedocs.io/en/latest/[on the project website].
 
 ==== Data Types
@@ -435,7 +435,7 @@ Note that you must explicitly add this command to your contract if you want it t
 
 ==== Adding a Constructor and selfdestruct to Our Faucet Example
 
-((("constructor function","adding to faucet example")))((("Faucet.sol contract (test example)","adding constructor and selfdestruct to")))((("Solidity","adding constructor/selfdestruct to faucet example")))The +Faucet+ example contract we introduced in <> does not have any constructor or +selfdestruct+ functions. It is an eternal contract that cannot be deleted. Let's change that, by adding a constructor and +selfdestruct+ function. We probably want +selfdestruct+ to be callable _only_ by the EOA that originally created the contract. By convention, this is usually stored in an address variable called +owner+. Our constructor sets the +owner+ variable, and the +selfdestruct+ function will first check that the owner called it directly.
+((("constructor function","adding to faucet example")))((("Faucet.sol contract (test example)","adding constructor and selfdestruct to")))((("Solidity","adding constructor/selfdestruct to faucet example")))The +Faucet+ example contract we introduced in xref:02intro.asciidoc#solidity_faucet_example[intro_chapter] does not have any constructor or +selfdestruct+ functions. It is an eternal contract that cannot be deleted. Let's change that, by adding a constructor and +selfdestruct+ function. We probably want +selfdestruct+ to be callable _only_ by the EOA that originally created the contract. By convention, this is usually stored in an address variable called +owner+. Our constructor sets the +owner+ variable, and the +selfdestruct+ function will first check that the owner called it directly.
 
 First, our constructor:
 
@@ -633,7 +633,7 @@ Additional error-checking code like this will increase gas consumption slightly,
 [[solidity_events]]
 ==== Events
 
-((("events","Solidity", id="ix_07smart-contracts-solidity-asciidoc18", range="startofrange")))((("Solidity","event objects", id="ix_07smart-contracts-solidity-asciidoc19", range="startofrange")))When ((("transaction receipt")))a transaction completes (successfully or not), it produces a _transaction receipt_, as we will see in <>. The transaction receipt contains _log_ entries that provide information about the actions that occurred during the execution of the transaction. _Events_ are the Solidity high-level objects that are used to construct these logs.
+((("events","Solidity", id="ix_07smart-contracts-solidity-asciidoc18", range="startofrange")))((("Solidity","event objects", id="ix_07smart-contracts-solidity-asciidoc19", range="startofrange")))When ((("transaction receipt")))a transaction completes (successfully or not), it produces a _transaction receipt_, as we will see in xref:13evm.asciidoc#evm_chapter[evm_chapter]. The transaction receipt contains _log_ entries that provide information about the actions that occurred during the execution of the transaction. _Events_ are the Solidity high-level objects that are used to construct these logs.
 
 Events are especially useful for light clients and DApp services, which can "watch" for specific events and report them to the user interface, or make a change in the state of the application to reflect an event in an underlying contract.
 
@@ -684,7 +684,7 @@ include::code/Solidity/Faucet8.sol[]
 
 ((("events","catching")))((("Faucet.sol contract (test example)","catching events")))OK, so we've set up our contract to emit events. How do we see the results of a transaction and "catch" the events? The web3.js library provides a data structure that contains a transaction's logs. Within those we can see the events generated by the transaction.
 
-((("Truffle","running test transaction with")))Let's use +truffle+ to run a test transaction on the revised +Faucet+ contract. Follow the instructions in <> to set up a project directory and compile the pass:[Faucet] code. The source code can be found in https://github.com/ethereumbook/ethereumbook[the book's GitHub repository] under _code/truffle/FaucetEvents_.
+((("Truffle","running test transaction with")))Let's use +truffle+ to run a test transaction on the revised +Faucet+ contract. Follow the instructions in xref:appdx-dev-tools.asciidoc#truffle[truffle] to set up a project directory and compile the pass:[Faucet] code. The source code can be found in https://github.com/ethereumbook/ethereumbook[the book's GitHub repository] under _code/truffle/FaucetEvents_.
 
 ++++
 
@@ -845,7 +845,7 @@ contract Token is Mortal {
 }
 ----
 
-((("blind calls")))As you can see, this type of +call+ is a _blind_ call into a function, very much like constructing a raw transaction, only from within a contract's context. ((("reentrancy attacks","blind calls and")))It can expose your contract to a number of security risks, most importantly _reentrancy_, which we will discuss in more detail in <>. The +call+ function will return +false+ if there is a problem, so you can evaluate the return value for error handling:
+((("blind calls")))As you can see, this type of +call+ is a _blind_ call into a function, very much like constructing a raw transaction, only from within a contract's context. ((("reentrancy attacks","blind calls and")))It can expose your contract to a number of security risks, most importantly _reentrancy_, which we will discuss in more detail in xref:09smart-contracts-security.asciidoc#reentrancy_security[reentrancy_security]. The +call+ function will return +false+ if there is a problem, so you can evaluate the return value for error handling:
 
 [source,solidity]
 ----
@@ -953,7 +953,7 @@ The next two calls, using the low-level +call+ and +delegatecall+, verify our ex
 [[gas_sec]]
 === Gas Considerations
 
-((("gas","conserving", id="ix_07smart-contracts-solidity-asciidoc24", range="startofrange")))((("smart contracts","gas considerations", id="ix_07smart-contracts-solidity-asciidoc25", range="startofrange")))((("Solidity","gas considerations", id="ix_07smart-contracts-solidity-asciidoc26", range="startofrange")))Gas, described in more detail in <>, is an incredibly important consideration in smart contract programming. Gas is a resource constraining the maximum amount of computation that Ethereum will allow a transaction to consume. If the gas limit is exceeded during computation, the following series of events occurs:
+((("gas","conserving", id="ix_07smart-contracts-solidity-asciidoc24", range="startofrange")))((("smart contracts","gas considerations", id="ix_07smart-contracts-solidity-asciidoc25", range="startofrange")))((("Solidity","gas considerations", id="ix_07smart-contracts-solidity-asciidoc26", range="startofrange")))Gas, described in more detail in xref:13evm.asciidoc#gas[gas], is an incredibly important consideration in smart contract programming. Gas is a resource constraining the maximum amount of computation that Ethereum will allow a transaction to consume. If the gas limit is exceeded during computation, the following series of events occurs:
 
 * An "out of gas" exception is thrown.
 * The state of the contract prior to execution is restored (reverted).
@@ -1046,4 +1046,4 @@ It is recommended that you evaluate the gas cost of functions as part of your de
 
 === Conclusions
 
-In this chapter we started working with smart contracts in detail and explored the Solidity contract programming language.(((range="endofrange", startref="ix_07smart-contracts-solidity-asciidoc4")))(((range="endofrange", startref="ix_07smart-contracts-solidity-asciidoc3"))) We took a simple example contract, _Faucet.sol_, and gradually improved it and made it more complex, using it to explore various aspects of the Solidity language. In <> we will work with Vyper, another contract-oriented programming language. We will compare Vyper to Solidity, showing some of the differences in the design of these two languages and deepening our understanding of smart contract programming.(((range="endofrange", startref="ix_07smart-contracts-solidity-asciidoc0")))
+In this chapter we started working with smart contracts in detail and explored the Solidity contract programming language.(((range="endofrange", startref="ix_07smart-contracts-solidity-asciidoc4")))(((range="endofrange", startref="ix_07smart-contracts-solidity-asciidoc3"))) We took a simple example contract, _Faucet.sol_, and gradually improved it and made it more complex, using it to explore various aspects of the Solidity language. In xref:08smart-contracts-vyper.asciidoc[vyper_chap] we will work with Vyper, another contract-oriented programming language. We will compare Vyper to Solidity, showing some of the differences in the design of these two languages and deepening our understanding of smart contract programming.(((range="endofrange", startref="ix_07smart-contracts-solidity-asciidoc0")))
diff --git a/09smart-contracts-security.asciidoc b/09smart-contracts-security.asciidoc
index 4016d3479..d4e20b219 100644
--- a/09smart-contracts-security.asciidoc
+++ b/09smart-contracts-security.asciidoc
@@ -253,7 +253,7 @@ occurred in the early development of Ethereum. At the time, the contract
 held over $150 million. Reentrancy played a major role in the
 attack, which ultimately led to the hard fork that created Ethereum
 Classic (ETC). For a good analysis of the DAO exploit, see
-http://bit.ly/2EQaLCI. More information on Ethereum's fork history, the DAO hack timeline, and the birth of ETC in a hard fork can be found in <>.(((range="endofrange", startref="ix_09smart-contracts-security-asciidoc4")))(((range="endofrange", startref="ix_09smart-contracts-security-asciidoc3")))
+http://bit.ly/2EQaLCI. More information on Ethereum's fork history, the DAO hack timeline, and the birth of ETC in a hard fork can be found in xref:appdx-standards-eip-erc.asciidoc#ethereum_standards[ethereum_standards].(((range="endofrange", startref="ix_09smart-contracts-security-asciidoc4")))(((range="endofrange", startref="ix_09smart-contracts-security-asciidoc3")))
 
 === Arithmetic Over/Underflows
 
diff --git a/10tokens.asciidoc b/10tokens.asciidoc
index 2084a01f3..5a96397ae 100644
--- a/10tokens.asciidoc
+++ b/10tokens.asciidoc
@@ -246,7 +246,7 @@ https://bit.ly/2xPYck6[OpenZeppelin StandardToken]:: This implementation is ERC2
 [[METoken_example]]
 ==== Launching Our Own ERC20 Token
 
-((("ERC20 token standard","METoken creation/launch example", id="ix_10tokens-asciidoc9", range="startofrange")))((("METoken (Mastering Ethereum Token)","creation/launch example", id="ix_10tokens-asciidoc10", range="startofrange")))Let's create and launch our own token. For this example, we will use the Truffle framework. The example assumes you have already installed +truffle+ and configured it, and are familiar with its basic operation (for details, see <>).
+((("ERC20 token standard","METoken creation/launch example", id="ix_10tokens-asciidoc9", range="startofrange")))((("METoken (Mastering Ethereum Token)","creation/launch example", id="ix_10tokens-asciidoc10", range="startofrange")))Let's create and launch our own token. For this example, we will use the Truffle framework. The example assumes you have already installed +truffle+ and configured it, and are familiar with its basic operation (for details, see xref:appdx-dev-tools.asciidoc#truffle[truffle]).
 
 We will call our token "Mastering Ethereum Token,” with the symbol "MET."
 
@@ -980,7 +980,7 @@ If you use an existing implementation you can also extend it. Again, however, be
 
 [TIP]
 ====
-Standards and implementation choices are important parts of overall secure smart contract design, but they're not the only considerations. See <>.(((range="endofrange", startref="ix_10tokens-asciidoc25")))(((range="endofrange", startref="ix_10tokens-asciidoc24")))
+Standards and implementation choices are important parts of overall secure smart contract design, but they're not the only considerations. See xref:09smart-contracts-security.asciidoc#smart_contract_security[smart_contract_security].(((range="endofrange", startref="ix_10tokens-asciidoc25")))(((range="endofrange", startref="ix_10tokens-asciidoc24")))
 ====
 
 
@@ -1020,4 +1020,4 @@ The trick is to separate the long-term vision and impact of this technology, whi
 
 === Conclusions
 
-Tokens are a very powerful concept in Ethereum and can form the basis of many important decentralized applications. In this chapter we looked at the different types of tokens and token standards, and you built your first token and related application. We will revisit tokens again in <>, where you will use a non-fungible token as the basis for an auction DApp.(((range="endofrange", startref="ix_10tokens-asciidoc0")))
+Tokens are a very powerful concept in Ethereum and can form the basis of many important decentralized applications. In this chapter we looked at the different types of tokens and token standards, and you built your first token and related application. We will revisit tokens again in xref:12dapps.asciidoc#decentralized_applications_chap[decentralized_applications_chap], where you will use a non-fungible token as the basis for an auction DApp.(((range="endofrange", startref="ix_10tokens-asciidoc0")))
diff --git a/11oracles.asciidoc b/11oracles.asciidoc
index 0e6b9bca4..bdd770940 100644
--- a/11oracles.asciidoc
+++ b/11oracles.asciidoc
@@ -91,7 +91,7 @@ Publish–subscribe is a pattern where publishers (in this context, oracles) do
 
 ((("oracles","computation oracles", id="ix_11oracles-asciidoc2", range="startofrange")))So far, we have only discussed oracles in the context of requesting and delivering data. However, oracles can also be used to perform arbitrary computation, a function that can be especially useful given Ethereum’s inherent block gas limit and comparatively expensive computation costs. Rather than just relaying the results of a query, computation oracles can be used to perform computation on a set of inputs and return a calculated result that may have been infeasible to calculate on-chain. For example, one might use a computation oracle to perform a computationally intensive regression calculation in order to estimate the yield of a bond contract.
 
-((("Oraclize")))If you are willing to trust a centralized but auditable service, you can go again to Oraclize. They provide a service that allows decentralized applications to request the output of a computation performed in a sandboxed AWS virtual machine. The AWS instance creates an executable container from a user-configured Dockerfile packed in an archive that is uploaded to the Inter-Planetary File System (IPFS; see <>). On request, Oraclize retrieves this archive using its hash and then initializes and executes the Docker container on AWS, passing any arguments that are provided to the application as environment variables. The containerized application performs the calculation, subject to a time constraint, and writes the result to standard output, where it can be retrieved by Oraclize and returned to the decentralized application. Oraclize currently offers this service on an auditable t2.micro AWS instance, so if the computation is of some nontrivial value, it is possible to check that the correct Docker container was executed. Nonetheless, this is not a truly decentralized solution.
+((("Oraclize")))If you are willing to trust a centralized but auditable service, you can go again to Oraclize. They provide a service that allows decentralized applications to request the output of a computation performed in a sandboxed AWS virtual machine. The AWS instance creates an executable container from a user-configured Dockerfile packed in an archive that is uploaded to the Inter-Planetary File System (IPFS; see xref:12dapps.asciidoc#data_storage_sec[data_storage_sec]). On request, Oraclize retrieves this archive using its hash and then initializes and executes the Docker container on AWS, passing any arguments that are provided to the application as environment variables. The containerized application performs the calculation, subject to a time constraint, and writes the result to standard output, where it can be retrieved by Oraclize and returned to the decentralized application. Oraclize currently offers this service on an auditable t2.micro AWS instance, so if the computation is of some nontrivial value, it is possible to check that the correct Docker container was executed. Nonetheless, this is not a truly decentralized solution.
 
 ((("cryplet")))The concept of a 'cryptlet' as a standard for verifiable oracle truths has been formalized as part of Microsoft's wider ESC Framework.  Cryptlets execute within an encrypted capsule that abstracts away the infrastructure, such as I/O, and has the CryptoDelegate attached so incoming and outgoing messages are signed, validated, and proven automatically.  Cryptlets support distributed transactions so that contract logic can take on complex multistep, multiblockchain, and external system transactions in an ACID manner.  This allows developers to create portable, isolated, and private resolutions of the truth for use in smart contracts. Cryptlets follow the format shown here:
 
diff --git a/12dapps.asciidoc b/12dapps.asciidoc
index f92a3581f..358b0efcc 100644
--- a/12dapps.asciidoc
+++ b/12dapps.asciidoc
@@ -56,7 +56,7 @@ The second major consideration of smart contract architecture design is DApp siz
 [[front_end_web_ui_cec]]
 ==== Frontend (Web User Interface)
 
-((("DApps (decentralized applications)","frontend (web user interface)")))((("user interface, as DApp frontend")))((("web user interface, as DApp frontend")))Unlike the business logic of the DApp, which requires a developer to understand the EVM and new languages such as Solidity, the client-side interface of a DApp can use standard web technologies (HTML, CSS, JavaScript, etc.). This allows a traditional web developer to use familiar tools, libraries, and frameworks. Interactions with Ethereum, such as signing messages, sending transactions, and managing keys, are often conducted through the web browser, via an extension such as MetaMask (see <>).
+((("DApps (decentralized applications)","frontend (web user interface)")))((("user interface, as DApp frontend")))((("web user interface, as DApp frontend")))Unlike the business logic of the DApp, which requires a developer to understand the EVM and new languages such as Solidity, the client-side interface of a DApp can use standard web technologies (HTML, CSS, JavaScript, etc.). This allows a traditional web developer to use familiar tools, libraries, and frameworks. Interactions with Ethereum, such as signing messages, sending transactions, and managing keys, are often conducted through the web browser, via an extension such as MetaMask (see xref:02intro.asciidoc#installing_MetaMask[intro_chapter]).
 
 Although it is possible to create a mobile DApp as well, currently there are few resources to help create mobile DApp frontends, mainly due to the lack of mobile clients that can serve as a light client with key-management functionality.
 
@@ -124,7 +124,7 @@ You can find the source code for the auction DApp http://bit.ly/2DcmjyA[in the b
 
 ((("Auction DApp","backend smart contracts", id="ix_12dapps-asciidoc4", range="startofrange")))((("smart contracts","as DApp backend", id="ix_12dapps-asciidoc5", range="startofrange")))Our Auction DApp example is supported by two smart contracts that we need to deploy on an Ethereum blockchain in order to support the application: pass:[AuctionRepository] and +DeedRepository+.
 
-Let's start by looking at +DeedRepository+, shown in <>. This contract is an ERC721-compatible non-fungible token (see <>).
+Let's start by looking at +DeedRepository+, shown in <>. This contract is an ERC721-compatible non-fungible token (see xref:10tokens.asciidoc#erc721[erc721]).
 
 [[deed_repository_code]]
 .DeedRepository.sol: An ERC721 deed token for use in an auction
@@ -213,7 +213,7 @@ If you read through the two smart contracts of the Auction DApp you will notice
 
 This is a deliberate choice to decentralize the governance of the DApp and relinquish any control once it has been deployed. Some DApps, by comparison, have one or more privileged accounts with special capabilities, such as the ability to terminate the DApp contract, to override or change its configuration, or to "veto" certain operations. Usually, these governance functions are introduced in the DApp in order to avoid unknown problems that might arise due to a bug.
 
-The issue of governance is a particularly difficult one to solve, as it represents a double-edged sword. On the one side, privileged accounts are dangerous; if compromised, they can subvert the security of the DApp. On the other side, without any privileged account, there are no recovery options if a bug is found. We have seen both of these risks manifest in Ethereum DApps. ((("DAO (Decentralized Autonomous Organization)","reentrancy attack")))In the case of The DAO (<> and <>), there were some privileged accounts called the "curators," but they were very limited in their capabilities. Those accounts were not able to override the DAO attacker's withdrawal of the funds. In a more recent case, the decentralized exchange Bancor experienced a massive theft because a privileged management account was compromised. Turns out, Bancor was not as decentralized as initially assumed.
+The issue of governance is a particularly difficult one to solve, as it represents a double-edged sword. On the one side, privileged accounts are dangerous; if compromised, they can subvert the security of the DApp. On the other side, without any privileged account, there are no recovery options if a bug is found. We have seen both of these risks manifest in Ethereum DApps. ((("DAO (Decentralized Autonomous Organization)","reentrancy attack")))In the case of The DAO (xref:09smart-contracts-security.asciidoc#real_world_example_the_dao[real_world_example_the_dao] and xref:appdx-forks-history.asciidoc#ethereum_fork_history[ethereum_fork_history]), there were some privileged accounts called the "curators," but they were very limited in their capabilities. Those accounts were not able to override the DAO attacker's withdrawal of the funds. In a more recent case, the decentralized exchange Bancor experienced a massive theft because a privileged management account was compromised. Turns out, Bancor was not as decentralized as initially assumed.
 
 When building a DApp, you have to decide if you want to make the smart contracts truly independent, launching them and then having no control, or create privileged accounts and run the risk of those being compromised. Either choice carries risk, but in the long run, true DApps cannot have specialized access for privileged accounts—that's not decentralized.(((range="endofrange", startref="ix_12dapps-asciidoc5")))(((range="endofrange", startref="ix_12dapps-asciidoc4")))
 
diff --git a/13evm.asciidoc b/13evm.asciidoc
index 79cf492ee..89902afa4 100644
--- a/13evm.asciidoc
+++ b/13evm.asciidoc
@@ -51,7 +51,7 @@ put back on the top of the stack.
 
 [NOTE]
 ====
-A complete list of opcodes and their corresponding gas cost can be found in <>.
+A complete list of opcodes and their corresponding gas cost can be found in xref:appdx-evm-opcodes-gas.asciidoc#evm_opcodes[evm_opcodes].
 ====
 
 The available opcodes can be divided into the following categories:
@@ -210,7 +210,7 @@ Note that because a smart contract can itself effectively initiate transactions,
 ==== Compiling Solidity to EVM Bytecode
 
 [[solc_help]]
-((("EVM (Ethereum Virtual Machine)","compiling Solidity to EVM bytecode", id="ix_13evm-asciidoc4", range="startofrange")))((("EVM bytecode","compiling source file to", id="ix_13evm-asciidoc5", range="startofrange")))((("Solidity","compiling source file to EVM bytecode", id="ix_13evm-asciidoc6", range="startofrange")))Compiling a Solidity source file to EVM bytecode can be accomplished via several methods. In <> we used the online Remix compiler. In this chapter, we will use the +solc+ executable at the command line. For a list of options, run the following pass:[command]:
+((("EVM (Ethereum Virtual Machine)","compiling Solidity to EVM bytecode", id="ix_13evm-asciidoc4", range="startofrange")))((("EVM bytecode","compiling source file to", id="ix_13evm-asciidoc5", range="startofrange")))((("Solidity","compiling source file to EVM bytecode", id="ix_13evm-asciidoc6", range="startofrange")))Compiling a Solidity source file to EVM bytecode can be accomplished via several methods. In xref:02intro.asciidoc[intro_chapter] we used the online Remix compiler. In this chapter, we will use the +solc+ executable at the command line. For a list of options, run the following pass:[command]:
 
 ++++
 
@@ -636,7 +636,7 @@ Although the transaction was unsuccessful, the sender will be charged a transact
 
 ==== Gas Accounting Considerations
 
-((("EVM (Ethereum Virtual Machine)","gas accounting considerations")))((("gas","accounting considerations")))The relative gas costs of the various operations that can be performed by the EVM have been carefully chosen to best protect the Ethereum blockchain from attack. You can see a detailed table of gas costs for different EVM opcodes in <>.
+((("EVM (Ethereum Virtual Machine)","gas accounting considerations")))((("gas","accounting considerations")))The relative gas costs of the various operations that can be performed by the EVM have been carefully chosen to best protect the Ethereum blockchain from attack. You can see a detailed table of gas costs for different EVM opcodes in xref:appdx-evm-opcodes-gas.asciidoc#evm_opcodes_table[evm_opcodes_table].
 
 More computationally intensive operations cost more gas. For example, executing the +SHA3+ function is 10 times more expensive (30 gas) than the +ADD+ operation (3 gas). More importantly, some operations, such as +EXP+, require an additional payment based on the size of the operand. There is also a gas cost to using EVM memory and for storing data in a contract's on-chain storage.
 
@@ -690,4 +690,4 @@ The miners on the network collectively decide the block gas limit. Individuals w
 
 === Conclusions
 
-In this chapter we have explored the Ethereum Virtual Machine, tracing the execution of various smart contracts and looking at how the EVM executes bytecode. We also looked at gas, the EVM's accounting mechanism, and saw how it solves the halting problem and protects Ethereum from denial-of-service attacks. Next, in <>, we will look at the mechanism used by Ethereum to achieve decentralized consensus.(((range="endofrange", startref="ix_13evm-asciidoc0")))
+In this chapter we have explored the Ethereum Virtual Machine, tracing the execution of various smart contracts and looking at how the EVM executes bytecode. We also looked at gas, the EVM's accounting mechanism, and saw how it solves the halting problem and protects Ethereum from denial-of-service attacks. Next, in xref:14consensus.asciidoc#consensus[consensus], we will look at the mechanism used by Ethereum to achieve decentralized consensus.(((range="endofrange", startref="ix_13evm-asciidoc0")))
diff --git a/appdx-dev-tools.asciidoc b/appdx-dev-tools.asciidoc
index f4a2e2c76..4c5d93036 100644
--- a/appdx-dev-tools.asciidoc
+++ b/appdx-dev-tools.asciidoc
@@ -176,7 +176,7 @@ $ truffle unbox BOX_NAME
 [[truffle_project_directory]]
 ===== Creating a Truffle project directory
 
-((("Truffle","creating a project directory", id="ix_appdx-dev-tools-asciidoc3", range="startofrange")))For each project where you will use +Truffle+, create a project directory and initialize +Truffle+ within that directory. +Truffle+ will create the necessary directory structure inside your project directory. It's customary to give the project directory a name that describes the project. For this example, we will use +Truffle+ to deploy our +Faucet+ contract from <>, and therefore we will name the project folder __Faucet__:
+((("Truffle","creating a project directory", id="ix_appdx-dev-tools-asciidoc3", range="startofrange")))For each project where you will use +Truffle+, create a project directory and initialize +Truffle+ within that directory. +Truffle+ will create the necessary directory structure inside your project directory. It's customary to give the project directory a name that describes the project. For this example, we will use +Truffle+ to deploy our +Faucet+ contract from xref:02intro.asciidoc#simple_contract_example[simple_contract_example], and therefore we will name the project folder __Faucet__:
 
 ++++
 
@@ -280,7 +280,7 @@ In following sections, we will configure additional networks for +Truffle+ to us
 
 ((("smart contracts","using Truffle to deploy")))((("Truffle","contract deployment with")))We now have a basic working directory for our _Faucet_ project, and we have +Truffle+ and its dependencies configured. Contracts go in the _contracts_ subdirectory of our project. The directory already contains a "helper" contract, _Migrations.sol_, which manages contract upgrades for us. We'll examine the use of _Migrations.sol_ in the next section.
 
-Let's copy the _Faucet.sol_ contract (from <>) into the _contracts_ subdirectory, so that the project directory looks like this:
+Let's copy the _Faucet.sol_ contract (from xref:02intro.asciidoc#solidity_faucet_example[solidity_faucet_example]) into the _contracts_ subdirectory, so that the project directory looks like this:
 
 ----
 Faucet
@@ -420,7 +420,7 @@ truffle(localnode)>
 
++++ -web3.js is a large JavaScript library that offers a comprehensive interface to the Ethereum system, via a provider such as a local client. We will examine web3.js in more detail in <>. Now let's try to interact with our contracts: +web3.js is a large JavaScript library that offers a comprehensive interface to the Ethereum system, via a provider such as a local client. We will examine web3.js in more detail in xref:appdx-web3js-tutorial.asciidoc#web3js_tutorial[web3js_tutorial]. Now let's try to interact with our contracts: ++++
diff --git a/appdx-forks-history.asciidoc b/appdx-forks-history.asciidoc
index e5e90b746..2e73c7bf8 100644
--- a/appdx-forks-history.asciidoc
+++ b/appdx-forks-history.asciidoc
@@ -27,7 +27,7 @@ Simultaneously, an assemblage of volunteers calling themselves the Robin Hood Gr
 
 [[dao_reentrancy_bug_technicals]]
 ==== Technical Details
-((("reentrancy bug","technical details")))While a more detailed and thorough explanation of the bug is given by http://bit.ly/2EQaLCI[Phil Daian], the short explanation is that a crucial function in the DAO had two lines of code in the wrong order, meaning that the attacker could have requests to withdraw ether acted upon repeatedly, before the check of whether the attacker was entitled to the withdrawal was completed. This type of vulnerability is described in <>.
+((("reentrancy bug","technical details")))While a more detailed and thorough explanation of the bug is given by http://bit.ly/2EQaLCI[Phil Daian], the short explanation is that a crucial function in the DAO had two lines of code in the wrong order, meaning that the attacker could have requests to withdraw ether acted upon repeatedly, before the check of whether the attacker was entitled to the withdrawal was completed. This type of vulnerability is described in xref:09smart-contracts-security.asciidoc#reentrancy_security[reentrancy_security].
 
 [[dao_reentrancy_bug_attack_flow]]
 ==== Attack Flow
diff --git a/preface.asciidoc b/preface.asciidoc
index 41c1e9a03..a323a477b 100644
--- a/preface.asciidoc
+++ b/preface.asciidoc
@@ -15,7 +15,7 @@ Finally, in May 2016, Gavin and Andreas were both coincidentally in the same cit
 
 === How to Use This Book
 
-The book is intended to serve both as a reference manual and as a cover-to-cover exploration of Ethereum. The first two chapters offer a gentle introduction, suitable for novice users, and the examples in those chapters can be completed by anyone with a bit of technical skill. Those two chapters will give you a good grasp of the basics and allow you to use the fundamental tools of Ethereum. <> and beyond are intended mainly for programmers and include many technical topics and programming examples.
+The book is intended to serve both as a reference manual and as a cover-to-cover exploration of Ethereum. The first two chapters offer a gentle introduction, suitable for novice users, and the examples in those chapters can be completed by anyone with a bit of technical skill. Those two chapters will give you a good grasp of the basics and allow you to use the fundamental tools of Ethereum. xref:03clients.asciidoc#ethereum_clients_chapter[ethereum_clients_chapter] and beyond are intended mainly for programmers and include many technical topics and programming examples.
 
 To serve as both a reference manual and a cover-to-cover narrative about Ethereum, the book inevitably contains some duplication. Some topics, such as _gas_, have to be introduced early enough for the rest of the topics to make sense, but are also examined in depth in their own sections.