/// <summary> /// Helper method. Convert a value to a key value /// </summary> /// <param name="value"> </param> /// <param name="info"> </param> /// <returns> </returns> public static KeyValue ValueToKeyValue(object value, KeyInfo info) { //check if directly assignable to int if (info.KeyDataType == KeyDataType.IntKey) { // default behavior for nullable values (works fine for dates) if (value == null) { return(new KeyValue(0, info)); } var propertyType = value.GetType(); //integer types if (propertyType == typeof(int) || propertyType == typeof(short) || propertyType == typeof(long) || propertyType == typeof(byte) || propertyType == typeof(char) || propertyType == typeof(bool) || propertyType == typeof(IntPtr)) { var longVal = Convert.ToInt64(value); return(new KeyValue(longVal, info)); } if (propertyType.IsEnum) { var longVal = Convert.ToInt64(value); return(new KeyValue(longVal, info)); } //other types. Can be used as keys if a key converter is provided var converter = KeyConverters.GetIfAvailable(propertyType); if (converter != null) { //prefer conversion to long if available if (converter.CanConvertToLong) { return(new KeyValue(converter.GetAsLong(value), info)); } if (converter.CanConvertToString) { return(new KeyValue(converter.GetAsString(value), info)); } Dbg.CheckThat(false, "trying to use an invalid key converter"); } } else { if (value != null) { return(new KeyValue(value.ToString(), info)); } return(new KeyValue(null, info)); } throw new InvalidOperationException($"Can not compute key value for object {value}"); }
public void ExecuteActions() { (var addresses, Transaction <DumbAction>[] txs) = MakeFixturesForAppendTests(); var genesis = _blockChain.Genesis; Block <DumbAction> block1 = MineNext( genesis, _policy.GetHashAlgorithm, txs, miner: _fx.Miner.PublicKey, difficulty: _policy.GetNextBlockDifficulty(_blockChain) ).Evaluate(_fx.Miner, _blockChain); _blockChain.Append( block1, evaluateActions: false, renderBlocks: true, renderActions: false ); var minerAddress = genesis.Miner; var expectedStates = new Dictionary <Address, IValue> { { addresses[0], (Text)"foo" }, { addresses[1], (Text)"bar" }, { addresses[2], (Text)"baz" }, { addresses[3], (Text)"qux" }, { minerAddress, (Integer)2 }, { MinerReward.RewardRecordAddress, (Text)$"{minerAddress},{minerAddress}" }, }; _blockChain.ExecuteActions(block1); foreach (KeyValuePair <Address, IValue> pair in expectedStates) { AssertBencodexEqual( pair.Value, _fx.StateStore.GetStates( block1.StateRootHash, new[] { KeyConverters.ToStateKey(pair.Key) } )[0] ); } }
public TxWithContext Sign(PrivateKey signer, params Arithmetic[] actions) { Address signerAddress = signer.ToAddress(); string rawStateKey = KeyConverters.ToStateKey(signerAddress); long nonce = Chain.GetNextTxNonce(signerAddress); Transaction <Arithmetic> tx = Transaction <Arithmetic> .Create(nonce, signer, Genesis.Hash, actions); BigInteger prevState = Chain.GetState(signerAddress) is Bencodex.Types.Integer i ? i.Value : 0; HashDigest <SHA256> prevStateRootHash = Chain.Tip.StateRootHash; ITrie prevTrie = GetTrie(Chain.Tip.Hash); (BigInteger, HashDigest <SHA256>)prevPair = (prevState, prevStateRootHash); (BigInteger, HashDigest <SHA256>)stagedStates = Chain.ListStagedTransactions() .Where(t => t.Signer.Equals(signerAddress)) .OrderBy(t => t.Nonce) .SelectMany(t => t.Actions) .TakeWhile(a => a.Error is null) .Aggregate(prevPair, (prev, act) => { BigInteger nextState = act.Operator.ToFunc()(prev.Item1, act.Operand); var updatedRawStates = ImmutableDictionary <string, IValue> .Empty .Add(rawStateKey, (Bencodex.Types.Integer)nextState); HashDigest <SHA256> nextRootHash = prevTrie.Set(updatedRawStates).Commit().Hash; return(nextState, nextRootHash); }); Chain.StageTransaction(tx); ImmutableArray <(BigInteger, HashDigest <SHA256>)> expectedDelta = tx.Actions .Take(tx.Actions.TakeWhile(a => a.Error is null).Count() + 1) .Aggregate( ImmutableArray.Create(stagedStates), (delta, act) => { BigInteger nextState = act.Operator.ToFunc()(delta[delta.Length - 1].Item1, act.Operand); var updatedRawStates = ImmutableDictionary <string, IValue> .Empty .Add(rawStateKey, (Bencodex.Types.Integer)nextState); HashDigest <SHA256> nextRootHash = prevTrie.Set(updatedRawStates).Commit().Hash; return(delta.Add((nextState, nextRootHash))); }