/// <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); } }
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); } }
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); } }
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); } }
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); } }
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)); }