The Pact documentation describes governing a module with a keyset. Specifically, given the module (module foo 'foo-keyset ...), then if someone tries to upgrade the contract then the 'foo-keyset will be "enforced on the transaction signature set."
I am trying to understand what it means to enforce 'foo-keyset. How does this string relate to one or more specific signatures in the signature set? Does the string mean anything, or could I name it anything I want? If the string is arbitrary, then what exactly is being enforced?
I tried to resolve this with the Pact documentation, to see whether there was a way to relate this keyset string with one or more signatures in the keyset. The docs describe a keyset as a list of public keys and a keyset predicate, and gives some JSON examples such as these two:
{ "keys": ["abc6bab9b88e08d","fe04ddd404feac2"], "pred": "keys-2" }
{ "keys": ["abc6bab9b88e08d","fe04ddd404feac2"], "pred": "my-module.custom-pred" }
I thought perhaps the keyset predicate could be used to relate 'foo-keyset to a particular key or set of keys in the keyset, like requiring a predicate my-module.foo-keyset, but the documentation for keyset predicates seems to focus on counting a particular number of matches from a keyset.
A keyset reference is a unique keyset defined in the environment. Either repl or the blockchain.
In repl you can define a keyset like this:
(env-data {
"bob-guard": {"keys": ["bob"], "pred": "keys-all"}
,"alice-guard": {"keys": ["alice"], "pred": "keys-all"}
})
On the blockchain you need to choose a unique name and define it with define-keyset:
(define-keyset 'my-unique-keyset-name (read-keyset "keyset"))
read-keyset reads the keyset from the variable my-keyset defined in the transaction data.
If you define a governance keyset for your module the keyset will be validated upon upgrade through deployment of the same module name. The validity of the keyset is checked through the predicate (pred).
The predicate can be any function that is fed as arguments the number of keys in the keyset and the count of matching signatures. If the predicate returns true the transaction can continue. You can construct custom predicates matching this function signature:
(defun keys-majority:bool(count:integer matched:integer)
(>= matched (+ (/ count 2) 1)))
And then create a keyset using that custom predicate:
(env-data {
"my-module-guard": {"keys": ["bob", "alice", "babena" ],
"pred": "my-module.keys-majority"}
})
Related
When building keysets, they have three options: keys-all, keys-2, and keys-any. I wanted to create a keyset that required 3 keys to sign the transaction, but I was confused about how to force the keyset to take all three keys in the signature section.
The validity of the keyset is checked through the predicate (pred).
The predicate can be any function that is fed as arguments:
the number of keys in the keyset
the count of matching signatures
If the predicate returns true the transaction can continue. You can construct custom predicates matching this function signature:
(defun keys-3:bool(count:integer matched:integer)
(>= matched 3))
And then create a keyset using that custom predicate:
(env-data {
"my-keyset": {"keys": ["bob", "alice", "babena" ],
"pred": "my-module.keys-3"}
})
How can one search for ndb models based on key inequality?
For example, for a string one can use:
def add_inequality_filter(query, attr, given)
end = given + u'\ufffd'
return query.filter(attr >= given, attr < end)
add_inequality_filter(query, "key", "abc.")
If key were an ordinary string property this would work, however the key is a ModelKey.
Comparing the key (or _key) to a string triggers a BadValueError.
There does not appear to be a documented way to create a ModelKey (or equivalent) for comparison.
When I try to filter on __key__ > (the db way) I get a Cannot filter a non-Node argument.
The db to ndb documentation certainly indicates that this should be possible.
To answer my own question, the given and end in this need to be ndb.Key instances, whereas I had only attempted ModelKey, KeyProperty and strings.
I need to check the existence of a key (i.e. an username). It seems that KEY_RESERVED_PROPERTY is a special key available for the java api that you can use to achieve the best performance and strong consistency so I'm wondering if there is any equivalent in Go.
Currently I'm considering using a query with the username as ancestor + KeysOnly().
If you look at the docs, KEY_RESERVED_PROPERTY is nothing but a property to refer to the key:
A reserved property name used to refer to the key of the entity. This string can be used for filtering and sorting by the entity key itself.
So this is nothing magical, you could do the same thing in Go with the __key__ property, as stated in the docs:
Key filters
To filter on the value of an entity's key, use the special property __key__:
q := datastore.NewQuery("Person").Filter("__key__ >", lastSeenKey)
I need to check the existence of a key (i.e. an username).
You can also do that by attempting to load the entity by key using the datastore.Get() function. A return value of ErrNoSuchEntity means no entity exists with the specified key:
if err := datastore.Get(c, key, dst); err == datastore.ErrNoSuchEntity {
// Key doesn't exist
}
Can someone explain how to define multi column indexes in Grails? The documentation is at best sparse.
This for example does not seem to work at all:
http://grails.org/GORM+Index+definitions
I've had some luck with this, but the results seems random at best. Definitions that works in one domain class does not when applied to another (with different names of course).
http://www.grails.org/doc/1.1/guide/single.html#5.5.2.6%20Database%20Indices
Some working examples and explanations would be highly appreciated!
The solution that has worked for me for multi-column indexes is:
class ClassName {
String name
String description
String state
static mapping = {
name index: 'name_idx'
description index: 'name_idx'
state index: 'name_idx'
}
}
This creates an index called 'name_idx' with the three columns in the index.
Downside: the columns are listed in the index in alphabetical order, not the order that they were entered.
To make your index multi-column, list the columns with comma separator (note, no space after the comma, to avoid this bug. The second URL you point to hits the bug, as it says:
index:'Name_Idx, Address_Index'
with a space; it should work as
index:'Name_Idx,Address_Index'
The first URL you point to was a proposed change (I don't believe it's implemented currently and have no idea how likely it is to ever be).
AFAIK, the index closure shown here was never implemented, so those examples should be ignored (this page is for discussing possible implementations, rather than documenting an actual implementation).
The correct way to define a single-column index name_idx for a name property is
static mapping = {
name index:'name_idx'
}
Sorry, but I don't know how to define a multi-column index, try the Grails mailing list if you don't get an answer here. In the unlikely event that multi-column indices can't be declared directly in the domain classes, you could define them in an SQL file which creates them if they don't already exist (or drops and re-creates them). This SQL file could be executed by the init closure in Bootstrap.groovy
I needed to be able to control the order of the columns in my multi-column index and also make it unique. I worked around the GORM / Hibernate limitations by creating the index in Bootstrap using direct SQL:
class BootStrap {
DataSource dataSource
def init = { servletContext ->
if (!MyModel.count()) { // new database
createIndexes()
...
}
}
private void createIndexes() {
Sql sql = new Sql(dataSource)
sql.execute("create unique index my_index on my_model(col1,col2);")
}
Does get(key) require the entity key and get_by_key_name(key_names) require the key_name?
There is a difference. An Entity in the datastore is identified by a combination of its Kind, its parent, and its identifier. (link) The "identifier" can either be a number or a string. A Key object contains both the identifier and the parent information. So when you call get(), there is just one argument - the Key object. When you call get_by_key_name, notice that there are 2 arguments - one is the key_name, one is the parent.
So a Key is an object with several parts, whereas a key name is just a string. To make things more confusing, a Key object can be encoded as a string.
Here is official explanation for get() and this one is for get_by_key_name()
I hope this helps.