Ejemplo n.º 1
0
        public void RemoveProductionAndConsumption()
        {
            var sozu = new VolatileCoinStore();

            var inbox      = new BoundedInbox();
            var outbox     = new BoundedInbox();
            var controller = new CoinController(inbox, outbox, sozu, _hash);

            controller.Lineage = new MockLineage();

            var clientId = new ClientId();
            var reqId    = new RequestId(1);

            var coin = GetCoin(_rand);

            sozu.AddProduction(
                _hash.Hash(ref coin.Outpoint),
                ref coin.Outpoint,
                false, coin.Payload,
                new BlockAlias(2),
                null);

            sozu.AddConsumption(
                _hash.Hash(ref coin.Outpoint),
                ref coin.Outpoint,
                new BlockAlias(2),
                null);

            var buffer            = new byte[RemoveCoinRequest.SizeInBytes];
            var removeCoinRequest = new RemoveCoinRequest(
                buffer, reqId, ref coin.Outpoint, new BlockAlias(2).ConvertToBlockHandle(clientId.Mask), true, true);

            inbox.TryWrite(removeCoinRequest.Span);
            controller.HandleRequest();

            var raw = outbox.Peek();

            Assert.Equal(RemoveCoinResponse.SizeInBytes, raw.Length);
            var response = new RemoveCoinResponse(raw.Span);

            // verify response contents
            Assert.Equal(reqId, response.MessageHeader.RequestId);
            Assert.Equal(clientId, response.MessageHeader.ClientId);
            Assert.Equal(MessageKind.RemoveCoinResponse, response.MessageHeader.MessageKind);
            Assert.Equal(ChangeCoinStatus.Success, response.Status);

            sozu.TryGet(_hash.Hash(ref coin.Outpoint), ref coin.Outpoint, new BlockAlias(2), null, out var coin2,
                        out var pe, out var ce);

            Assert.False(pe.IsDefined);
            Assert.False(ce.IsDefined);
        }
Ejemplo n.º 2
0
        // DELETE: Transaction/RemoveCoin/RemoveCoinRequest
        public bool RemoveCoin([FromBody] RemoveCoinRequest request)
        {
            CibitDb      context = HttpContext.RequestServices.GetService(typeof(CibitDb)) as CibitDb;
            ValidateUser valid   = new ValidateUser();

            var config   = new MapperConfiguration(mc => mc.CreateMap <RemoveCoinRequest, TransactionDTO>());
            var mapper   = new Mapper(config);
            var userinfo = mapper.Map <RemoveCoinRequest, TransactionDTO>(request);

            valid.VerifyCoinId(userinfo.CoinId, userinfo.SenderId);

            var spObj  = Converters.RemoveCoinConverter(userinfo);
            var reader = context.StoredProcedureSql("RemoveCoin", spObj);

            context.Connection.Close();
            return(true);
        }
Ejemplo n.º 3
0
        public bool HandleRequest()
        {
            if (!_inbox.CanPeek)
            {
                return(false);
            }

            var next = _inbox.Peek().Span;

            try
            {
                var message   = new Message(next);
                var mask      = message.Header.ClientId.Mask;
                var kind      = message.Header.MessageKind;
                var requestId = message.Header.RequestId;
                var clientId  = message.Header.ClientId;

                if (!_connections.TryGetValue(clientId, out var connection))
                {
                    // Outdated message, drop and move on.
                    return(true);
                }

                if (!connection.Connected || kind == MessageKind.CloseConnection)
                {
                    // Client disconnected, drop message and remove connection.
                    _connections.Remove(clientId);
                    return(true);
                }

                if (kind.IsResponse())
                {
                    // Forward responses to their respective 'ConnectionController'.
                    connection.Send(next);
                    return(true);
                }

                if (kind.IsForCoinController())
                {
                    // Multiple coin controllers
                    Outpoint outpoint;
                    switch (kind)
                    {
                    case MessageKind.GetCoin:
                        outpoint = new GetCoinRequest(next, mask).Outpoint;
                        break;

                    case MessageKind.ProduceCoin:
                        outpoint = new ProduceCoinRequest(next, mask).Outpoint;
                        break;

                    case MessageKind.ConsumeCoin:
                        outpoint = new ConsumeCoinRequest(next, mask).Outpoint;
                        break;

                    case MessageKind.RemoveCoin:
                        outpoint = new RemoveCoinRequest(next, mask).Outpoint;
                        break;

                    default:
                        throw new NotSupportedException();
                    }

                    // Sharding based on the outpoint hash

                    // Beware: the factor 'BigPrime' is used to avoid accidental factor collision
                    // between the sharding performed at the dispatch controller level, and the
                    // sharding performed within the Sozu table.

                    // PERF: hashing the outpoint is repeated in the CoinController itself
                    const ulong BigPrime        = 1_000_000_007;
                    var         controllerIndex = (int)((_hash.Hash(ref outpoint) % BigPrime)
                                                        % (ulong)_coinControllerBoxes.Length);

                    var written = _coinControllerBoxes[controllerIndex].TryWrite(next);
                    if (written)
                    {
                        OnCoinMessageDispatched[controllerIndex]();
                    }
                    else
                    {
                        // Coin controller is saturated.
                        Span <byte> buffer       = stackalloc byte[ProtocolErrorResponse.SizeInBytes];
                        var         errorMessage = new ProtocolErrorResponse(
                            buffer, requestId, clientId, ProtocolErrorStatus.ServerBusy);

                        connection.Send(errorMessage.Span);
                    }

                    return(true);
                }

                {
                    // Block controller
                    var written = _chainControllerBox.TryWrite(next);
                    if (written)
                    {
                        OnBlockMessageDispatched();
                    }
                    else
                    {
                        // Block controller is saturated.
                        Span <byte> buffer       = stackalloc byte[ProtocolErrorResponse.SizeInBytes];
                        var         errorMessage = new ProtocolErrorResponse(
                            buffer, requestId, clientId, ProtocolErrorStatus.ServerBusy);

                        connection.Send(errorMessage.Span);
                    }
                }
            }
            finally
            {
                _inbox.Next();
            }

            return(true);
        }