独自暗号貨幣を作ろう 第1回

これから独自の暗号貨幣(cryptocurrency)を作る試みを連載していこうと思います。
コードはGitHubで公開します。
https://github.com/pizyumi/CREA


<方針1>
基本的にはBitcoinと同様の、仕事証明(proof of work)に基づく分散型の合意形成系を用いた暗号貨幣を作ります。
細かい部分に関してはBitcoinの改良を目指します。
Bitcoinのコードを利用せず、全て自分で書きます。
C#で書きます。
暗号貨幣の名称はCREACOIN(クレアコイン)とします。


<貨幣単位>
主貨幣単位(貨幣の額面価格の主たる単位)はcreacoin(CREA)とし、補助貨幣単位(貨幣の額面価格の補助的な単位)は1CREA=100yuminaとします(更に補助貨幣単位を公募するかも知れません)。貨幣の最小額面価格はBitcoinと同様に0.00000001CREAとします。便宜上、額面価格を保持する際には最小額面価格を単位として表現するものとします。

全ての貨幣単位(による額面価格)を表すCurrencyUnitクラス並びに主貨幣単位creacoin及び補助貨幣単位yumina(による額面価格)を表すCreacoinクラス及びYuminaクラスを作ります。
rawAmountが最小額面価格を単位として表した場合の額面価格です。
Amountがその貨幣単位による額面価格です。

public class CurrencyUnit
{
    public CurrencyUnit() { }
 
    public CurrencyUnit(ulong _rawAmount) { rawAmount = _rawAmount; }
 
    public ulong rawAmount { get; protected set; }
 
    public virtual decimal Amount { get { throw new NotImplementedException("currency_unit_amount"); } }
    public virtual Creacoin AmountInCreacoin { get { return new Creacoin(rawAmount); } }
    public virtual Yumina AmountInYumina { get { return new Yumina(rawAmount); } }
}
 
public class Creacoin : CurrencyUnit
{
    public Creacoin(ulong _rawAmount) { rawAmount = _rawAmount; }
 
    public Creacoin(decimal _amountInCreacoin)
    {
        if (_amountInCreacoin < 0.0m)
            throw new ArgumentException("creacoin_out_of_range");
 
        decimal amountInMinimumUnit = _amountInCreacoin * CreacoinInMinimumUnit;
        if (amountInMinimumUnit != Math.Floor(amountInMinimumUnit))
            throw new InvalidDataException("creacoin_precision");
 
        rawAmount = (ulong)amountInMinimumUnit;
    }
 
    public static decimal CreacoinInMinimumUnit = 100000000.0m;
 
    public override decimal Amount { get { return rawAmount / CreacoinInMinimumUnit; } }
    public override Creacoin AmountInCreacoin { get { return this; } }
}
 
public class Yumina : CurrencyUnit
{
    public Yumina(ulong _rawAmount) { rawAmount = _rawAmount; }
 
    public Yumina(decimal _amountInYumina)
    {
        if (_amountInYumina < 0.0m)
            throw new ArgumentException("yumina_out_of_range");
 
        decimal amountInMinimumUnit = _amountInYumina * YuminaInMinimumUnit;
        if (amountInMinimumUnit != Math.Floor(amountInMinimumUnit))
            throw new InvalidDataException("yumina_precision");
 
        rawAmount = (ulong)amountInMinimumUnit;
    }
 
    public static decimal YuminaInMinimumUnit = 1000000.0m;
 
    public override decimal Amount { get { return rawAmount / YuminaInMinimumUnit; } }
    public override Yumina AmountInYumina { get { return this; } }
}