6

斯坦福大学 CS251(加密货币与区块链技术) 2021 期末考试题 看看你能得多少分?

 2 years ago
source link: https://www.jinse.com/blockchain/1183048.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

编译:TechFlow intern

根据斯坦福荣誉守则的明文规定和精神,我在这次考试中既没有得到任何帮助,也没有提供任何帮助给别人。

  • 本考试包含6个问题,共计100分。

  • 你需要在规定时间完成考试。

  • 请在Gradescope (D5GKRX)上作答。  

  • 回答问题请简明扼要。

问题1.(18分)宏观问题。

A)→请简要回答为什么Rollup系统将所有交易都存储在链上?如果交易数据丢失,而其他地方又没有备份,那将会怎么样呢?

B)→请看以下Solidity 代码:

pragma solidity ^0.8.0;

contract ERC20 is IERC20 {

mapping(address => uint256) private _balances;

event Transfer(address indexed from, address indexed to, uint256 value); function _transfer(address sender, address recipient, uint256 amount) { emit Transfer(sender, recipient, amount);

假设该代码部署于两个契约中:一个地址为X的契约和一个地址为Y的契约。 以下的哪个选项可以在契约X中读到_balances的状态?圈出正确的答案(一个或多个)。

A 合同ERC20中地址X处的_transfer()函数中的代码

B 合同ERC20中地址为Y的_transfer()函数中的代码

C 使用 etherscan.io的终端用户

C)→继续上一题,下面哪一个选项可以在函数_transfer()被撤回时,读取日志项Transfer的发出?请圈出正确的答案。

A 在ERC20合同中定义的地址为X的getBalance()函数中的代码

B 在ERC20合同中定义的地址为Y的getBalance()函数中的代码

C 使用 etherscan.io的终端用户

D)→当两个以太坊交易txi和tx2 被同时提交时,将 交易  txi的maxPriorityFee设置为y, 交易tx2的maxPriorityFee设置为2y, 请问tx2一定要在txi之前在chain上执行吗? 请给出答案并论证。 你可以假设txi和tx2的maxFee都大于baseFee + maxPriorityFee。  

E)→ Alice想从经销商Bob那里买一辆车。她发送1个比特币到Bob的比特币地址。Bob等待一个交易, 这个交易中其1,输入来自Alice的地址,其2,其中一个输出是绑定到Bob地址的UTXO,价值1 BTC。只要鲍勃在比特币区块链上看到这笔交易,他就把钥匙给Alice,然后Alice就可以把车开车走了。这样安全吗? Alice能免费得到那辆车吗? 如果可以,请解释原因。如果不可以,请解释Bob应该如何做来确保他被支付。

F)→Alice有一台型号为Y的全新特斯拉。她现在就可以以此为抵押物在Compound系统做贷款吗(在不卖出的情况下)? 如果是,请解释怎么做,如果不可以,请解释为什么。

问题 2.(20分) Byzantine broadcast.

假设有n 方, 而且n>3, 其中一方被指定为是sender. Sender有比特b∈{0,1}. brodacast 协议是指各方向对方发出信息,而且最终每一方都输出一些 比特bi,这里的i可以是1,....,n或者为0.

我们认为协议具有一致性,即对于每两个诚实方来说,如果一方输出b,另一方输出b',则b = b'。

我们认为协议是有效的,即如果发送方是诚实的,则所有诚实方的输出等于发送方的输入比特b。 

我们认为协议具有普遍性,即当某个诚实方输出一个比特时,那么最终所有的诚实方都输出一个比特。

一个 reliable broadcast protocol(RBC)是满足以下三个特性的广播协议。我们假设存在一个公钥基础设施(PKI),这意味着每一方都有一个秘密的签名密钥,并且每一方都知道另一方的正确的公开签名验证密钥。

在同步网络中,考虑以下广播协议:

步骤0: The sender sends its input bit b (along with its signature) to all other parties. The sender then outputs its bit b and terminates. Sender 向其他所有协议方 连同其签名一起输入比特b,然后输出比特b 并终止。

步骤1 : 每个非发送方i 向其他非发送方反馈其从发送给方听到的信息,该信息被附加了i的签名。 如果其未听到任何发送方的消息,则在这一环节什么都不做。同样地,如果发送方的信息是畸形的,那非发送方在这一环节仍然什么都不做。畸形的信息包括 发送者的签名无效,或者该信息并被单独比特。

步骤2:每个非发送将其收到的所有信息收集起来,最多到n - 1的消息, 其中最多一条来自步骤0的发送方,和最多1条来自步骤1中的每一个非发送方non-sender方。如果有两个由发送方收到消息包含一个有效的签名,但比特相反(即,在一个签名的消息中,比特为0,在另一个签名的消息中,比特为1),那么发送方是不诚实的,那么非发送方输出0并终止协议。相反,发送方发送的所有正确签名的比特都是相同的,那么非发送方输出该比特。如果非发送方没有收到任何消息,则不输出任何内容。

针对以下问题,描述一次攻击,或解释为什么没有受到攻击。

A)    假设最多只有一个不诚实方,协议是否仍具有一致性?  

B)    假设最多只有一个不诚实方,协议是否仍具有有效性?

C)    假设最多只有两个不诚实方,则表明协议不具备一致性。

D)    假设最多有两个不诚实方,协议是否具有有效性?

E)     对于任何数量的不诚实方,协议是否具有普遍性?

问题3(20分): Automated market maker (AMM).

你作为Uniswap V2的流动性提供者,为DAI/ETH池贡献5个ETH即5000个DAI。假设1个DAI值1美元,那么你的出资总额为1万美元。

A)    几个月后,1个ETH的价格上升到2000 DAI。在DAI/ETH池适应这个新的汇率稳定下来以后,您决定撤回作为流动性提供者的全部份额。假设系统不收费(∅= 1),你会收到多少ETH和DAI ?

B)    如果你自己持有你的5 ETH和5000 DAI,你的资产现在将价值15K DAI,获取了5000 DAI的利润。在这几个月里,作为Uniswap V2的流动性提供者,与“自己持有”策略相比,你经历了什么损失? 将损失以美元的绝对值表示,假设1 DAI = 1 USD。这被称为暂时性损失,尽管在这种情况下,这种损失是相当永久性的。

C)    如果您因担任Uniswap V2的流动性提供者而损失了x美元,Uniswap V2是用部分(b)计算x的,那么这些资金流向了哪里?具体来说,就是谁在这个过程中获得了x美元?

D)     现在让我们转向使用Uniswap V2 交易。假设Bob使用DAI/ETH池将DAI兑换成ETH进行大型 交易。交易完成后,DAI/ETH池中的DAI金额比之前略高,而ETH的金额则略低。因此,DAI/ETH  池中的资产比率有点偏离其平衡点。

套利者Alice发现了这个机会,并希望在反方向发行一个交易,以重新平衡资金池。她旨在从这笔交易中获利,所以希望确保她的交易在Bob交易后被立即执行。这种策略被称为“尾随”。

那么Alice如何能实施尾随计划呢?请提出可以使Alice的交易在Bob之后可以有合理机会被立即被执行的方法。

E)      假设10个不同的套利者,为捕获Bob的交易创造的套利机会, 在同一时间执行了相同的尾随操作策略。他们都使用了你在(D)部分中所描述的相同机制,那么这10个中的哪一个会获胜呢?  

问题4. [16 分]: Hashmasks 重入缺陷

在第8课和第3节中,我们讨论了坚固重入缺陷。在这个问题中,我们将看一个有趣的现实世界的例子。考虑下面16384个NFT中使用的稳固代码片段。通过撤回此NFT合约上的mintNFT()函数,用户一次最多可以声明20个NFT。您可以假设所有内部变量都由构造函数正确初始化(未显示)。

function mintNFT(uint256 numberOfNfts) public payable {

require(totalSupply() < 16384, "Sale has already ended");

require(numberOfNfts > 0, "numberOfNfts cannot be 0");

require(numberOfNfts <= 20, "You may not buy more than 20 NFTs at once"); require(totalSupply().add(numberOfNfts) <= 16384, "Exceeds NFT supply"); require(getNFTPrice().mul(numberOfNfts) == msg.value, "Value sent is not correct");

for (uint i = 0; i < numberOfNfts; i++) {

uint mintIndex = totalSupply(); // get number of NFTs issued so far        

_safeMint(msg.sender, mintIndex); // mint the next one

function _safeMint(address to, uint256 tokenId) internal virtual {

// Mint one NFT and assign it to address(to).

require(!_exists(tokenId), "ERC721: token already minted");

_data = _mint(to, tokenId); // mint NFT and assign it to address to

_totalSupply ++; // increment totalSupply() by one

if (to.isContract()) {

// Confirm that NFT was recorded properly by calling

// the function onERC721Received() at address(to).

// The arguments to the function are not important here.

// If onERC721Received is implemented correctly at address(to) then

// the function returns _ERC721_RECEIVED if all is well.

bytes4 memory retval=

IERC721Receiver(to).onERC721Received(to, address(0), tokenId, _data);

require(retval == _ERC721_RECEIVED, "NFT Rejected by receiver");

让我们证明_safeMint根本不安全(尽管它的名字是安全)。

A)    假设已经铸造了16370个NFT,那么总供给()=16370。请解释恶意合同如何导致超过16384个NFT被伪造。攻击者最多可以造出多少个NFT?

提示:如果在呼叫地址收到的OneRC721是恶意的,结果会怎样?请仔细检查铸币回路,并考虑重入缺陷。

B)    假设现在总供给的价值是16370,请写出实施对(a)部分进行攻击的恶意Solidity合约代码。

C)    你会在前一页的代码中添加或更改哪一行Solidity来防止你的攻击?请注意,单个交易不应该铸造超过20个NFT。

问题5.  (15分)比特币问题 .

A)    Lightning Network协议的好处是无需向比特币网络发布交易即可执行支付。Lightning Network支付最终会完全取代所有的比特币交易,使区块链变得不必要吗?

B)    回顾而知,比特币交易有一组输入地址和一组输出地址。通常,每个输入地址预示着整个交易可(不包括签名)授权支付。此签名类型被称为SIGHASH_ALL。

相反,假设使用每个输入地址的密钥来签名整个Txin(交易的输入部分,不包括签名),而不签名其他任何内容。也就是说,Txout(交易的输出部分)没有签名。(该签名类型称为SIGHASH_NONE)。

一旦交易提交给比特币网络后,对于使用SIGHASHNONE方法的交易,矿工是否可以从其输入的地址中窃取资金?如果可以,请解释如何窃取;如果不可以,请解释原因。

C)    如果有人在只有ECDSA公钥的情况下,发现了一种方法来伪造ECDSA签名的任意消息,比特币会受到怎样的影响? 假设伪造一个签名需要30分钟且不能加速。

问题6.(11分): Tornado 现金

在第14讲中,我们讲了Tornado Cash搅拌机。回想一下,Tornado现金合同需要存储一个大的nullifiers,列表,每次从树中提取一个nullifiers,。在合同撤销期间,合同需要确保被撤销的票据的nullifiers,不在已撤销的nullifiers,清单中。如果是,合同将这个nullifier添加到集合中。Tornado现金合同将其实现为一个映射:

mapping(bytes32 => bool) public nullifierHashes;

在撤销过程中,合同应验证所提供的zk-SNARK证据,如果合同有效,则应:

bytes32 _nullifierHash; // nullifier of note being withdrawn require(!nullifierHashes[_nullifierHash], "The note has been spent"); nullifierHashes[_nullifierHash] = true;

A)    假设从树中成功提取了k。考虑一个矿工正在验证以太坊交易。作为k的函数,这个矿工需要分配多少存储空间来存储nullifierhash映射? 你可以假设除了这个nullifierhash映射之外,Tornado合同不需要其他长期存储。

B)    如果我们能将撤销的nullifier Sk在链外存储起来,比如储存在云端,那就更好了。Tornado契约将只存储针对当前nullifier Sk集合的一个短提交。当撤回withdraw函数时,用户将向该函数提供所有当前参数,此外,用户还将提供:

  • 一个证明π,即 撤回的硬币的nullifier nf  不在提交的nullifier 集合中,即nf ∉Sk,而且

  • Tornado合同能够计算更新的nullifier 集合提交的足够的信息Sk+1:= Sk U {nf}

该合约将验证π的证明 nf  ∉ Sk,并计算出对Sk+1的提交,并用更新后的对Sk+1的提交替换当前对Sk的提交。

有几种数据结构提供了这些功能,比如Sk的提交是一个32字节的哈希值,而π证明只包含2个[log2k] 32字节的哈希值。此外,这个简短的证明使Tornado合同能够计算Sk+1的短期提交。通过改编第7讲中介绍的Merkle Patricia树可以得到一个例子,但我们将把这个问题留到以后来解决。

虽然这种方法将大大减少合同存储矩阵的大小,但只有当它将减少撤回提取函数所需的燃料时,才值得实现。考虑以下的燃料成本:

  • 写入存储数组中的零项: 20K 燃料

  • 写入存储数组中的非零项: 5K 燃料,

  • calldata (包含参数函数的字节数组): 每字节16个燃料

假设我们只计算上面列出的三项所消耗的燃料。当撤回当前的执行时,这一改变将节省的燃料价值k是多少?回想一下,证明π是32 × 2[log2k]字节,其必须作为提取函数撤回call-data的一部分提供。

C)    回想一下,Tornado现金提供了一个合规工具,可以让用户去匿名化他们的硬币:该工具生成一个文件,将用户的存款与特定的撤回联系起来。在交易所接受该资金前,该文档可能需要提交给集中式交易所(如Coinbase)。

假设n个人将一枚硬币存入一个Tornado 池,那么这个池的匿名性设置为n(假设n = 1000)。此后,所有的n个人将他们的硬币取出到n个新的以太坊地址中(每个新地址都有一个硬币)。观察者无法判断哪个新的以太坊地址对应于这n个人中的某一个,因此匿名集的大小为n。

但是,假设有n - 1人使用合规工具并将结果文档发送到Coinbase。这对于最后一个希望拥有私人地址的人的隐私意味着什么?

课程链接:https://cs251.stanford.edu/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK