예제 #1
0
        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;
        }
예제 #3
0
        public static void ShouldHexEncodeEmpty()
        {
            Span <byte> input  = default;
            var         result = HexHelpers.HexEncodeBigEndian(input);

            Assert.Empty(result);
        }
예제 #4
0
        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);
        }
예제 #5
0
        /* ---------------------------------------------------------------------------------------------------------- */

        #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;
        }
예제 #6
0
        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] })
            });
        }
예제 #7
0
        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());
        }
예제 #8
0
    /// <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();
        }
    }
예제 #9
0
        public static void ShouldReturnEmptyTryHexEncodeEmpty()
        {
            Span <byte> input  = default;
            Span <char> buffer = default;
            var         result = HexHelpers.TryHexEncodeBigEndian(input, buffer);

            Assert.True(result);
        }
예제 #10
0
 public static void FromHex(this IBitcoinSerializable me, string hex)
 {
     if (me == null)
     {
         throw new ArgumentNullException(nameof(me));
     }
     me.FromBytes(HexHelpers.GetBytes(hex));
 }
예제 #11
0
        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);
        }
예제 #12
0
        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);
        }
예제 #13
0
        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);
        }
예제 #14
0
        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());
            }
        }
예제 #15
0
    /* ---------------------------------------------------------------------------------------------------------- */

    #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;
    }
예제 #16
0
        /// <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);
            }
        }
예제 #17
0
        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
                }));
            }
        }
예제 #18
0
        public void ShouldReturnFalseIfBufferIsTooSmall()
        {
            Span <char> buffer = stackalloc char[1];

            Assert.False(HexHelpers.TryHexEncode(new byte[2], buffer));
        }
예제 #19
0
 public static string ToHex(this IBitcoinSerializable me)
 {
     return(HexHelpers.ToString(me.ToBytes()));
 }
예제 #20
0
        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
                }));
            }
        }
예제 #21
0
    /// <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);
    }