独自暗号貨幣を作ろう 第11回
第1回 第2回 第3回 第4回 第5回 第6回 第7回 第8回 第9回 第10回
<修正1>
TXBLOCKBASE抽象クラスのId仮想プロパティの実装が間違っていたので修正します。
IdCacheを計算した後はIsModifiedフィールドを偽に変更しなければなりませんでした。
public abstract class TXBLOCKBASE<TxidBlockidHashType> : SHAREDDATA where TxidBlockidHashType : HASHBASE { public TXBLOCKBASE(int? _version) : base(_version) { } protected bool isModified; protected TxidBlockidHashType idCache; public virtual TxidBlockidHashType Id { get { if (isModified || idCache == null) { idCache = Activator.CreateInstance(typeof(TxidBlockidHashType), ToBinary()) as TxidBlockidHashType; isModified = false; } return idCache; } } public virtual bool IsValid { get { return true; } } }
<修正2>
貨幣を移動する取引に含まれる取引入力に署名を行った際にisModifiedフィールドを真に変更するのを忘れていました。修正します。
public class TransferTransaction<TxidHashType, PubKeyHashType, PubKeyType> : Transaction<TxidHashType, PubKeyHashType> where TxidHashType : HASHBASE where PubKeyHashType : HASHBASE where PubKeyType : DSAPUBKEYBASE { (中略) public void Sign(TransactionOutput<PubKeyHashType>[] prevTxOutputs, DSAPRIVKEYBASE[] privKeys) { if (prevTxOutputs.Length != inputs.Length) throw new ArgumentException("inputs_and_prev_outputs"); if (privKeys.Length != inputs.Length) throw new ArgumentException("inputs_and_priv_keys"); byte[] bytesToSign = GetBytesToSign(prevTxOutputs); for (int i = 0; i < inputs.Length; i++) inputs[i].SetSenderSig(privKeys[i].Sign(bytesToSign)); //取引入力の内容が変更された isModified = true; } (中略) }
<改良1>
今まで楕円曲線DSAの公開鍵及び秘密鍵を可変長としていましたが、直列化する場合に必要なデータ長の削減のために固定長に変更します。
DSAPUBKEYBASE抽象クラス及びDSAPRIVKEYBASE抽象クラスにSizeByte抽象プロパティを追加し、StreamInfo抽象プロパティの実装を変更します。DSAKEYPAIRBASEクラスの実装も変更します。
public abstract class DSAPUBKEYBASE : SHAREDDATA { public DSAPUBKEYBASE() : base(null) { } public DSAPUBKEYBASE(byte[] _pubKey) : base(null) { if (_pubKey.Length != SizeByte) throw new InvalidOperationException("invalid_length_pub_key"); pubKey = _pubKey; } public byte[] pubKey { get; private set; } public abstract int SizeByte { get; } public abstract bool Verify(byte[] data, byte[] signature); protected override Func<ReaderWriter, IEnumerable<MainDataInfomation>> StreamInfo { get { return (msrw) => new MainDataInfomation[]{ new MainDataInfomation(typeof(byte[]), SizeByte, () => pubKey, (o) => pubKey = (byte[])o), }; } } } public abstract class DSAPRIVKEYBASE : SHAREDDATA { public DSAPRIVKEYBASE() : base(null) { } public DSAPRIVKEYBASE(byte[] _privKey) : base(null) { if (_privKey.Length != SizeByte) throw new InvalidOperationException("invalid_length_priv_key"); privKey = _privKey; } public byte[] privKey { get; private set; } public abstract int SizeByte { get; } public abstract byte[] Sign(byte[] data); protected override Func<ReaderWriter, IEnumerable<MainDataInfomation>> StreamInfo { get { return (msrw) => new MainDataInfomation[]{ new MainDataInfomation(typeof(byte[]), SizeByte, () => privKey, (o) => privKey = (byte[])o), }; } } } public abstract class DSAKEYPAIRBASE<DsaPubKeyType, DsaPrivKeyType> : SHAREDDATA where DsaPubKeyType : DSAPUBKEYBASE where DsaPrivKeyType : DSAPRIVKEYBASE { public DSAKEYPAIRBASE() : base(null) { } public DsaPubKeyType pubKey { get; protected set; } public DsaPrivKeyType privKey { get; protected set; } protected override Func<ReaderWriter, IEnumerable<MainDataInfomation>> StreamInfo { get { return (msrw) => new MainDataInfomation[]{ new MainDataInfomation(typeof(DsaPubKeyType), null, () => pubKey, (o) => pubKey = (DsaPubKeyType)o), new MainDataInfomation(typeof(DsaPrivKeyType), null, () => privKey, (o) => privKey = (DsaPrivKeyType)o), }; } } }
具象クラスにSizeByte抽象プロパティを実装します。それ程大きな変更ではないので、コードは示しません。
<改良2>
更に取引入力の署名も可変長から固定長に変更します。senderSigLength静的フィールドを追加します。
public class TransactionInput<TxidHashType, PubKeyType> : SHAREDDATA where TxidHashType : HASHBASE where PubKeyType : DSAPUBKEYBASE { (中略) public static readonly int senderSigLength = 64; (中略) protected override Func<ReaderWriter, IEnumerable<MainDataInfomation>> StreamInfo { get { return (msrw) => new MainDataInfomation[]{ new MainDataInfomation(typeof(TxidHashType), null, () => prevTxHash, (o) => prevTxHash = (TxidHashType)o), new MainDataInfomation(typeof(int), () => prevTxOutputIndex, (o) => prevTxOutputIndex = (int)o), new MainDataInfomation(typeof(byte[]), senderSigLength, () => senderSig, (o) => senderSig = (byte[])o), new MainDataInfomation(typeof(PubKeyType), null, () => senderPubKey, (o) => senderPubKey = (PubKeyType)o), }; } } (中略) public void SetSenderSig(byte[] sig) { if (sig.Length != senderSigLength) throw new ArgumentException("tx_in_sender_sig_length"); senderSig = sig; } }