/// <summary>
        /// <see cref="IDtoService{TEntity, TDto, TDtoKey}.Retrieve(Expression{Func{TEntity, bool}}, PagingContext, Func{IQueryable{TEntity}, IOrderedQueryable{TEntity}}, Expression{Func{TEntity, object}}[])"/>
        /// </summary>
        public virtual async Task <IEnumerable <TDto> > RetrieveAsync(
            Expression <Func <TEntity, bool> > filter = null,
            PagingContext pagingContext = null,
            Func <IQueryable <TEntity>, IOrderedQueryable <TEntity> > sortCondition = null,
            CancellationToken cancellationToken = default,
            params Expression <Func <TEntity, object> >[] includes)
        {
            try
            {
                var items = new List <TDto>();
                IEnumerable <TEntity> models = await ObjectService.RetrieveAsync(
                    filter,
                    pagingContext,
                    sortCondition,
                    cancellationToken,
                    includes);

                if (models?.Count() > 0)
                {
                    items = Mapper.Map <List <TDto> >(models);

                    if (KeyEncoder != null)
                    {
                        items.ForEach(d => d.Id = KeyEncoder.Encode(d.Id));
                    }
                }

                return(items);
            }
            catch (EncodingException e)
            {
                throw new ServiceException($"Error retrieving objects of type {typeof(TDto).Name}.", e);
            }
        }
        /// <summary>
        /// <see cref="IObjectService{TDto, TDtoKey}.Update(TDto)"/>
        /// </summary>
        public virtual void Update(TDto item)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            try
            {
                if (KeyEncoder != null)
                {
                    item.Id = KeyEncoder.Decode(item.Id);
                }

                var     modelId       = Mapper.Map <TEntityKey>(item.Id);
                TEntity originalModel = ObjectService.Retrieve(modelId);

                if (originalModel == null)
                {
                    throw new NotFoundException($"Error updating an object of type {typeof(TDto).Name} as identifier of {item.Id} not found.");
                }

                Mapper.Map(item, originalModel);
                ObjectService.Update(originalModel);
            }
            catch (EncodingException e)
            {
                throw new ServiceException($"Error updating an object of type {typeof(TDto).Name}.", e);
            }
        }
Exemple #3
0
    public void TestPrimaryKeys()
    {
        // Test that we get the correct memcmp result,
        // the bytes are in big-endian order in a key
        var schema = GetSchema(new TableBuilder()
                               .AddColumn("key", KuduType.Int32, opt => opt.Key(true))
                               .AddColumn("key2", KuduType.String, opt => opt.Key(true)));

        var small = new PartialRow(schema);

        small.SetInt32("key", 20);
        small.SetString("key2", "data");
        var smallPK = KeyEncoder.EncodePrimaryKey(small);

        Assert.Equal(
            new byte[] { 0x80, 0, 0, 20, (byte)'d', (byte)'a', (byte)'t', (byte)'a' },
            smallPK);

        var big = new PartialRow(schema);

        big.SetInt32("key", 10000);
        big.SetString("key2", "data");
        byte[] bigPK = KeyEncoder.EncodePrimaryKey(big);
        Assert.Equal(
            new byte[] { 0x80, 0, 0x27, 0x10, (byte)'d', (byte)'a', (byte)'t', (byte)'a' },
            bigPK);
        Assert.True(smallPK.SequenceCompareTo(bigPK) < 0);
    }
        /// <summary>
        /// <see cref="IObjectService{TDto, TDtoKey}.RetrieveAsync(TDtoKey, CancellationToken, Expression{Func{TDto, object}}[])"/>
        /// </summary>
        public virtual async Task <TDto> RetrieveAsync(
            TDtoKey id,
            CancellationToken cancellationToken = default,
            params Expression <Func <TDto, object> >[] includes)
        {
            try
            {
                if (KeyEncoder != null)
                {
                    id = KeyEncoder.Decode(id);
                }

                TDto    item    = default;
                var     modelId = Mapper.Map <TEntityKey>(id);
                TEntity model   = await ObjectService.RetrieveAsync(modelId, cancellationToken);

                if (model != null)
                {
                    item = Mapper.Map <TDto>(model);

                    if (KeyEncoder != null)
                    {
                        item.Id = KeyEncoder.Encode(item.Id);
                    }
                }

                return(item);
            }
            catch (EncodingException e)
            {
                throw new ServiceException($"Error retrieving an object of type {typeof(TDto).Name} with a unique identifier of {id}.", e);
            }
        }
        /// <summary>
        /// <see cref="IObjectService{TDto, TDtoKey}.UpdateAsync(TDto, CancellationToken)"/>
        /// </summary>
        public virtual async Task UpdateAsync(TDto item, CancellationToken cancellationToken = default)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            try
            {
                if (KeyEncoder != null)
                {
                    item.Id = KeyEncoder.Decode(item.Id);
                }

                var     modelId       = Mapper.Map <TEntityKey>(item.Id);
                TEntity originalModel = await ObjectService.RetrieveAsync(modelId, cancellationToken);

                if (originalModel == null)
                {
                    throw new NotFoundException($"Error updating an object of type {typeof(TDto).Name} as identifier of {item.Id} not found.");
                }

                Mapper.Map(item, originalModel);
                await ObjectService.UpdateAsync(originalModel, cancellationToken);
            }
            catch (EncodingException e)
            {
                throw new ServiceException($"Error updating an object of type {typeof(TDto).Name}.", e);
            }
        }
Exemple #6
0
    public void TestSimplePrimaryKey()
    {
        var schema = GetSchema(new TableBuilder()
                               .AddColumn("key", KuduType.String, opt => opt.Key(true)));

        var row = new PartialRow(schema);

        row.SetString("key", "foo");
        Assert.Equal("foo".ToUtf8ByteArray(), KeyEncoder.EncodePrimaryKey(row));
    }
        public void IsP2pkh_Success()
        {
            KeyEncoder keyEncoder = new KeyEncoder(111);

            // Valid
            Assert.Equal(true, keyEncoder.IsP2pkh("mfiCwNxuFYMtb5ytCacgzDAineD2GNCnYo"));
            // Wrong checksum
            Assert.Equal(false, keyEncoder.IsP2pkh("mfiCwNxuFYMtb5ytCacgzDAineD2GNCnYp"));
            // Invalid size
            Assert.Equal(false, keyEncoder.IsP2pkh("2Qx7aDxjSh772"));
            // Empty
            Assert.Equal(false, keyEncoder.IsP2pkh(""));
            // Invalid version byte
            Assert.Equal(false, keyEncoder.IsP2pkh("1CCW1yPxC8meB7JzF8xEwaad4DxksFqhrQ"));
        }
        public void IsP2pkh_Success()
        {
            KeyEncoder keyEncoder = new KeyEncoder(111);

            // Valid
            Assert.Equal(true, keyEncoder.IsP2pkh("mfiCwNxuFYMtb5ytCacgzDAineD2GNCnYo"));
            // Wrong checksum
            Assert.Equal(false, keyEncoder.IsP2pkh("mfiCwNxuFYMtb5ytCacgzDAineD2GNCnYp"));
            // Invalid size
            Assert.Equal(false, keyEncoder.IsP2pkh("2Qx7aDxjSh772"));
            // Empty
            Assert.Equal(false, keyEncoder.IsP2pkh(""));
            // Invalid version byte
            Assert.Equal(false, keyEncoder.IsP2pkh("1CCW1yPxC8meB7JzF8xEwaad4DxksFqhrQ"));
        }
    private FindTabletResult GetResult(PartialRow row)
    {
        var         partitionSchema = _partitionSchema;
        int         maxSize         = KeyEncoder.CalculateMaxPartitionKeySize(row, partitionSchema);
        Span <byte> buffer          = stackalloc byte[maxSize];

        KeyEncoder.EncodePartitionKey(
            row,
            partitionSchema,
            buffer,
            out int bytesWritten);

        var partitionKey = buffer.Slice(0, bytesWritten);

        return(RemoteTabletExtensions.FindTablet(_tablets, partitionKey));
    }
        /// <summary>
        /// <see cref="IObjectService{TDto, TDtoKey}.ExistsAsync(TDtoKey, CancellationToken)"/>
        /// </summary>
        public virtual async Task <bool> ExistsAsync(TDtoKey id, CancellationToken cancellationToken = default)
        {
            try
            {
                if (KeyEncoder != null)
                {
                    id = KeyEncoder.Decode(id);
                }

                var modelId = Mapper.Map <TEntityKey>(id);

                return(await ObjectService.ExistsAsync(modelId, cancellationToken));
            }
            catch (EncodingException e)
            {
                throw new ServiceException($"Error determining whether an object of type {typeof(TDto).Name} with unique identifier of {id} exists.", e);
            }
        }
        /// <summary>
        /// <see cref="IObjectService{TDto, TDtoKey}.Exists(TDtoKey)"/>
        /// </summary>
        public virtual bool Exists(TDtoKey id)
        {
            try
            {
                if (KeyEncoder != null)
                {
                    id = KeyEncoder.Decode(id);
                }

                var modelId = Mapper.Map <TEntityKey>(id);

                return(ObjectService.Exists(modelId));
            }
            catch (EncodingException e)
            {
                throw new ServiceException($"Error determining whether an object of type {typeof(TDto).Name} with unique identifier of {id} exists.", e);
            }
        }
Exemple #12
0
    private static void CheckPartitionKey(
        PartialRow row,
        PartitionSchema partitionSchema,
        byte[] expectedPartitionKey)
    {
        var         maxSize = KeyEncoder.CalculateMaxPartitionKeySize(row, partitionSchema);
        Span <byte> buffer  = stackalloc byte[maxSize];

        KeyEncoder.EncodePartitionKey(
            row,
            partitionSchema,
            buffer,
            out int bytesWritten);

        var partitionKey = buffer.Slice(0, bytesWritten).ToArray();

        Assert.Equal(expectedPartitionKey, partitionKey);
    }
        /// <summary>
        /// <see cref="IObjectService{TDto, TDtoKey}.Create(IEnumerable{TDto})"/>
        /// </summary>
        public virtual IEnumerable <TDto> Create(IEnumerable <TDto> items)
        {
            try
            {
                var models = Mapper.Map <IEnumerable <TEntity> >(items);
                models = ObjectService.Create(models);
                List <TDto> created = Mapper.Map <IEnumerable <TDto> >(models).ToList();

                if (KeyEncoder != null)
                {
                    created.ForEach(d => d.Id = KeyEncoder.Encode(d.Id));
                }

                return(created);
            }
            catch (EncodingException e)
            {
                throw new ServiceException($"Error creating objects of type {typeof(TDto).Name}.", e);
            }
        }
        /// <summary>
        /// <see cref="IObjectService{TDto, TDtoKey}.Create(TDto)"/>
        /// </summary>
        public virtual TDto Create(TDto item)
        {
            try
            {
                var model = Mapper.Map <TEntity>(item);
                model = ObjectService.Create(model);
                var created = Mapper.Map <TDto>(model);

                if (KeyEncoder != null)
                {
                    created.Id = KeyEncoder.Encode(created.Id);
                }

                return(created);
            }
            catch (EncodingException e)
            {
                throw new ServiceException($"Error creating an object of type {typeof(TDto).Name}.", e);
            }
        }
        /// <summary>
        /// <see cref="IObjectService{TDto, TDtoKey}.CreateAsync(TDto, CancellationToken)"/>
        /// </summary>
        public virtual async Task <TDto> CreateAsync(TDto item, CancellationToken cancellationToken = default)
        {
            try
            {
                var model = Mapper.Map <TEntity>(item);
                model = await ObjectService.CreateAsync(model, cancellationToken);

                var created = Mapper.Map <TDto>(model);

                if (KeyEncoder != null)
                {
                    created.Id = KeyEncoder.Encode(created.Id);
                }

                return(created);
            }
            catch (EncodingException e)
            {
                throw new ServiceException($"Error creating an object of type {typeof(TDto).Name}.", e);
            }
        }
Exemple #16
0
    public void TestPrimaryKeyWithNull()
    {
        var schema = GetSchema(new TableBuilder()
                               .AddColumn("key", KuduType.String, opt => opt.Key(true))
                               .AddColumn("key2", KuduType.String, opt => opt.Key(true)));

        var row1 = new PartialRow(schema);

        row1.SetString("key", "foo");
        row1.SetString("key2", "bar");
        Assert.Equal(
            "foo\0\0bar".ToUtf8ByteArray(),
            KeyEncoder.EncodePrimaryKey(row1));

        var row2 = new PartialRow(schema);

        row2.SetString("key", "xxx\0yyy");
        row2.SetString("key2", "bar");
        Assert.Equal(
            "xxx\0\u0001yyy\0\0bar".ToUtf8ByteArray(),
            KeyEncoder.EncodePrimaryKey(row2));
    }
        /// <summary>
        /// <see cref="IObjectService{TDto, TDtoKey}.CreateAsync(IEnumerable{TDto}, CancellationToken)"/>
        /// </summary>
        public virtual async Task <IEnumerable <TDto> > CreateAsync(
            IEnumerable <TDto> items,
            CancellationToken cancellationToken = default)
        {
            try
            {
                var models = Mapper.Map <IEnumerable <TEntity> >(items);
                models = await ObjectService.CreateAsync(models, cancellationToken);

                List <TDto> created = Mapper.Map <IEnumerable <TDto> >(models).ToList();

                if (KeyEncoder != null)
                {
                    created.ForEach(d => d.Id = KeyEncoder.Encode(d.Id));
                }

                return(created);
            }
            catch (EncodingException e)
            {
                throw new ServiceException($"Error creating objects of type {typeof(TDto).Name}.", e);
            }
        }
        public void GetPubKeyHash_Success()
        {
            KeyEncoder keyEncoder = new KeyEncoder(111);

            Assert.Equal("n12RA1iohYEerfXiBixSoERZG8TP8xQFL2", keyEncoder.GetPubKeyHash(ByteString.Parse("abcdef")));
        }
        public static IMutationValidator CreateRulesValidator(IServiceProvider serviceProvider)
        {
            IConfiguration configuration = serviceProvider.GetService <IConfiguration>().GetSection("validator_mode");
            ILogger        logger        = serviceProvider.GetService <ILogger>();

            string rootUrl = configuration["root_url"];

            if (rootUrl != null)
            {
                if (!Uri.IsWellFormedUriString(rootUrl, UriKind.Absolute))
                {
                    string errorMessage = $"The server root URL is not a valid URL: '{rootUrl}'. Please make sure it is configured correctly.";
                    throw new InvalidOperationException(errorMessage);
                }

                logger.LogInformation("Current mode: Validator mode");
                logger.LogInformation($"Namespace: {rootUrl}");
                IConfiguration validator = configuration.GetSection("validator");

                switch (validator["type"])
                {
                case "PermissionBased":
                    byte       versionByte = byte.Parse(validator["version_byte"]);
                    KeyEncoder keyEncoder  = new KeyEncoder(versionByte);

                    P2pkhSubject[] adminAddresses = validator
                                                    .GetSection("admin_addresses")
                                                    .GetChildren()
                                                    .Select(key => key.Value)
                                                    .Select(address => new P2pkhSubject(new[] { address }, 1, keyEncoder))
                                                    .ToArray();

                    List <Acl> pathPermissions = new List <Acl>()
                    {
                        // Admins have full rights
                        new Acl(adminAddresses, LedgerPath.Parse("/"), true, StringPattern.MatchAll, PermissionSet.AllowAll)
                    };

                    foreach (IConfigurationSection section in validator.GetSection("issuers").GetChildren())
                    {
                        LedgerPath assetPath = LedgerPath.Parse(section["path"]);

                        P2pkhSubject[] addresses = section
                                                   .GetSection("addresses")
                                                   .GetChildren()
                                                   .Select(child => child.Value)
                                                   .Select(address => new P2pkhSubject(new[] { address }, 1, keyEncoder))
                                                   .ToArray();

                        pathPermissions.Add(new Acl(
                                                addresses,
                                                assetPath,
                                                true,
                                                StringPattern.MatchAll,
                                                new PermissionSet(accountSpend: Access.Permit, dataModify: Access.Permit)));

                        pathPermissions.Add(new Acl(
                                                addresses,
                                                assetPath,
                                                true,
                                                new StringPattern(DynamicPermissionLayout.AclResourceName, PatternMatchingStrategy.Exact),
                                                new PermissionSet(dataModify: Access.Deny)));

                        pathPermissions.Add(new Acl(
                                                new[] { EveryoneSubject.Instance },
                                                assetPath,
                                                true,
                                                new StringPattern(assetPath.FullPath, PatternMatchingStrategy.Prefix),
                                                new PermissionSet(accountModify: Access.Permit)));

                        pathPermissions.Add(new Acl(
                                                addresses,
                                                LedgerPath.Parse("/"),
                                                true,
                                                new StringPattern(assetPath.FullPath, PatternMatchingStrategy.Prefix),
                                                new PermissionSet(accountNegative: Access.Permit)));
                    }

                    List <IPermissionsProvider> permissionProviders = new List <IPermissionsProvider>();

                    if (bool.Parse(validator["allow_third_party_assets"]))
                    {
                        permissionProviders.Add(new P2pkhIssuanceImplicitLayout(keyEncoder));
                    }

                    if (bool.Parse(validator["allow_p2pkh_accounts"]))
                    {
                        permissionProviders.Add(new P2pkhImplicitLayout(keyEncoder));
                    }

                    permissionProviders.Add(new StaticPermissionLayout(pathPermissions));
                    permissionProviders.Add(new DynamicPermissionLayout(serviceProvider.GetRequiredService <IStorageEngine>(), keyEncoder));

                    return(new PermissionBasedValidator(permissionProviders));

                case "Disabled":
                    return(ActivatorUtilities.CreateInstance <NullValidator>(serviceProvider, true));

                default:
                    return(null);
                }
            }
            else
            {
                logger.LogInformation("Transaction validation mode disabled (Slave mode)");
                return(null);
            }
        }
        public async Task Test_FdbMap_With_Custom_Key_Encoder()
        {
            // Use a table as a backing store for the rules of a Poor Man's firewall, where each keys are the IPEndPoint (tcp only!), and the values are "pass" or "block"

            // Encode IPEndPoint as the (IP, Port,) encoded with the Tuple codec
            // note: there is a much simpler way or creating composite keys, this is just a quick and dirty test!
            var keyEncoder = new KeyEncoder <IPEndPoint>(
                (ipe) => ipe == null ? Slice.Empty : TuPack.EncodeKey(ipe.Address, ipe.Port),
                (packed) =>
            {
                if (packed.IsNullOrEmpty)
                {
                    return(default(IPEndPoint));
                }
                var t = TuPack.Unpack(packed);
                return(new IPEndPoint(t.Get <IPAddress>(0), t.Get <int>(1)));
            }
                );

            var rules = new Dictionary <IPEndPoint, string>()
            {
                { new IPEndPoint(IPAddress.Parse("172.16.12.34"), 6667), "block" },
                { new IPEndPoint(IPAddress.Parse("192.168.34.56"), 80), "pass" },
                { new IPEndPoint(IPAddress.Parse("192.168.34.56"), 443), "pass" }
            };

            using (var db = await OpenTestPartitionAsync())
            {
                var location = db.Root["Collections"]["Maps"];
                await CleanLocation(db, location);

                var mapHosts = new FdbMap <IPEndPoint, string>(location.ByKey("Hosts").AsTyped <IPEndPoint>(keyEncoder), BinaryEncoding.StringEncoder);

                // import all the rules
                await mapHosts.WriteAsync(db, (tr, hosts) =>
                {
                    foreach (var rule in rules)
                    {
                        hosts.Set(tr, rule.Key, rule.Value);
                    }
                }, this.Cancellation);

#if FULL_DEBUG
                await DumpSubspace(db, location);
#endif

                // test the rules

                await mapHosts.ReadAsync(db, async (tr, hosts) =>
                {
                    var value = await hosts.GetAsync(tr, new IPEndPoint(IPAddress.Parse("172.16.12.34"), 6667));
                    Assert.That(value, Is.EqualTo("block"));

                    value = await hosts.GetAsync(tr, new IPEndPoint(IPAddress.Parse("192.168.34.56"), 443));
                    Assert.That(value, Is.EqualTo("pass"));

                    var baz = new IPEndPoint(IPAddress.Parse("172.16.12.34"), 80);
                    Assert.That(async() => await hosts.GetAsync(tr, baz), Throws.InstanceOf <KeyNotFoundException>());

                    var opt = await hosts.TryGetAsync(tr, baz);
                    Assert.That(opt.HasValue, Is.False);
                }, this.Cancellation);
            }
        }
Exemple #21
0
    public void TestPrimaryKeyEncoding()
    {
        var schema = GetSchema(new TableBuilder()
                               .AddColumn("int8", KuduType.Int8, opt => opt.Key(true))
                               .AddColumn("int16", KuduType.Int16, opt => opt.Key(true))
                               .AddColumn("int32", KuduType.Int32, opt => opt.Key(true))
                               .AddColumn("int64", KuduType.Int64, opt => opt.Key(true))
                               .AddColumn("decimal32", KuduType.Decimal32, opt => opt.Key(true)
                                          .DecimalAttributes(DecimalUtil.MaxDecimal32Precision, 0))
                               .AddColumn("decimal64", KuduType.Decimal64, opt => opt.Key(true)
                                          .DecimalAttributes(DecimalUtil.MaxDecimal64Precision, 0))
                               .AddColumn("decimal128", KuduType.Decimal128, opt => opt.Key(true)
                                          .DecimalAttributes(DecimalUtil.MaxDecimal128Precision, 0))
                               .AddColumn("varchar", KuduType.Varchar, opt => opt.Key(true)
                                          .VarcharAttributes(10))
                               .AddColumn("string", KuduType.String, opt => opt.Key(true))
                               .AddColumn("binary", KuduType.Binary, opt => opt.Key(true)));

        var rowA = new PartialRow(schema);

        rowA.SetSByte("int8", sbyte.MinValue);
        rowA.SetInt16("int16", short.MinValue);
        rowA.SetInt32("int32", int.MinValue);
        rowA.SetInt64("int64", long.MinValue);
        // Note: The decimal value is not the minimum of the underlying int32,
        // int64, int128 type so we don't use "minimum" values in the test.
        rowA.SetDecimal("decimal32", 5m);
        rowA.SetDecimal("decimal64", 6m);
        rowA.SetDecimal("decimal128", 7m);
        rowA.SetString("varchar", "");
        rowA.SetString("string", "");
        rowA.SetBinary("binary", Array.Empty <byte>());

        var rowAEncoded = KeyEncoder.EncodePrimaryKey(rowA);

        Assert.Equal(new byte[]
        {
            0,
            0, 0,
            0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0,
            0x80, 0, 0, 5,
            0x80, 0, 0, 0, 0, 0, 0, 6,
            0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,
            0, 0,
            0, 0
        }, rowAEncoded);

        var rowB = new PartialRow(schema);

        rowB.SetSByte("int8", sbyte.MaxValue);
        rowB.SetInt16("int16", short.MaxValue);
        rowB.SetInt32("int32", int.MaxValue);
        rowB.SetInt64("int64", long.MaxValue);
        // Note: The decimal value is not the maximum of the underlying int32,
        // int64, int128 type so we don't use "maximum" values in the test.
        rowB.SetDecimal("decimal32", 5m);
        rowB.SetDecimal("decimal64", 6m);
        rowB.SetDecimal("decimal128", 7m);
        rowB.SetString("varchar", "abc\u0001\0defghij");
        rowB.SetString("string", "abc\u0001\0def");
        rowB.SetBinary("binary", "\0\u0001binary".ToUtf8ByteArray());

        var rowBEncoded = KeyEncoder.EncodePrimaryKey(rowB);

        Assert.Equal(ToByteArray(new int[]
        {
            0xff,
            0xff, 0xff,
            0xff, 0xff, 0xff, 0xff,
            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
            0x80, 0, 0, 5,
            0x80, 0, 0, 0, 0, 0, 0, 6,
            0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,
            'a', 'b', 'c', 1, 0, 1, 'd', 'e', 'f', 'g', 'h', 0, 0,
            'a', 'b', 'c', 1, 0, 1, 'd', 'e', 'f', 0, 0,
            0, 1, 'b', 'i', 'n', 'a', 'r', 'y'
        }), rowBEncoded);

        var rowC = new PartialRow(schema);

        rowC.SetSByte("int8", 1);
        rowC.SetInt16("int16", 2);
        rowC.SetInt32("int32", 3);
        rowC.SetInt64("int64", 4);
        rowC.SetDecimal("decimal32", 5m);
        rowC.SetDecimal("decimal64", 6m);
        rowC.SetDecimal("decimal128", 7m);
        rowC.SetString("varchar", "abc\n12345678");
        rowC.SetString("string", "abc\n123");
        rowC.SetBinary("binary", "\0\u0001\u0002\u0003\u0004\u0005".ToUtf8ByteArray());

        var rowCEncoded = KeyEncoder.EncodePrimaryKey(rowC);

        Assert.Equal(ToByteArray(new int[]
        {
            0x81,
            0x80, 2,
            0x80, 0, 0, 3,
            0x80, 0, 0, 0, 0, 0, 0, 4,
            0x80, 0, 0, 5,
            0x80, 0, 0, 0, 0, 0, 0, 6,
            0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,
            'a', 'b', 'c', '\n', '1', '2', '3', '4', '5', '6', 0, 0,
            'a', 'b', 'c', '\n', '1', '2', '3', 0, 0,
            0, 1, 2, 3, 4, 5
        }), rowCEncoded);

        var rowD = new PartialRow(schema);

        rowD.SetSByte("int8", -1);
        rowD.SetInt16("int16", -2);
        rowD.SetInt32("int32", -3);
        rowD.SetInt64("int64", -4);
        rowD.SetDecimal("decimal32", -5m);
        rowD.SetDecimal("decimal64", -6m);
        rowD.SetDecimal("decimal128", -7m);
        rowD.SetString("varchar", "\0abc\n\u0001\u0001\0 123\u0001\0");
        rowD.SetString("string", "\0abc\n\u0001\u0001\0 123\u0001\0");
        rowD.SetBinary("binary", "\0\u0001\u0002\u0003\u0004\u0005\0".ToUtf8ByteArray());

        var rowDEncoded = KeyEncoder.EncodePrimaryKey(rowD);

        Assert.Equal(ToByteArray(new int[]
        {
            127,
            127, -2,
            127, -1, -1, -3,
            127, -1, -1, -1, -1, -1, -1, -4,
            127, -1, -1, -5,
            127, -1, -1, -1, -1, -1, -1, -6,
            127, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -7,
            0, 1, 'a', 'b', 'c', '\n', 1, 1, 0, 1, ' ', '1', 0, 0,
            0, 1, 'a', 'b', 'c', '\n', 1, 1, 0, 1, ' ', '1', '2', '3', 1, 0, 1, 0, 0,
            0, 1, 2, 3, 4, 5, 0,
        }), rowDEncoded);
    }
 /// <summary>
 /// Add an upper bound (exclusive) primary key for the scan.
 /// If any bound is already added, this bound is intersected with that one.
 /// </summary>
 /// <param name="row">A partial row with specified key columns.</param>
 public TBuilder ExclusiveUpperBound(PartialRow row)
 {
     byte[] endPrimaryKey = KeyEncoder.EncodePrimaryKey(row);
     return(ExclusiveUpperBoundRaw(endPrimaryKey));
 }
        public void GetPubKeyHash_Success()
        {
            KeyEncoder keyEncoder = new KeyEncoder(111);

            Assert.Equal("n12RA1iohYEerfXiBixSoERZG8TP8xQFL2", keyEncoder.GetPubKeyHash(ByteString.Parse("abcdef")));
        }
 /// <summary>
 /// Add a lower bound (inclusive) primary key for the scan.
 /// If any bound is already added, this bound is intersected with that one.
 /// </summary>
 /// <param name="row">A partial row with specified key columns.</param>
 public TBuilder LowerBound(PartialRow row)
 {
     byte[] startPrimaryKey = KeyEncoder.EncodePrimaryKey(row);
     return(LowerBoundRaw(startPrimaryKey));
 }