返回介绍

6.流动的民主

发布于 2024-12-29 22:37:18 字数 6092 浏览 0 评论 0 收藏 0

a.概览

这部分纯粹是颜色币一项应用的概念性练习。设想这样一个公司,投资者委员会经过投票作出决策。

  • 一些投资者不知道主题内容,所以他们想委托其他一些人作出决策
  • 投资者的数量非常之大
  • 作为 CEO,你想拥有为公司融资而销售投票权的能力
  • 作为 CEO,你想在作出决定后,可以投出一票

颜色币如何可以透明地组织这样的选举?

开始前,我们探讨一下区块链上投票的一些背景:

  • 没有人知道投票人的真实 ID,
  • 矿工可以审查(就算它是可证明的,而且不是出于自利)
  • 虽然没有人知道投票人的真实 ID,在几轮投票后通过对投票人进行行为分析可以识别出他的 ID

这几点是否关联取决于投票组织者的决策。我们先大概看看它的实现。

b.发行投票权

一切从公司创始人开始(我们叫他老板),他想销售公司的决策权给一些投资者。决策权采取颜色币的形式,在本练习中,我们称之为 权力币 。

我们以紫色表示它:

假设 3 个人感兴趣,Satoshi、Alice 和 Bob。(是的,又是他们 3 个)

老板决定按照 0.1BTC/权力币的价格向他们每个人出售。

我们开始向权力币的地址发送一些货币,包括 Satoshi、Alice 和 Bob。

var powerCoin = new Key();
var alice = new Key();
var bob = new Key();
var satoshi = new Key();
var init = new Transaction()
{
    Outputs =
    {
        new TxOut(Money.Coins(1.0m), powerCoin),
        new TxOut(Money.Coins(1.0m), alice),
        new TxOut(Money.Coins(1.0m), bob),
        new TxOut(Money.Coins(1.0m), satoshi),
    }
};

var repo = new NoSqlColoredTransactionRepository();
repo.Transactions.Put(init);

设想 Alice 购买了 2 个权力币,创建交易如下:

var issuance = GetCoins(init,powerCoin)
    .Select(c=> new IssuanceCoin(c))
    .ToArray();
var builder = new TransactionBuilder();
var toAlice =
builder
    .AddCoins(issuance)
    .AddKeys(powerCoin)
    .IssueAsset(alice, new Asset(powerCoin, 2))
    .SetChange(powerCoin)
    .Then()
    .AddCoins(GetCoins(init, alice))
    .AddKeys(alice)
    .Send(alice, Money.Coins(0.2m))
    .SetChange(alice)
    .BuildTransaction(true);
repo.Transactions.Put(toAlice);

总的来说,权力币向 Alice 发行了 2 个币,并把零钱发送给自己。类似,Alice 发送 0.2BTC 给权力币,并把零钱发送给她自己。

GetCoins 函数如下:

private IEnumerable<Coin> GetCoins(Transaction tx, Key owner)
{
    return tx.Outputs.AsCoins().Where(c => c.ScriptPubKey == owner.ScriptPubKey);
}

由于一些原因,Alice 可能想要出售一些投票权给 Satoshi。

builder = new TransactionBuilder();
var toSatoshi =
builder
    .AddCoins(ColoredCoin.Find(toAlice, repo))
    .AddCoins(GetCoins(init, alice))
    .AddKeys(alice)
    .SendAsset(satoshi, new Asset(powerCoin, 1))
    .SetChange(alice)
    .Then()
    .AddCoins(GetCoins(init, satoshi))
    .AddKeys(satoshi)
    .Send(alice, Money.Coins(0.1m))
    .SetChange(satoshi)
    .BuildTransaction(true);
repo.Transactions.Put(toSatoshi);

你可以注意到我正从 init 交易中双花 Alice 的币。

这种事情在区块链上是不被允许的。然而,我们还没有看到如何从区块链上轻松地取回未花出去的币,所以我们在本练习中暂且设想并没有双花。

现在 Alice 和 Satoshi 都有投票权了,看看老板如何举行一次投票选举。

c.投票选举

通过询问区块链,老板任何时候都可以知道 ScriptPubKeys,它拥有权力币。

因此他按投票权力比例发送投票币给这些所有者,在我们的例子中,给 Alice 和 Satoshi 各一个投票币。

首先,我需要为 votingCoin 创建一些资金池。

var votingCoin = new Key();
var init2 = new Transaction()
{
    Outputs =
    {
        new TxOut(Money.Coins(1.0m), votingCoin),
    }
};
repo.Transactions.Put(init2);

然后,就是发行投票币。

issuance = GetCoins(init2, votingCoin).Select(c => new IssuanceCoin(c)).ToArray();

builder = new TransactionBuilder();
var toVoters =
    builder
    .AddCoins(issuance)
    .AddKeys(votingCoin)
    .IssueAsset(alice, new Asset(votingCoin, 1))
    .IssueAsset(satoshi, new Asset(votingCoin, 1))
    .SetChange(votingCoin)
    .BuildTransaction(true);
repo.Transactions.Put(toVoters);

d.投票代理

问题是投票牵涉到一些商业上的金融事项,而 Alice 比较关心市场方面的情况。

她的策略就是把投票币委托给她认为对金融事项有比较准确判断的人。她选择将投票委托给 Bob。

var aliceVotingCoin = ColoredCoin.Find(toVoters,repo)
    .Where(c=>c.ScriptPubKey == alice.ScriptPubKey)
    .ToArray();
builder = new TransactionBuilder();
var toBob =
    builder
    .AddCoins(aliceVotingCoin)
    .AddKeys(alice)
    .SendAsset(bob, new Asset(votingCoin, 1))
    .BuildTransaction(true);
repo.Transactions.Put(toBob);

你会注意到这里没有 SetChange,原因是输入的颜色币被全部花掉了,所以没有剩下的供返回。

e.投票

设想 Satoshi 太忙了决定不去投票。现在 Bob 必须表明自己的观点。投票议题是公司是否应该向银行申请一笔贷款用于投资新生产机器。

老板在公司网站上说明:

发送你的币到 1HZwkjkeaoZfTSaJxDw6aKkxp45agDiEzN 表示同意,

到 1F3sAm6ZtwLAUnj7d38pGFxtP3RVEvtsbV 表示不同意。

Bob 认为公司应该申请这笔贷款:

builder = new TransactionBuilder();
var vote =
    builder
    .AddCoins(bobVotingCoin)
    .AddKeys(bob)
    .SendAsset(BitcoinAddress.Create("1HZwkjkeaoZfTSaJxDw6aKkxp45agDiEzN"),
        new Asset(votingCoin, 1))
    .BuildTransaction(true);

现在老板可以计算出投票结果了,1 票赞同,0 票反对,结果是同意。因此他申请了贷款。

每一个参与者都可以自己计算出结果。

f.替代方案:使用李嘉图合约

在签名的练习中,我们假设老板在区块链之外声明投票的形式,也就是在公司网站上。

这样很好,但是 Bob 需要知道网址在哪里。

另一种解决方案就是把投票形式直接发布在区块链上,在资产定义文件里面,这样一些软件就可以自动地获得并展现给 Bob。

唯一需要更改的代码段就是发行投票币给投票人员。

issuance = GetCoins(init2, votingCoin).Select(c => new IssuanceCoin(c)).ToArray();
issuance[0].DefinitionUrl = new Uri("http://boss.com/vote01.json");
builder = new TransactionBuilder();
var toVoters =
    builder
    .AddCoins(issuance)
    .AddKeys(votingCoin)
    .IssueAsset(alice, new Asset(votingCoin, 1))
    .IssueAsset(satoshi, new Asset(votingCoin, 1))
    .SetChange(votingCoin)
    .BuildTransaction(true);
repo.Transactions.Put(toVoters);

本例中,Bob 可以看到,在发行他的投票币期间,一份资产定义文件被发布了,这份文件是 JSON 格式文档,部分格式定义在开放资产中。

格式定义可以被扩展到一些信息,比如:

  • 投票期限
  • 每位候选人的投票地址
  • 人工可读的描述

然而,设想有一位黑客想要在投票中作弊。他总可以篡改 json 文档(中间人攻击、物理访问 boss.com 或者访问 Bob 的机器),由此 Bob 就被欺骗了,然后投票给错误的候选人。

通过签名将资产定义文件转换为李嘉图合约,将使得任何改变 Bob 的软件都可以实时监测到。(参照在资产定义协议中的真实性证明)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文