mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Update documentation.
This commit is contained in:
@@ -90,7 +90,7 @@ of votes.
|
||||
// If the first argument of `require` evaluates
|
||||
// to `false`, execution terminates and all
|
||||
// changes to the state and to Ether balances
|
||||
// are reverted.
|
||||
// are reverted.
|
||||
// This used to consume all gas in old EVM versions, but
|
||||
// not anymore.
|
||||
// It is often a good idea to use `require` to check if
|
||||
@@ -708,7 +708,7 @@ For a contract that fulfills payments, the signed message must include:
|
||||
A replay attack is when a signed message is reused to claim authorization for
|
||||
a second action.
|
||||
To avoid replay attacks we will use the same as in Ethereum transactions
|
||||
themselves, a so-called nonce, which is the number of transactions sent by an
|
||||
themselves, a so-called nonce, which is the number of transactions sent by an
|
||||
account.
|
||||
The smart contract will check if a nonce is used multiple times.
|
||||
|
||||
@@ -731,7 +731,7 @@ Packing arguments
|
||||
Now that we have identified what information to include in the
|
||||
signed message, we are ready to put the message together, hash it,
|
||||
and sign it. For simplicity, we just concatenate the data.
|
||||
The
|
||||
The
|
||||
`ethereumjs-abi <https://github.com/ethereumjs/ethereumjs-abi>`_ library provides
|
||||
a function called ``soliditySHA3`` that mimics the behavior
|
||||
of Solidity's ``keccak256`` function applied to arguments encoded
|
||||
@@ -750,7 +750,7 @@ creates the proper signature for the ``ReceiverPays`` example:
|
||||
["address", "uint256", "uint256", "address"],
|
||||
[recipient, amount, nonce, contractAddress]
|
||||
).toString("hex");
|
||||
|
||||
|
||||
web3.personal.sign(hash, web3.eth.defaultAccount, callback);
|
||||
}
|
||||
|
||||
@@ -779,7 +779,7 @@ at the end of this chapter).
|
||||
|
||||
Computing the Message Hash
|
||||
--------------------------
|
||||
|
||||
|
||||
The smart contract needs to know exactly what parameters were signed,
|
||||
and so it must recreate the message from the parameters and use that
|
||||
for signature verification. The functions ``prefixed`` and
|
||||
@@ -801,7 +801,7 @@ The full contract
|
||||
|
||||
constructor() public payable {}
|
||||
|
||||
function claimPayment(uint256 amount, uint256 nonce, bytes signature) public {
|
||||
function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) public {
|
||||
require(!usedNonces[nonce]);
|
||||
usedNonces[nonce] = true;
|
||||
|
||||
@@ -820,7 +820,7 @@ The full contract
|
||||
}
|
||||
|
||||
/// signature methods.
|
||||
function splitSignature(bytes sig)
|
||||
function splitSignature(bytes memory sig)
|
||||
internal
|
||||
pure
|
||||
returns (uint8 v, bytes32 r, bytes32 s)
|
||||
@@ -839,7 +839,7 @@ The full contract
|
||||
return (v, r, s);
|
||||
}
|
||||
|
||||
function recoverSigner(bytes32 message, bytes sig)
|
||||
function recoverSigner(bytes32 message, bytes memory sig)
|
||||
internal
|
||||
pure
|
||||
returns (address)
|
||||
@@ -874,7 +874,7 @@ two parties (Alice and Bob). Using it involves three steps:
|
||||
1. Alice funds a smart contract with Ether. This "opens" the payment channel.
|
||||
2. Alice signs messages that specify how much of that Ether is owed to the recipient. This step is repeated for each payment.
|
||||
3. Bob "closes" the payment channel, withdrawing their portion of the Ether and sending the remainder back to the sender.
|
||||
|
||||
|
||||
Not ethat only steps 1 and 3 require Ethereum transactions, step 2 means that
|
||||
the sender transmits a cryptographically signed message to the recipient via off chain ways (e.g. email).
|
||||
This means only two transactions are required to support any number of transfers.
|
||||
@@ -906,7 +906,7 @@ Each message includes the following information:
|
||||
|
||||
* The smart contract's address, used to prevent cross-contract replay attacks.
|
||||
* The total amount of Ether that is owed the recipient so far.
|
||||
|
||||
|
||||
A payment channel is closed just once, at the of a series of transfers.
|
||||
Because of this, only one of the messages sent will be redeemed. This is why
|
||||
each message specifies a cumulative total amount of Ether owed, rather than the
|
||||
@@ -926,7 +926,7 @@ Here is the modified javascript code to cryptographically sign a message from th
|
||||
[contractAddress, amount]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function signMessage(message, callback) {
|
||||
web3.personal.sign(
|
||||
"0x" + message.toString("hex"),
|
||||
@@ -934,10 +934,10 @@ Here is the modified javascript code to cryptographically sign a message from th
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// contractAddress is used to prevent cross-contract replay attacks.
|
||||
// amount, in wei, specifies how much Ether should be sent.
|
||||
|
||||
|
||||
function signPayment(contractAddress, amount, callback) {
|
||||
var message = constructPaymentMessage(contractAddress, amount);
|
||||
signMessage(message, callback);
|
||||
@@ -1003,7 +1003,7 @@ The full contract
|
||||
expiration = now + duration;
|
||||
}
|
||||
|
||||
function isValidSignature(uint256 amount, bytes signature)
|
||||
function isValidSignature(uint256 amount, bytes memory signature)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
@@ -1017,7 +1017,7 @@ The full contract
|
||||
/// the recipient can close the channel at any time by presenting a
|
||||
/// signed amount from the sender. the recipient will be sent that amount,
|
||||
/// and the remainder will go back to the sender
|
||||
function close(uint256 amount, bytes signature) public {
|
||||
function close(uint256 amount, bytes memory signature) public {
|
||||
require(msg.sender == recipient);
|
||||
require(isValidSignature(amount, signature));
|
||||
|
||||
@@ -1043,7 +1043,7 @@ The full contract
|
||||
/// All functions below this are just taken from the chapter
|
||||
/// 'creating and verifying signatures' chapter.
|
||||
|
||||
function splitSignature(bytes sig)
|
||||
function splitSignature(bytes memory sig)
|
||||
internal
|
||||
pure
|
||||
returns (uint8 v, bytes32 r, bytes32 s)
|
||||
@@ -1058,11 +1058,11 @@ The full contract
|
||||
// final byte (first byte of the next 32 bytes)
|
||||
v := byte(0, mload(add(sig, 96)))
|
||||
}
|
||||
|
||||
|
||||
return (v, r, s);
|
||||
}
|
||||
|
||||
function recoverSigner(bytes32 message, bytes sig)
|
||||
|
||||
function recoverSigner(bytes32 message, bytes memory sig)
|
||||
internal
|
||||
pure
|
||||
returns (address)
|
||||
@@ -1083,7 +1083,7 @@ Note: The function ``splitSignature`` is very simple and does not use all securi
|
||||
A real implementation should use a more rigorously tested library, such as
|
||||
openzepplin's `version <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ECRecovery.sol>`_ of this code.
|
||||
|
||||
|
||||
|
||||
|
||||
Verifying Payments
|
||||
------------------
|
||||
@@ -1101,7 +1101,7 @@ The recipient should verify each message using the following process:
|
||||
2. Verify that the new total is the expected amount.
|
||||
3. Verify that the new total does not exceed the amount of Ether escrowed.
|
||||
4. Verify that the signature is valid and comes from the payment channel sender.
|
||||
|
||||
|
||||
We'll use the `ethereumjs-util <https://github.com/ethereumjs/ethereumjs-util>`_
|
||||
library to write this verifications. The final step can be done a number of ways,
|
||||
but if it's being done in **JavaScript**.
|
||||
@@ -1117,14 +1117,14 @@ above:
|
||||
["\x19Ethereum Signed Message:\n32", hash]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function recoverSigner(message, signature) {
|
||||
var split = ethereumjs.Util.fromRpcSig(signature);
|
||||
var publicKey = ethereumjs.Util.ecrecover(message, split.v, split.r, split.s);
|
||||
var signer = ethereumjs.Util.pubToAddress(publicKey).toString("hex");
|
||||
return signer;
|
||||
}
|
||||
|
||||
|
||||
function isValidSignature(contractAddress, amount, signature, expectedSigner) {
|
||||
var message = prefixed(constructPaymentMessage(contractAddress, amount));
|
||||
var signer = recoverSigner(message, signature);
|
||||
|
||||
Reference in New Issue
Block a user