-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8b86dc3
commit b6b842a
Showing
5 changed files
with
219 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.16; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {console2 as console} from "forge-std/console2.sol"; | ||
|
||
import { | ||
StealthSecp256k1, | ||
StealthAddress, | ||
StealthMetaAddress, | ||
SCHEME_ID | ||
} from "src/stealth-addresses/StealthSecp256k1.sol"; | ||
import { | ||
IERC5564Announcer, | ||
ERC5564Announcer | ||
} from "src/stealth-addresses/ERC5564Announcer.sol"; | ||
|
||
import {Secp256k1, PrivateKey, PublicKey} from "src/curves/Secp256k1.sol"; | ||
|
||
contract StealthSecp256k1Example is Script { | ||
using StealthSecp256k1 for PrivateKey; | ||
using StealthSecp256k1 for StealthAddress; | ||
using StealthSecp256k1 for StealthMetaAddress; | ||
|
||
using Secp256k1 for PrivateKey; | ||
using Secp256k1 for PublicKey; | ||
|
||
function run() public { | ||
// Sender key pair. | ||
console.log("Sender: Creates key pair"); | ||
PrivateKey senderPrivKey = Secp256k1.newPrivateKey(); | ||
PublicKey memory senderPubKey = senderPrivKey.toPublicKey(); | ||
|
||
// Receiver key pairs consist of spending and viewing key pairs. | ||
console.log("Receiver: Creates key pairs"); | ||
PrivateKey receiverSpendingPrivKey = Secp256k1.newPrivateKey(); | ||
PublicKey memory receiverSpendingPubKey = | ||
receiverSpendingPrivKey.toPublicKey(); | ||
PrivateKey receiverViewPrivKey = Secp256k1.newPrivateKey(); | ||
PublicKey memory receiverViewPubKey = receiverViewPrivKey.toPublicKey(); | ||
|
||
// There exists an ERC5564Announcer instance. | ||
IERC5564Announcer announcer = IERC5564Announcer(new ERC5564Announcer()); | ||
|
||
// Receiver creates their stealth meta address. | ||
// TODO: Note that these addresses need to be published somehow. | ||
console.log("Receiver: Creates stealth meta address"); | ||
StealthMetaAddress memory receiverStealthMeta; | ||
receiverStealthMeta = StealthMetaAddress({ | ||
spendingPubKey: receiverSpendingPubKey, | ||
viewingPubKey: receiverViewPubKey | ||
}); | ||
|
||
// Sender creates stealth address from receiver's stealth meta address. | ||
console.log( | ||
"Sender: Creates stealth address based on receiver's meta address" | ||
); | ||
StealthAddress memory stealth = receiverStealthMeta.newStealthAddress(); | ||
|
||
// Sender sends ETH to stealth. | ||
console.log("Sender: Sends ETH to receiver's stealth address"); | ||
vm.deal(senderPubKey.toAddress(), 1 ether); | ||
vm.prank(senderPubKey.toAddress()); | ||
(bool ok, ) = stealth.recipient.call{value: 1 ether}(""); | ||
require(ok, "Sender: ETH transfer failed"); | ||
|
||
// Sender announces tx via ERC5564Announcer. | ||
console.log("Sender: Announces tx via ERC5564Announcer"); | ||
vm.prank(senderPubKey.toAddress()); | ||
announcer.announce({ | ||
schemeId: SCHEME_ID, | ||
stealthAddress: stealth.recipient, | ||
ephemeralPubKey: stealth.ephemeralPubKey.toBytes(), | ||
// See ERC5564Announcer.sol for more info. | ||
metadata: abi.encodePacked( | ||
stealth.viewTag, | ||
hex"eeeeeeee", | ||
hex"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", | ||
uint(1 ether) | ||
) | ||
}); | ||
|
||
// Receiver checks announces stealth address. | ||
console.log("Receiver: Verifies tx is based on own meta address"); | ||
require( | ||
receiverViewPrivKey.checkStealthAddress( | ||
receiverSpendingPubKey, stealth | ||
), | ||
"Check failed" | ||
); | ||
|
||
// Receiver computed stealth's private key. | ||
console.log("Receiver: Computes private key for stealth address"); | ||
PrivateKey stealthPrivKey = receiverSpendingPrivKey | ||
.computeStealthPrivateKey(receiverViewPrivKey, stealth); | ||
|
||
// Verify computed private key's address matches stealth's recipient | ||
// address. | ||
console.log("Receiver: Verifies access on stealth address"); | ||
require( | ||
stealthPrivKey.toPublicKey().toAddress() == stealth.recipient, | ||
"Private key computation failed" | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.16; | ||
|
||
/** | ||
* @title IERC5561Announcer | ||
* | ||
* @notice Interface to announce a tx to an [EIP-5564] stealth address | ||
* | ||
* @dev Metadata Specification and Recommendations | ||
* | ||
* The first byte of the metadata MUST be the view tag. The view tag provides | ||
* a probabilistic filter to skip computations when checking announcements. | ||
* | ||
* The following recommendations are given in [EIP-5564]: | ||
* | ||
* - Tx transferring the native token, eg ETH: | ||
* | ||
* Index | Description | Length in bytes | ||
* ----------------------------------------------------------------------------- | ||
* [0x00] | View tag | 1 | ||
* [0x01:0x04] | `0xeeeeeeee` | 4 | ||
* [0x05:0x24] | `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` | 20 | ||
* [0x18:0x38] | Amount in wei | 32 | ||
* | ||
* - Tx involving a contract call with a single argument, eg ERC-20/ERC-721 | ||
* transfers: | ||
* | ||
* Index | Description | Length in bytes | ||
* ----------------------------------------------------------------------------- | ||
* [0x00] | View tag | 1 | ||
* [0x01:0x04] | Solidity function selector | 4 | ||
* [0x05:0x24] | Contract address | 20 | ||
* [0x18:0x38] | One word argument, eg token amount | 32 | ||
* | ||
* @custom:references | ||
* - [EIP-5564]: https://eips.ethereum.org/EIPS/eip-5564 | ||
* - [EIP-5564 Scheme Registry]: https://eips.ethereum.org/assets/eip-5564/scheme_ids | ||
*/ | ||
interface IERC5564Announcer { | ||
/// @notice Emitted to announce a tx to a stealth address. | ||
/// | ||
/// @param schemeId Scheme id based on [EIP-5564 Scheme Registry] registry. | ||
/// @param stealthAddress The stealth address. | ||
/// @param caller The address who announced the tx. | ||
/// @param ephemeralPubKey The ephemeral public key created during the | ||
/// stealth address generation. | ||
/// @param metadata Bytes blob providing the view tag and arbitrary | ||
/// additional metadata. Note that [EIP-5564] provides | ||
/// recommendations. | ||
event Announcement( | ||
uint indexed schemeId, | ||
address indexed stealthAddress, | ||
address indexed caller, | ||
bytes ephemeralPubKey, | ||
bytes metadata | ||
); | ||
|
||
/// @notice Announces a tx to stealth address `stealthAddress` using scheme | ||
/// `schemeId` and ephemeral public key `ephemeralPubKey`. View tag | ||
/// and additional metadata are provided via `metadata`. | ||
/// | ||
/// @param schemeId Scheme id based on [EIP-5564 Scheme Registry] registry. | ||
/// @param stealthAddress The stealth address. | ||
/// @param ephemeralPubKey The ephemeral public key created during the | ||
/// stealth address generation. | ||
/// @param metadata Bytes blob providing the view tag and arbitrary | ||
/// additional metadata. Note that [EIP-5564] provides | ||
/// recommendations. | ||
function announce( | ||
uint schemeId, | ||
address stealthAddress, | ||
bytes memory ephemeralPubKey, | ||
bytes memory metadata | ||
) external; | ||
} | ||
|
||
/** | ||
* @title ERC5564Announcer | ||
* | ||
* @notice Minimal [EIP-5564] stealth address announcement contract | ||
*/ | ||
contract ERC5564Announcer is IERC5564Announcer { | ||
/// @inheritdoc IERC5564Announcer | ||
function announce( | ||
uint schemeId, | ||
address stealthAddress, | ||
bytes memory ephemeralPubKey, | ||
bytes memory metadata | ||
) external { | ||
emit Announcement( | ||
schemeId, stealthAddress, msg.sender, ephemeralPubKey, metadata | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters