public void ShouldNotClobberSurroundingData() { Span <char> buffer = stackalloc char[] { 'Q', 'Q', 'Q', 'Q' }; Assert.True(HexHelpers.TryHexEncode(new byte[] { 0x66 }, buffer.Slice(1, 2))); Assert.Equal("Q66Q", buffer.ToString()); }
public PreviewSPC(Config config, byte[] sampleDirectory, byte[] brrDump, EBMFile song) { var result = FileIO.GetDummySPC(); //TODO: Make a class that runs GetDummySPC and has a .PatchData(byte[] , offset) method *in* it //Make the sound engine think that the new song is being loaded, so it'll reset all the patterns result = PatchData(result, Padding(0x00, 1), 0x08); //Make it so this SPC's song index (song 0x53) knows to look for the note data at whatever offset it needs to be in result = PatchData(result, HexHelpers.UInt16toByteArray_LittleEndian(song.aramOffset), 0x2EEE); //Zero out a few locations to make sure there aren't garbage notes playing in any of the channels var padding = Padding(0x00, 2); for (uint offset = 0x010000; offset <= 0x010070; offset += 0x10) { result = PatchData(result, padding, offset); } //Patch in all of the data generated by this program, as well as the song data result = PatchData(result, sampleDirectory, config.offsetForSampleDir); result = PatchData(result, brrDump, config.offsetForBRRdump); result = PatchData(result, config.GetPatches(), config.offsetForInstrumentConfig); result = PatchData(result, song.data, song.aramOffset); filedata = result; }
public static void ShouldHexEncodeEmpty() { Span <byte> input = default; var result = HexHelpers.HexEncodeBigEndian(input); Assert.Empty(result); }
public static void ShouldHexEncodeBigEndian() { var input = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; var result = HexHelpers.HexEncodeBigEndian(input); Assert.Equal("100F0E0D0C0B0A09080706050403020100", result); }
/* ---------------------------------------------------------------------------------------------------------- */ #region Constructors/Initialisation /// <summary> /// Creates a new movement action for the specified unit. /// </summary> /// <param name="unit">The unit this action is attached to.</param> /// <param name="startPosition">The initial position to start this action from.</param> /// <param name="distance">The total distance of the movement.</param> /// <param name="startRotation">The initial rotation to start this action from.</param> /// <param name="endRotation">The end rotation for this movement action.</param> /// <param name="speedModifier">The movement speed modifier.</param> internal UnitMovement(BattleUnit unit, Vector3 startPosition, Vector3 endPosition, BattleHex currentTile, HexDirection startDirection, HexDirection endDirection, float startRotation, float endRotation, float speedModifier) : base(unit) { this._startPosition = startPosition; this._endPosition = endPosition; this._endTile = currentTile; this._endFacingDirection = endDirection; if (startDirection != endDirection) { HexDirection between = HexHelpers.DirectionBetween(startDirection, endDirection); this._rotateAround = currentTile.GetNeighbourPosition(between); this._startRotation = startRotation; this._endRotation = endRotation; float rotation = endRotation - startRotation; while (rotation <= 0f) { rotation += 360f; } this._rotationAngle = rotation; } this._speedModifier = speedModifier; this._lerpValue = 0f; }
public static Item ParseHex(byte[] input) { int offsetTemp = BitConverter.ToUInt16(new byte[] { input[0], input[1] }, 0); offsetTemp -= 0x7FF0; //The ROM byte array will be headerless, but this is a value that people will compare to an open hex editor, where the header *will* be present. So we still need to do this, right? var attributesTemp = HexHelpers.InterpretByteAsBools(input[2]); var thirdByte = new PowerTypeCombo(input[3]); return(new Item { NameTextOffset = offsetTemp.ToString("X4"), NintenUsable = attributesTemp[0], AnaUsable = attributesTemp[1], LloydUsable = attributesTemp[2], TeddyUsable = attributesTemp[3], Unknown1 = attributesTemp[4], Unknown2 = attributesTemp[5], Edible = attributesTemp[6], Permanent = attributesTemp[7], Power = thirdByte.Power, Type = thirdByte.Type, EffectOutsideOfBattle = input[4], EffectInBattle = input[5], Price = BitConverter.ToUInt16(new byte[] { input[6], input[7] }) }); }
public void ShouldEncodeToHex(byte[] input, string expected) { Span <char> buffer = stackalloc char[expected.Length]; Assert.True(HexHelpers.TryHexEncode(input, buffer)); Assert.Equal(expected, buffer.ToString()); }
/// <summary> /// Tells the unit to follow the specified path, then attack the unit at the end of the path. /// </summary> /// <param name="path">The path to be followed by this unit</param> /// <param name="unit">The unit to be attacked at the end of the path</param> public void TravelPathAndAttack(List <BattleHex> path, BattleUnit unit) { HexDirection finalFacingDirection = TravelPath(path); BattleHex unitTile; //this._actions.la if (path.Count > 1) { unitTile = path[path.Count - 1]; } else { unitTile = _currentHex; } HexDirection requiredDirection = HexHelpers.GetTargetDirection(unitTile, unit.CurrentHexTile); if (requiredDirection != finalFacingDirection) { this._actions.Enqueue(new UnitRotation(this, HexHelpers.GetTargetDegrees(HexHelpers.ReverseDirection(finalFacingDirection)), HexHelpers.GetTargetDegrees(requiredDirection))); } this._actions.Enqueue(new UnitAttack(this, unit)); if (this._currentAction == null) { this._currentAction = this._actions.Dequeue(); } }
public static void ShouldReturnEmptyTryHexEncodeEmpty() { Span <byte> input = default; Span <char> buffer = default; var result = HexHelpers.TryHexEncodeBigEndian(input, buffer); Assert.True(result); }
public static void FromHex(this IBitcoinSerializable me, string hex) { if (me == null) { throw new ArgumentNullException(nameof(me)); } me.FromBytes(HexHelpers.GetBytes(hex)); }
public static void ShouldReturnFalseForIncompleteBuffer() { Span <byte> input = new byte[] { 1, 2, 3 }; Span <char> buffer = new char[1]; var result = HexHelpers.TryHexEncodeBigEndian(input, buffer); Assert.False(result); }
public static void ShouldHexEncodeBigEndianExceedingStackLimit() { Span <byte> input = new byte[10 * 1024 * 1024]; //A 10 MB string would normally blow the stack. input.Fill(1); var result = HexHelpers.HexEncodeBigEndian(input); Assert.Equal(input.Length * 2, result.Length); }
public void CanEncodeDecodeBlinding() { var key = new BlindingRsaKey(); byte[] message = Encoding.UTF8.GetBytes("áéóúősing me please~!@#$%^&*())_+"); byte[] blindedData = key.PubKey.Blind(message).BlindedData; string encoded = HexHelpers.ToString(blindedData); byte[] decoded = HexHelpers.GetBytes(encoded); Assert.Equal(blindedData, decoded); }
public void ShouldTranslateAllValues() { Span <char> buffer = stackalloc char[2]; Span <byte> value = stackalloc byte[1]; for (var i = 0; i <= 0xFF; i++) { value[0] = (byte)i; Assert.True(HexHelpers.TryHexEncode(value, buffer)); Assert.Equal(i.ToString("X2"), buffer.ToString()); } }
/* ---------------------------------------------------------------------------------------------------------- */ #region Internal Methods /// <summary> /// Initialises the unit with the provided tile and sets the starting rotation. /// </summary> /// <param name="battleGrid">The battle grid that manages all tiles.</param> /// <param name="tile">The starting tile.</param> /// <param name="yRotation">The starting rotation.</param> internal void InitialiseWithTile(BattleGrid battleGrid, BattleHex tile, float yRotation) { this.BattleGrid = battleGrid; this.CurrentHexTile = tile; this.transform.position = tile.transform.position; this._rotation.y = yRotation; _facingDirection = HexHelpers.GetRotationDirection(yRotation); this.transform.rotation = Quaternion.Euler(this._rotation); tile.Unit = this; }
/// <summary> /// Performs the standard unit rotation. /// </summary> internal override void Perform() { Vector3 currentRotation = base.unit.transform.rotation.eulerAngles; currentRotation.y = Mathf.LerpAngle(this._startRotation, this._endRotation, this._lerpValue); base.unit.transform.rotation = Quaternion.Euler(currentRotation); if (this._lerpValue >= 1f) { base.unit.FacingDirection = HexHelpers.ReverseDirection(HexHelpers.GetRotationDirection(this._endRotation)); base.FinishAction(); } else { this._lerpValue += (Time.deltaTime * base.unit._standingRotationSpeed); } }
public async Task <IActionResult> InputsAsync([FromBody] InputsRequest request) { var roundId = Global.StateMachine.RoundId; TumblerPhase phase = TumblerPhase.InputRegistration; try { if (Global.StateMachine.Phase != TumblerPhase.InputRegistration || !Global.StateMachine.AcceptRequest) { return(new ObjectResult(new FailureResponse { Message = "Wrong phase" })); } // Check not nulls string blindedOutputString = request.BlindedOutput.Trim(); if (string.IsNullOrWhiteSpace(blindedOutputString)) { return(new BadRequestResult()); } if (string.IsNullOrWhiteSpace(request.ChangeOutput)) { return(new BadRequestResult()); } if (request.Inputs == null || request.Inputs.Count() == 0) { return(new BadRequestResult()); } // Check format (parse everyting)) if (Global.StateMachine.BlindedOutputs.Contains(blindedOutputString)) { throw new ArgumentException("Blinded output has already been registered"); } byte[] blindedOutput = HexHelpers.GetBytes(blindedOutputString); Network network = Global.Config.Network; var changeOutput = new BitcoinWitPubKeyAddress(request.ChangeOutput, expectedNetwork: network); if (request.Inputs.Count() > Global.Config.MaximumInputsPerAlices) { throw new NotSupportedException("Too many inputs provided"); } var inputs = new HashSet <(TxOut Output, OutPoint OutPoint)>(); var alicesToRemove = new HashSet <Guid>(); using (await InputRegistrationLock.LockAsync()) { foreach (InputProofModel input in request.Inputs) { var op = new OutPoint(); op.FromHex(input.Input); if (inputs.Any(x => x.OutPoint.Hash == op.Hash && x.OutPoint.N == op.N)) { throw new ArgumentException("Attempting to register an input twice is not permitted"); } foreach (var a in Global.StateMachine.Alices) { if (a.Inputs.Any(x => x.OutPoint.Hash == op.Hash && x.OutPoint.N == op.N)) { alicesToRemove.Add(a.UniqueId); // input is already registered by this alice, remove it if all the checks are completed fine } } BannedUtxo banned = Global.UtxoReferee.Utxos.FirstOrDefault(x => x.Utxo.Hash == op.Hash && x.Utxo.N == op.N); if (banned != default(BannedUtxo)) { var maxBan = (int)TimeSpan.FromDays(30).TotalMinutes; int banLeft = maxBan - (int)((DateTimeOffset.UtcNow - banned.TimeOfBan).TotalMinutes); throw new ArgumentException($"Input is banned for {banLeft} minutes"); } var getTxOutResponse = await Global.RpcClient.GetTxOutAsync(op.Hash, (int)op.N, true); // Check if inputs are unspent if (getTxOutResponse == null) { throw new ArgumentException("Provided input is not unspent"); } // Check if inputs are unconfirmed, if so check if they are part of previous CoinJoin if (getTxOutResponse.Confirmations <= 0) { if (!Global.CoinJoinStore.Transactions .Any(x => x.State >= CoinJoinTransactionState.Succeeded && x.Transaction.GetHash() == op.Hash)) { throw new ArgumentException("Provided input is not confirmed, nor spends a previous CJ transaction"); } else { // after 24 unconfirmed cj in the mempool dont't let unconfirmed coinjoin to be registered var unconfirmedCoinJoins = Global.CoinJoinStore.Transactions.Where(x => x.State == CoinJoinTransactionState.Succeeded); if (unconfirmedCoinJoins.Count() >= 24) { var toFailed = new HashSet <uint256>(); var toConfirmed = new HashSet <uint256>(); foreach (var tx in unconfirmedCoinJoins) { RPCResponse getRawTransactionResponse = (await Global.RpcClient.SendCommandAsync("getrawtransaction", tx.Transaction.GetHash().ToString(), true)); if (string.IsNullOrWhiteSpace(getRawTransactionResponse?.ResultString)) { toFailed.Add(tx.Transaction.GetHash()); } if (getRawTransactionResponse.Result.Value <int>("confirmations") > 0) { toConfirmed.Add(tx.Transaction.GetHash()); } } foreach (var tx in toFailed) { Global.CoinJoinStore.TryUpdateState(tx, CoinJoinTransactionState.Failed); } foreach (var tx in toConfirmed) { Global.CoinJoinStore.TryUpdateState(tx, CoinJoinTransactionState.Confirmed); } if (toFailed.Count + toConfirmed.Count > 0) { await Global.CoinJoinStore.ToFileAsync(Global.CoinJoinStorePath); } // if couldn't remove any unconfirmed tx then refuse registration if (Global.CoinJoinStore.Transactions.Count(x => x.State == CoinJoinTransactionState.Succeeded) >= 24) { throw new ArgumentException("Registering unconfirmed CJ transaction output is currently not allowed due to too long mempool chain"); } } } } // Check coinbase > 100 if (getTxOutResponse.Confirmations < 100) { if (getTxOutResponse.IsCoinBase) { throw new ArgumentException("Provided input is unspendable"); } } // Check if inputs are native segwit if (getTxOutResponse.ScriptPubKeyType != "witness_v0_keyhash") { throw new ArgumentException("Provided input is not witness_v0_keyhash"); } var txout = getTxOutResponse.TxOut; var address = (BitcoinWitPubKeyAddress)txout.ScriptPubKey.GetDestinationAddress(network); // Check if proofs are valid var validProof = address.VerifyMessage(blindedOutputString, input.Proof); if (!validProof) { throw new ArgumentException("Provided proof is invalid"); } inputs.Add((txout, op)); } // Check if inputs have enough coins Money amount = Money.Zero; foreach (Money val in inputs.Select(x => x.Output.Value)) { amount += val; } Money feeToPay = (inputs.Count() * Global.StateMachine.FeePerInputs + 2 * Global.StateMachine.FeePerOutputs); Money changeAmount = amount - (Global.StateMachine.Denomination + feeToPay); if (changeAmount < Money.Zero + new Money(548)) // 546 is dust { throw new ArgumentException("Total provided inputs must be > denomination + fee + dust"); } byte[] signature = Global.RsaKey.SignBlindedData(blindedOutput); Global.StateMachine.BlindedOutputs.Add(blindedOutputString); Guid uniqueId = Guid.NewGuid(); var alice = new Alice { UniqueId = uniqueId, ChangeOutput = changeOutput, ChangeAmount = changeAmount, State = AliceState.InputsRegistered }; alice.Inputs = new ConcurrentHashSet <(TxOut Output, OutPoint OutPoint)>(); foreach (var input in inputs) { alice.Inputs.Add(input); } AssertPhase(roundId, phase); foreach (var aliceToRemove in alicesToRemove) { if (Global.StateMachine.TryRemoveAlice(aliceToRemove)) { await Global.StateMachine.BroadcastPeerRegisteredAsync(); } } Global.StateMachine.Alices.Add(alice); await Global.StateMachine.BroadcastPeerRegisteredAsync(); if (Global.StateMachine.Alices.Count >= Global.StateMachine.AnonymitySet) { Global.StateMachine.UpdatePhase(TumblerPhase.ConnectionConfirmation); } TumblerStateMachine.EstimateInputAndOutputSizes(out int inputSizeInBytes, out int outputSizeInBytes); int estimatedTxSize = Global.StateMachine.Alices.SelectMany(x => x.Inputs).Count() * inputSizeInBytes + 2 * outputSizeInBytes; if (estimatedTxSize >= 90000) // standard transaction is < 100KB { Global.StateMachine.UpdatePhase(TumblerPhase.ConnectionConfirmation); } var ret = new ObjectResult(new InputsResponse() { UniqueId = uniqueId.ToString(), SignedBlindedOutput = HexHelpers.ToString(signature) }); return(ret); } } catch (Exception ex) { return(new ObjectResult(new FailureResponse { Message = ex.Message })); } }
public void ShouldReturnFalseIfBufferIsTooSmall() { Span <char> buffer = stackalloc char[1]; Assert.False(HexHelpers.TryHexEncode(new byte[2], buffer)); }
public static string ToHex(this IBitcoinSerializable me) { return(HexHelpers.ToString(me.ToBytes())); }
public IActionResult Output([FromBody] OutputRequest request) { var roundId = Global.StateMachine.RoundId; TumblerPhase phase = TumblerPhase.OutputRegistration; try { if (Global.StateMachine.Phase != TumblerPhase.OutputRegistration || !Global.StateMachine.AcceptRequest) { return(new ObjectResult(new FailureResponse { Message = "Wrong phase" })); } if (string.IsNullOrWhiteSpace(request.Output)) { return(new BadRequestResult()); } if (string.IsNullOrWhiteSpace(request.Signature)) { return(new BadRequestResult()); } if (string.IsNullOrWhiteSpace(request.RoundHash)) { return(new BadRequestResult()); } if (request.RoundHash != Global.StateMachine.RoundHash) { throw new ArgumentException("Wrong round hash provided"); } var output = new BitcoinWitPubKeyAddress(request.Output, expectedNetwork: Global.Config.Network); // if not already registered if (Global.StateMachine.Bobs.Any(x => x.Output == output)) { return(new ObjectResult(new SuccessResponse())); } if (Global.RsaKey.PubKey.Verify(HexHelpers.GetBytes(request.Signature), Encoding.UTF8.GetBytes(request.Output))) { try { AssertPhase(roundId, phase); Global.StateMachine.Bobs.Add(new Bob { Output = output }); return(new ObjectResult(new SuccessResponse())); } finally { if (Global.StateMachine.Alices.Count == Global.StateMachine.Bobs.Count) { Global.StateMachine.UpdatePhase(TumblerPhase.Signing); } } } else { throw new ArgumentException("Bad output"); } } catch (Exception ex) { return(new ObjectResult(new FailureResponse { Message = ex.Message })); } }
/// <summary> /// Tells the unit to follow the specified path. /// </summary> /// <param name="path">The path to be followed by this unit</param> public HexDirection TravelPath(List <BattleHex> path) { if (path.Count == 1) { return(_facingDirection); } float currentRotation = Mathf.Round(base.transform.eulerAngles.y); Vector3 startPosition = Vector3.zero; Vector3 endPosition = this.CurrentHexTile.WorldPosition; HexDirection facingDirection = _facingDirection; for (var i = 0; i < path.Count - 1; i++) { BattleHex current = path[i]; BattleHex next = path[i + 1]; HexDirection requiredDirection = HexHelpers.GetTargetDirection(current, next); float requiredRotation = HexHelpers.GetTargetDegrees(requiredDirection); if (i == 0 && currentRotation != requiredRotation) { _actions.Enqueue(new UnitRotation(this, currentRotation, requiredRotation)); currentRotation = requiredRotation; facingDirection = requiredDirection; } float distance = current.TileLength; float speedModifier = 1f; if (i == 0) { distance /= 2f; speedModifier = 2f; } startPosition = endPosition; endPosition = next.GetEdge(requiredDirection); HexDirection requiredFacingDirection = HexHelpers.ReverseDirection(requiredDirection); _actions.Enqueue(new UnitMovement(this, startPosition, endPosition, current, facingDirection, requiredFacingDirection, currentRotation, requiredRotation, speedModifier)); facingDirection = requiredFacingDirection; currentRotation = requiredRotation; } BattleHex endTile = path[path.Count - 1]; _actions.Enqueue(new UnitMovement(this, endPosition, endTile.transform.position, endTile, facingDirection, facingDirection, 0f, 0f, 2f)); this._currentAction = this._actions.Dequeue(); _battleGrid.UnhighlightNodes(); return(facingDirection); }