public override long AppendIndex( string @namespace, HashDigest <SHA256> hash ) { var indexFile = new FileInfo(GetIndexPath(@namespace)); using (Stream stream = indexFile.Open( FileMode.Append, FileAccess.Write)) { var offset = stream.Position; stream.Write(hash.ToByteArray(), 0, hash.ToByteArray().Length); return(offset / HashDigest <SHA256> .Size); } }
public byte[] Sign(HashDigest <T> messageHash, PrivateKey privateKey) { var h = new Sha256Digest(); var kCalculator = new HMacDsaKCalculator(h); var signer = new ECDsaSigner(kCalculator); signer.Init(true, privateKey.KeyParam); BigInteger[] rs = signer.GenerateSignature(messageHash.ToByteArray()); var r = rs[0]; var s = rs[1]; BigInteger otherS = privateKey.KeyParam.Parameters.N.Subtract(s); if (s.CompareTo(otherS) == 1) { s = otherS; } var bos = new MemoryStream(72); var seq = new DerSequenceGenerator(bos); seq.AddObject(new DerInteger(r)); seq.AddObject(new DerInteger(s)); seq.Close(); return(bos.ToArray()); }
/// <inheritdoc/> public override void StoreStateReference <T>( string @namespace, IImmutableSet <Address> addresses, Block <T> block) { HashDigest <SHA256> blockHash = block.Hash; long blockIndex = block.Index; int hashSize = HashDigest <SHA256> .Size; foreach (Address address in addresses) { var stateReferenceFile = new FileInfo( GetStateReferencePath(@namespace, address)); if (!stateReferenceFile.Directory.Exists) { stateReferenceFile.Directory.Create(); } using (Stream stream = stateReferenceFile.Open( FileMode.Append, FileAccess.Write)) { stream.Write(blockHash.ToByteArray(), 0, hashSize); stream.Write( BitConverter.GetBytes(blockIndex), 0, sizeof(long)); } } }
/// <inheritdoc/> public override void StoreStateReference( Guid chainId, IImmutableSet <string> keys, HashDigest <SHA256> blockHash, long blockIndex) { ColumnFamilyHandle cf = GetColumnFamily(_stateRefDb, chainId); foreach (string key in keys) { byte[] keyBytes = StateRefKey(key, blockIndex); _stateRefDb.Put(keyBytes, blockHash.ToByteArray(), cf); } if (!_lastStateRefCaches.ContainsKey(chainId)) { _lastStateRefCaches[chainId] = new LruCache <string, Tuple <HashDigest <SHA256>, long> >(); } LruCache <string, Tuple <HashDigest <SHA256>, long> > stateRefCache = _lastStateRefCaches[chainId]; foreach (string key in keys) { _logger.Debug($"Try to set cache {key}"); if (!stateRefCache.TryGetValue(key, out Tuple <HashDigest <SHA256>, long> cache) || cache.Item2 < blockIndex) { stateRefCache[key] = new Tuple <HashDigest <SHA256>, long>(blockHash, blockIndex); } } }
public byte[] Sign(HashDigest <T> messageHash, PrivateKey privateKey) { lock (_instanceLock) { var secp256K1Signature = new byte[Secp256k1.SIGNATURE_LENGTH]; var privateKeyBytes = new byte[Secp256k1.PRIVKEY_LENGTH]; privateKey.ByteArray.CopyTo( privateKeyBytes, Secp256k1.PRIVKEY_LENGTH - privateKey.ByteArray.Length); _instance.Sign( secp256K1Signature, messageHash.ToByteArray(), privateKeyBytes); var signature = new byte[Secp256k1.SERIALIZED_DER_SIGNATURE_MAX_SIZE]; _instance.SignatureSerializeDer( signature, secp256K1Signature, out int signatureLength); return(signature.Take(signatureLength).ToArray()); } }
/// <inheritdoc/> public override void SetBlockStates( HashDigest <SHA256> blockHash, IImmutableDictionary <Address, IValue> states) { _statesCache.AddOrUpdate(blockHash, states); var serialized = new Bencodex.Types.Dictionary( states.Select(kv => new KeyValuePair <IKey, IValue>( new Binary(kv.Key.ToByteArray()), kv.Value ) ) ); using (var stream = new MemoryStream()) { _codec.Encode(serialized, stream); stream.Seek(0, SeekOrigin.Begin); UploadFile( BlockStateFileId(blockHash), ByteUtil.Hex(blockHash.ToByteArray()), stream ); } }
public bool Verify( HashDigest <T> messageHash, byte[] signature, PublicKey publicKey) { try { Asn1Sequence asn1Sequence = (Asn1Sequence)Asn1Object.FromByteArray(signature); var rs = new[] { ((DerInteger)asn1Sequence[0]).Value, ((DerInteger)asn1Sequence[1]).Value, }; var verifier = new ECDsaSigner(); verifier.Init(false, publicKey.KeyParam); return(verifier.VerifySignature(messageHash.ToByteArray(), rs[0], rs[1])); } catch (IOException) { return(false); } catch (Asn1ParsingException) { return(false); } }
internal ITrie GetTrie(HashDigest <SHA256> blockHash) => new MerkleTrie( _stateKeyValueStore, new HashNode( new HashDigest <SHA256>( _stateHashKeyValueStore.Get(blockHash.ToByteArray()))));
internal void SetStates <T>( Block <T> block, HashDigest <SHA256> stateRootHash) where T : IAction, new() { _stateHashKeyValueStore.Set( block.Hash.ToByteArray(), stateRootHash.ToByteArray()); }
public static void AssertBytesEqual <T>( HashDigest <T>?expected, HashDigest <T>?actual ) where T : HashAlgorithm { AssertBytesEqual(expected?.ToByteArray(), actual?.ToByteArray()); }
internal static void AssertBytesEqual <T>( HashDigest <T> expected, HashDigest <T> actual ) where T : HashAlgorithm { AssertBytesEqual(expected.ToByteArray(), actual.ToByteArray()); }
public override long AppendIndex(HashDigest <SHA256> hash) { var indexFile = new FileInfo(_indexPath); if (!indexFile.Directory.Exists) { indexFile.Directory.Create(); } using (Stream stream = indexFile.Open( FileMode.Append, FileAccess.Write)) { var offset = stream.Position; stream.Write(hash.ToByteArray(), 0, hash.ToByteArray().Length); return(offset / HashDigest <SHA256> .Size); } }
public void StoreTxReferences(TxId txId, HashDigest <SHA256> blockHash, long txNonce) { Insert("tx_references", new Dictionary <string, object> { ["tx_id"] = txId.ToByteArray(), ["tx_nonce"] = txNonce, ["block_hash"] = blockHash.ToByteArray(), }); }
public IAccountStateDelta EvaluateActions( HashDigest <SHA256> blockHash, long blockIndex, IAccountStateDelta previousStates, Address minerAddress, bool rehearsal = false ) { int seed = BitConverter.ToInt32(blockHash.ToByteArray(), 0) ^ (Signature.Empty() ? 0 : BitConverter.ToInt32(Signature, 0)); IAccountStateDelta states = previousStates; foreach (T action in Actions) { var context = new ActionContext( signer: Signer, miner: minerAddress, blockIndex: blockIndex, previousStates: states, randomSeed: unchecked (seed++), rehearsal: rehearsal ); try { states = action.Execute(context); } catch (Exception e) { if (!rehearsal) { throw; } var msg = $"The action {action} threw an exception during its " + "rehearsal. It is probably because the logic of the " + $"action {action} is not enough generic so that it " + "can cover every case including rehearsal mode.\n" + "The IActionContext.Rehearsal property also might be " + "useful to make the action can deal with the case of " + "rehearsal mode.\n" + "See also this exception's InnerException property."; throw new UnexpectedlyTerminatedTxRehearsalException( action, msg, e ); } } return(states); }
/// <inheritdoc/> public override void ForkBlockIndexes( Guid sourceChainId, Guid destinationChainId, HashDigest <SHA256> branchPoint) { HashDigest <SHA256>?genesisHash = IterateIndexes(sourceChainId, 0, 1) .Cast <HashDigest <SHA256>?>() .FirstOrDefault(); if (genesisHash is null || branchPoint.Equals(genesisHash)) { return; } ColumnFamilyHandle cf = GetColumnFamily(_chainDb, destinationChainId); var writeBatch = new WriteBatch(); long index = 0; try { foreach (Iterator it in IterateDb(_chainDb, IndexKeyPrefix, sourceChainId)) { byte[] hashBytes = it.Value(); writeBatch.Put(it.Key(), hashBytes, cf); index += 1; if (writeBatch.Count() >= ForkWriteBatchSize) { _chainDb.Write(writeBatch); writeBatch.Dispose(); writeBatch = new WriteBatch(); } if (branchPoint.ToByteArray().SequenceEqual(hashBytes)) { break; } } } finally { _chainDb.Write(writeBatch); writeBatch.Dispose(); } _chainDb.Put( IndexCountKey, RocksDBStoreBitConverter.GetBytes(index), cf ); }
/// <inheritdoc/> public void SetBlockStates( HashDigest <SHA256> blockHash, AddressStateMap states) { using (var stream = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(stream, states); stream.Seek(0, SeekOrigin.Begin); _db.FileStorage.Upload( BlockStateFileId(blockHash), ByteUtil.Hex(blockHash.ToByteArray()), stream); } }
public bool Verify( HashDigest <T> messageHash, byte[] signature, PublicKey publicKey) { lock (_instanceLock) { var secp256K1Signature = new byte[64]; _instance.SignatureParseDer(secp256K1Signature, signature); byte[] secp256K1PublicKey = new byte[64]; byte[] serializedPublicKey = publicKey.Format(false); _instance.PublicKeyParse(secp256K1PublicKey, serializedPublicKey); return(_instance.Verify(secp256K1Signature, messageHash.ToByteArray(), secp256K1PublicKey)); } }
public IValue?GetState( string stateKey, HashDigest <SHA256>?blockHash = null, Guid?chainId = null) { if (blockHash is null) { throw new ArgumentNullException(nameof(blockHash)); } var stateHash = _stateHashKeyValueStore.Get(blockHash?.ToByteArray() !); var stateTrie = new MerkleTrie( _stateKeyValueStore, new HashNode(new HashDigest <SHA256>(stateHash))); var key = Encoding.UTF8.GetBytes(stateKey); return(stateTrie.TryGet(key, out IValue? value) ? value : null); }
/// <inheritdoc/> public override long AppendIndex(Guid chainId, HashDigest <SHA256> hash) { long index = CountIndex(chainId); byte[] indexBytes = RocksDBStoreBitConverter.GetBytes(index); byte[] key = IndexKeyPrefix.Concat(indexBytes).ToArray(); ColumnFamilyHandle cf = GetColumnFamily(_chainDb, chainId); using var writeBatch = new WriteBatch(); writeBatch.Put(key, hash.ToByteArray(), cf); writeBatch.Put(IndexCountKey, RocksDBStoreBitConverter.GetBytes(index + 1), cf); _chainDb.Write(writeBatch); return(index); }
/// <summary> /// Executes the <paramref name="actions"/> step by step, and emits /// <see cref="ActionEvaluation"/> for each step. /// </summary> /// <param name="blockHash">The <see cref="Block{T}.Hash"/> of <see cref="Block{T}"/> that /// <paramref name="actions"/> belongs to.</param> /// <param name="blockIndex">The <see cref="Block{T}.Index"/> of <see cref="Block{T}"/> that /// <paramref name="actions"/> belongs to.</param> /// <param name="txid">The <see cref="Transaction{T}.Id"/> of <see cref="Transaction{T}"/> /// that <paramref name="actions"/> belongs to. This can be <c>null</c> on rehearsal mode /// or if an action is a <see cref="IBlockPolicy{T}.BlockAction"/>.</param> /// <param name="previousStates">The states immediately before <paramref name="actions"/> /// being executed. Note that its <see cref="IAccountStateDelta.UpdatedAddresses"/> are /// remained to the returned next states.</param> /// <param name="minerAddress">An address of block miner.</param> /// <param name="signer">Signer of the <paramref name="actions"/>.</param> /// <param name="signature"><see cref="Transaction{T}"/> signature used to generate random /// seeds.</param> /// <param name="actions">Actions to evaluate.</param> /// <param name="rehearsal">Pass <c>true</c> if it is intended /// to be dry-run (i.e., the returned result will be never used). /// The default value is <c>false</c>.</param> /// <param name="previousBlockStatesTrie">The trie to contain states at previous block. /// </param> /// <param name="blockAction">Pass <c>true</c> if it is /// <see cref="IBlockPolicy{T}.BlockAction"/>.</param> /// <returns>Enumerates <see cref="ActionEvaluation"/>s for each one in /// <paramref name="actions"/>. The order is the same to the <paramref name="actions"/>. /// Note that each <see cref="IActionContext.Random"/> object /// has a unconsumed state. /// </returns> internal static IEnumerable <ActionEvaluation> EvaluateActionsGradually( HashDigest <SHA256> blockHash, long blockIndex, TxId?txid, IAccountStateDelta previousStates, Address minerAddress, Address signer, byte[] signature, IImmutableList <IAction> actions, bool rehearsal = false, ITrie previousBlockStatesTrie = null, bool blockAction = false) { ActionContext CreateActionContext( IAccountStateDelta prevStates, int randomSeed ) => new ActionContext( signer: signer, miner: minerAddress, blockIndex: blockIndex, previousStates: prevStates, randomSeed: randomSeed, rehearsal: rehearsal, previousBlockStatesTrie: previousBlockStatesTrie, blockAction: blockAction ); byte[] hashedSignature; using (var hasher = SHA1.Create()) { hashedSignature = hasher.ComputeHash(signature); } int seed = BitConverter.ToInt32(blockHash.ToByteArray(), 0) ^ (signature.Any() ? BitConverter.ToInt32(hashedSignature, 0) : 0); IAccountStateDelta states = previousStates; Exception exc = null; foreach (IAction action in actions) { ActionContext context = CreateActionContext(states, seed); IAccountStateDelta nextStates = context.PreviousStates; try { DateTimeOffset actionExecutionStarted = DateTimeOffset.Now; nextStates = action.Execute(context); TimeSpan spent = DateTimeOffset.Now - actionExecutionStarted; Log.Verbose($"{action} execution spent {spent.TotalMilliseconds} ms."); } catch (Exception e) { if (rehearsal) { var msg = $"The action {action} threw an exception during its " + "rehearsal. It is probably because the logic of the " + $"action {action} is not enough generic so that it " + "can cover every case including rehearsal mode.\n" + "The IActionContext.Rehearsal property also might be " + "useful to make the action can deal with the case of " + "rehearsal mode.\n" + "See also this exception's InnerException property."; exc = new UnexpectedlyTerminatedActionException( null, null, null, null, action, msg, e ); } else { var stateRootHash = context.PreviousStateRootHash; var msg = $"The action {action} (block #{blockIndex} {blockHash}, tx {txid}, " + $"state root hash {stateRootHash}) threw an exception " + "during execution. See also this exception's InnerException property."; Log.Error("{Message}\nInnerException: {ExcMessage}", msg, e.Message); exc = new UnexpectedlyTerminatedActionException( blockHash, blockIndex, txid, stateRootHash, action, msg, e ); } } // As IActionContext.Random is stateful, we cannot reuse // the context which is once consumed by Execute(). ActionContext equivalentContext = CreateActionContext(states, seed); yield return(new ActionEvaluation( action, equivalentContext, nextStates, exc )); states = nextStates; unchecked { seed++; } } }
private byte[] BlockStateKey(HashDigest <SHA256> blockHash) { return(BlockStateKeyPrefix.Concat(blockHash.ToByteArray()).ToArray()); }
public bool ContainsBlockStates(HashDigest <SHA256> blockHash) { return(_stateHashKeyValueStore.Exists(blockHash.ToByteArray())); }
public HashDigest <SHA256> GetRootHash(HashDigest <SHA256> blockHash) => new HashDigest <SHA256>(_stateHashKeyValueStore.Get(blockHash.ToByteArray()));
EvaluateActionsGradually( HashDigest <SHA256> blockHash, long blockIndex, IAccountStateDelta previousStates, Address minerAddress, bool rehearsal = false ) { ActionContext CreateActionContext( IAccountStateDelta prevStates, int randomSeed ) => new ActionContext( signer: Signer, miner: minerAddress, blockIndex: blockIndex, previousStates: prevStates, randomSeed: randomSeed, rehearsal: rehearsal ); int seed = BitConverter.ToInt32(blockHash.ToByteArray(), 0) ^ (Signature.Any() ? BitConverter.ToInt32(Signature, 0) : 0); IAccountStateDelta states = previousStates; foreach (T action in Actions) { ActionContext context = CreateActionContext(states, seed); IAccountStateDelta nextStates; try { nextStates = action.Execute(context); } catch (Exception e) { if (!rehearsal) { throw; } var msg = $"The action {action} threw an exception during its " + "rehearsal. It is probably because the logic of the " + $"action {action} is not enough generic so that it " + "can cover every case including rehearsal mode.\n" + "The IActionContext.Rehearsal property also might be " + "useful to make the action can deal with the case of " + "rehearsal mode.\n" + "See also this exception's InnerException property."; throw new UnexpectedlyTerminatedTxRehearsalException( action, msg, e ); } // As IActionContext.Random is stateful, we cannot reuse // the context which is once consumed by Execute(). ActionContext equivalentContext = CreateActionContext(states, seed); yield return(new ActionEvaluation <T>( action, equivalentContext, nextStates )); states = nextStates; unchecked { seed++; } } }
/// <summary> /// Executes the <paramref name="actions"/> step by step, and emits /// <see cref="ActionEvaluation"/> for each step. /// </summary> /// <param name="blockHash">The <see cref="Block{T}.Hash"/> of <see cref="Block{T}"/> that /// <paramref name="actions"/> belongs to.</param> /// <param name="blockIndex">The <see cref="Block{T}.Index"/> of <see cref="Block{T}"/> that /// <paramref name="actions"/> belongs to.</param> /// <param name="txid">The <see cref="Transaction{T}.Id"/> of <see cref="Transaction{T}"/> /// that <paramref name="actions"/> belongs to. This can be <c>null</c> on rehearsal mode /// or if an action is a <see cref="IBlockPolicy{T}.BlockAction"/>.</param> /// <param name="previousStates">The states immediately before <paramref name="actions"/> /// being executed. Note that its <see cref="IAccountStateDelta.UpdatedAddresses"/> are /// remained to the returned next states.</param> /// <param name="minerAddress">An address of block miner.</param> /// <param name="signer">Signer of the <paramref name="actions"/>.</param> /// <param name="signature"><see cref="Transaction{T}"/> signature used to generate random /// seeds.</param> /// <param name="actions">Actions to evaluate.</param> /// <param name="rehearsal">Pass <c>true</c> if it is intended /// to be dry-run (i.e., the returned result will be never used). /// The default value is <c>false</c>.</param> /// <returns>Enumerates <see cref="ActionEvaluation"/>s for each one in /// <paramref name="actions"/>. The order is the same to the <paramref name="actions"/>. /// Note that each <see cref="IActionContext.Random"/> object /// has a unconsumed state. /// </returns> internal static IEnumerable <ActionEvaluation> EvaluateActionsGradually( HashDigest <SHA256> blockHash, long blockIndex, TxId?txid, IAccountStateDelta previousStates, Address minerAddress, Address signer, byte[] signature, IImmutableList <IAction> actions, bool rehearsal = false) { ActionContext CreateActionContext( IAccountStateDelta prevStates, int randomSeed ) => new ActionContext( signer: signer, miner: minerAddress, blockIndex: blockIndex, previousStates: prevStates, randomSeed: randomSeed, rehearsal: rehearsal ); byte[] hashedSignature; using (var hasher = SHA1.Create()) { hashedSignature = hasher.ComputeHash(signature); } int seed = BitConverter.ToInt32(blockHash.ToByteArray(), 0) ^ (signature.Any() ? BitConverter.ToInt32(hashedSignature, 0) : 0); IAccountStateDelta states = previousStates; Exception exc = null; foreach (IAction action in actions) { ActionContext context = CreateActionContext(states, seed); IAccountStateDelta nextStates = context.PreviousStates; try { nextStates = action.Execute(context); } catch (Exception e) { string msg; if (!rehearsal) { // FIXME: The below "exc" object seems never used; Hong Minhee believes // this code's behavior does not follow the intention. msg = $"The action {action} (block #{blockIndex} {blockHash}, tx {txid}) " + "threw an exception during execution. See also this exception's " + "InnerException property."; exc = new UnexpectedlyTerminatedActionException( blockHash, blockIndex, txid, action, msg, e ); } msg = $"The action {action} threw an exception during its " + "rehearsal. It is probably because the logic of the " + $"action {action} is not enough generic so that it " + "can cover every case including rehearsal mode.\n" + "The IActionContext.Rehearsal property also might be " + "useful to make the action can deal with the case of " + "rehearsal mode.\n" + "See also this exception's InnerException property."; exc = new UnexpectedlyTerminatedActionException( null, null, null, action, msg, e ); } // As IActionContext.Random is stateful, we cannot reuse // the context which is once consumed by Execute(). ActionContext equivalentContext = CreateActionContext(states, seed); yield return(new ActionEvaluation( action, equivalentContext, nextStates, exc )); states = nextStates; unchecked { seed++; } } }
private INode?GetNode(HashDigest <SHA256> nodeHash) { return(NodeDecoder.Decode( _codec.Decode(KeyValueStore.Get(nodeHash.ToByteArray())))); }
public static IValue Serialize(this HashDigest <SHA256> hashDigest) { return(new Binary(hashDigest.ToByteArray())); }