From 15fbf7fda511e3dd39b85f27cd2a6b20dbf9bcce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Wed, 25 Jul 2018 13:19:23 +0200 Subject: [PATCH 01/89] Custom active permissions --- bsip-0040.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 bsip-0040.md diff --git a/bsip-0040.md b/bsip-0040.md new file mode 100644 index 0000000..fb63e89 --- /dev/null +++ b/bsip-0040.md @@ -0,0 +1,52 @@ + BSIP: 0040 + Title: Custom active permissions + Authors: + Alex M + Fabian Schuh + Stefan Schießl + Status: Draft + Type: Protocol + Created: 2018-07-25 + Discussion: https://github.com/bitshares/bitshares-core/issues/1061 + Worker: + +# Abstract + +Strengthening user security is one of the main factors to elevate BitShares. Inlight of recent +hacking and phishing attempts this becomes even more important. The need for a more sophisticated +account security preceeded the idea for a finer-grained control of account permissions. +We propose to add an additional authority to the account, called Custom Active (Permission). The +permission contains a list of operationid-to-authority mappings that each grant access to the respective +operation as if it were the active permission of the account. Additionally, the arguments of said operation +can be restricted. + +# Motivation and Rational + +Any successfull hacking or phishing attempt on any of the web wallets that are powered by the +BitShares Blockchain is bad publicity. The user needs to be educated in account security, and this BSIP +aims to ensure all technical possibilities are met while being flexible to allow many use-cases. + +Examples: + - Witness Key: Only allows update signing key and publish price feed + - Trading Key: Only allows limit orders (arguments restricted to desired markets), update margin position and transfers (arguments restricted to certain accounts) + - Proposal Update Key: Approve proposals (2FA comes to mind) +The above list of named keys is nothing that is known to the backend as the backend should have an abstract implementation. + The UI should provide a button "Create Trading Key" that properly configures the respective custom active permission entry. + + + +# Specifications + +# Discussion + +To be found in the forum - see link above. + +# Summary for Shareholders + +# Copyright + +This document is placed in the public domain. + +# See Also + +* https://github.com/bitshares/bitshares-core/issues/1061 From 7a13f4de7c08db79c9d32974944ff6503652ea11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Wed, 25 Jul 2018 13:34:40 +0200 Subject: [PATCH 02/89] Update bsip-0040.md --- bsip-0040.md | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index fb63e89..e236f41 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -30,23 +30,40 @@ Examples: - Witness Key: Only allows update signing key and publish price feed - Trading Key: Only allows limit orders (arguments restricted to desired markets), update margin position and transfers (arguments restricted to certain accounts) - Proposal Update Key: Approve proposals (2FA comes to mind) + - Faucet Key: Allow only to create accounts The above list of named keys is nothing that is known to the backend as the backend should have an abstract implementation. The UI should provide a button "Create Trading Key" that properly configures the respective custom active permission entry. - - # Specifications +The description here is more on a superficial level and no recommendation how it can best be implemented. +Custom active permission is a list of custom active authorities. A `custom active authorities` contains an `operation_id`, an `authority` (just like with active permission) and a list of `restricted arguments`. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. It also checks if the arguments are in the allowed range. + +Example: +Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: +``` +custom active authority = { + operationid: 0 (transfer), + authority: K, + restricted: { + to: B + } +} +``` +That has the consquence now that a a transfer transaction sending funds away from A can be signed with key K as long as the receiver is B. + # Discussion -To be found in the forum - see link above. +To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/1061). # Summary for Shareholders +Bad publicity in terms of security can have very negative effect on the BTS value. This BSIP allows that traders can e.g. use a trading key, witnesses can use their witness key and a faucet can use a faucet key. If then for some reason the key or witness/faucet server becomes compromised, such a key can do little harm to the account holders, minimizing the risk. + # Copyright This document is placed in the public domain. # See Also -* https://github.com/bitshares/bitshares-core/issues/1061 + From aed7556df5b69b60d6d2d1a4611ce2ebfc250583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Wed, 25 Jul 2018 13:35:17 +0200 Subject: [PATCH 03/89] Update bsip-0040.md --- bsip-0040.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index e236f41..294fd96 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -20,7 +20,7 @@ permission contains a list of operationid-to-authority mappings that each grant operation as if it were the active permission of the account. Additionally, the arguments of said operation can be restricted. -# Motivation and Rational +# Motivation Any successfull hacking or phishing attempt on any of the web wallets that are powered by the BitShares Blockchain is bad publicity. The user needs to be educated in account security, and this BSIP @@ -34,7 +34,7 @@ Examples: The above list of named keys is nothing that is known to the backend as the backend should have an abstract implementation. The UI should provide a button "Create Trading Key" that properly configures the respective custom active permission entry. -# Specifications +# Rational The description here is more on a superficial level and no recommendation how it can best be implemented. Custom active permission is a list of custom active authorities. A `custom active authorities` contains an `operation_id`, an `authority` (just like with active permission) and a list of `restricted arguments`. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. It also checks if the arguments are in the allowed range. @@ -52,6 +52,8 @@ custom active authority = { ``` That has the consquence now that a a transfer transaction sending funds away from A can be signed with key K as long as the receiver is B. +# Specifications + # Discussion To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/1061). From e928c44cc819cf844b3f37a61f88028b0add3f13 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Wed, 25 Jul 2018 13:50:14 +0200 Subject: [PATCH 04/89] Update bsip-0040.md --- bsip-0040.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 294fd96..3564dc2 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -44,8 +44,12 @@ Assume account A and B and some unrelated key K. Furthermore A has a custom acti ``` custom active authority = { operationid: 0 (transfer), - authority: K, - restricted: { + authority: { + threshold: 1 + key_auth: [K, 1] + account_auth: [] + }, + assert: { to: B } } @@ -54,6 +58,12 @@ That has the consquence now that a a transfer transaction sending funds away fro # Specifications +* the account objects must be extended to store custom active authority +* an operation must be extended or created to allow changing the custom active authority +* additional signatures and operation-specific authorities (if present) must be evaluated against incoming transactions + +* additional committee parameters may need to be specified to limit the extend of usage of this feature + # Discussion To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/1061). From e8fabfd5cd9ffd351df3e72bd25e96dea13b8e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Wed, 25 Jul 2018 14:11:03 +0200 Subject: [PATCH 05/89] Update bsip-0040.md --- bsip-0040.md | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 3564dc2..2661b2f 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -37,7 +37,17 @@ The above list of named keys is nothing that is known to the backend as the back # Rational The description here is more on a superficial level and no recommendation how it can best be implemented. -Custom active permission is a list of custom active authorities. A `custom active authorities` contains an `operation_id`, an `authority` (just like with active permission) and a list of `restricted arguments`. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. It also checks if the arguments are in the allowed range. +Custom active permission is a list of custom active authorities. A `custom active authorities` contains an `operation_id`, an `authority` (just like with active permission) and a list of `assert`s than can be used to restricted arguments. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. It also checks if the arguments are in the allowed range. + +A Custom Active Permission looks like follows (in JSON for clarification, backend serializes and stores in a different way): +``` +custom_active_permission = list of custom_active_authority items +custom_active_authority = { + operationid, + auhtority, + assert +} +``` Example: Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: @@ -57,12 +67,11 @@ custom active authority = { That has the consquence now that a a transfer transaction sending funds away from A can be signed with key K as long as the receiver is B. # Specifications - -* the account objects must be extended to store custom active authority -* an operation must be extended or created to allow changing the custom active authority -* additional signatures and operation-specific authorities (if present) must be evaluated against incoming transactions - -* additional committee parameters may need to be specified to limit the extend of usage of this feature +Requirements to modify the backend includes +* Extend the account object to store custom active permission +* Extend `account_update` or create a new operation to allow changing the custom active permission +* Operation-specific authorities (if present) must be evaluated in incoming transactions +* Additional committee parameters may be needed to limit the extend of usage of this feature # Discussion @@ -76,6 +85,3 @@ Bad publicity in terms of security can have very negative effect on the BTS valu This document is placed in the public domain. -# See Also - - From 5ebcbb6f99744b2c4a57632f1d1ef25b64d4f830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Wed, 25 Jul 2018 14:11:50 +0200 Subject: [PATCH 06/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 2661b2f..8855536 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -1,7 +1,7 @@ BSIP: 0040 Title: Custom active permissions Authors: - Alex M + Alex Megalokonomos Fabian Schuh Stefan Schießl Status: Draft From a82530729e951e7b664fb6b0b355967dbacfbd8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Wed, 25 Jul 2018 14:12:42 +0200 Subject: [PATCH 07/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 8855536..acb5f7f 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -37,7 +37,7 @@ The above list of named keys is nothing that is known to the backend as the back # Rational The description here is more on a superficial level and no recommendation how it can best be implemented. -Custom active permission is a list of custom active authorities. A `custom active authorities` contains an `operation_id`, an `authority` (just like with active permission) and a list of `assert`s than can be used to restricted arguments. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. It also checks if the arguments are in the allowed range. +Custom active permission is a list of custom active authorities. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and a list of `assert`s than can be used to restricted arguments. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. It also checks if the arguments are in the allowed range. A Custom Active Permission looks like follows (in JSON for clarification, backend serializes and stores in a different way): ``` From 239b7a29572e04b14790b8f55bb6a0ea7fa1473f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Wed, 25 Jul 2018 14:13:07 +0200 Subject: [PATCH 08/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index acb5f7f..b2e5808 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -37,7 +37,7 @@ The above list of named keys is nothing that is known to the backend as the back # Rational The description here is more on a superficial level and no recommendation how it can best be implemented. -Custom active permission is a list of custom active authorities. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and a list of `assert`s than can be used to restricted arguments. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. It also checks if the arguments are in the allowed range. +Custom active permission is a list of custom active authorities. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `assert`s than can be used to restricted arguments. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. It also checks if the arguments are in the allowed range. A Custom Active Permission looks like follows (in JSON for clarification, backend serializes and stores in a different way): ``` From 28f96bafcc5042705c7592abebe2ef714336467f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Wed, 25 Jul 2018 14:33:47 +0200 Subject: [PATCH 09/89] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b3f4e90..5b3a9eb 100644 --- a/README.md +++ b/README.md @@ -47,3 +47,4 @@ Number | Title | [37](bsip-0037.md) | Allow new asset name to end with a number | oxarbitrage | Protocol | Installed [38](bsip-0038.md) | Add target collateral ratio option to short positions | Abit More | Protocol | Installed [39](bsip-0039.md) | Automatically approve proposals by the proposer | Fabian Schuh | Protocol | Draft +[40](bsip-0040.md) | Custom active permission | Stefan Schießl | Protocol | Draft From 10fa5ad679f4fe5ae78fb70ea6ebe11b4de96f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 27 Jul 2018 13:14:48 +0200 Subject: [PATCH 10/89] Comments from pmconrad --- bsip-0040.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index b2e5808..bbaad74 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -12,7 +12,7 @@ # Abstract -Strengthening user security is one of the main factors to elevate BitShares. Inlight of recent +Strengthening user security is one of the main factors to elevate BitShares. In light of recent hacking and phishing attempts this becomes even more important. The need for a more sophisticated account security preceeded the idea for a finer-grained control of account permissions. We propose to add an additional authority to the account, called Custom Active (Permission). The @@ -32,19 +32,19 @@ Examples: - Proposal Update Key: Approve proposals (2FA comes to mind) - Faucet Key: Allow only to create accounts The above list of named keys is nothing that is known to the backend as the backend should have an abstract implementation. - The UI should provide a button "Create Trading Key" that properly configures the respective custom active permission entry. + The UI could provide a button "Create Trading Key" that properly configures the respective custom active permission entry. # Rational The description here is more on a superficial level and no recommendation how it can best be implemented. -Custom active permission is a list of custom active authorities. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `assert`s than can be used to restricted arguments. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. It also checks if the arguments are in the allowed range. +Custom active permission is a list of custom active authorities. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `assert`s than can be used to restrict arguments. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. It also checks if the arguments are in the allowed range. A Custom Active Permission looks like follows (in JSON for clarification, backend serializes and stores in a different way): ``` custom_active_permission = list of custom_active_authority items custom_active_authority = { operationid, - auhtority, + authority, assert } ``` @@ -68,7 +68,7 @@ That has the consquence now that a a transfer transaction sending funds away fro # Specifications Requirements to modify the backend includes -* Extend the account object to store custom active permission +* Extend the account object to store custom active permission that includes a list of custom active authorities. Multiple custom active authority entries are possible for one operation * Extend `account_update` or create a new operation to allow changing the custom active permission * Operation-specific authorities (if present) must be evaluated in incoming transactions * Additional committee parameters may be needed to limit the extend of usage of this feature From 815a50c802891f81062e50d01d7426742c42c627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 27 Jul 2018 14:33:35 +0200 Subject: [PATCH 11/89] add more detailed asserts description and milestones --- bsip-0040.md | 57 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index bbaad74..0e74c74 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -31,37 +31,68 @@ Examples: - Trading Key: Only allows limit orders (arguments restricted to desired markets), update margin position and transfers (arguments restricted to certain accounts) - Proposal Update Key: Approve proposals (2FA comes to mind) - Faucet Key: Allow only to create accounts + - Withdrawal Key: Allow another account to transfer funds to himself + - Cold Storage Key: Only allow to move funds to the Hot Wallet + The above list of named keys is nothing that is known to the backend as the backend should have an abstract implementation. The UI could provide a button "Create Trading Key" that properly configures the respective custom active permission entry. # Rational The description here is more on a superficial level and no recommendation how it can best be implemented. -Custom active permission is a list of custom active authorities. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `assert`s than can be used to restrict arguments. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. It also checks if the arguments are in the allowed range. +Custom active permission is a list of custom active authorities. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `asserts` than can be used to restrict arguments. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. If there are several custom active authorities, any matched one grants this, thus finding the first match is sufficient. It also checks if the arguments are in the allowed range. A Custom Active Permission looks like follows (in JSON for clarification, backend serializes and stores in a different way): ``` custom_active_permission = list of custom_active_authority items custom_active_authority = { + valid_from, // this custom active authority is valid starting at this timestamp, defaults to now + valid_to, // this custom active authority is valid until this timestamp, defaults to 1 year operationid, authority, - assert + asserts } ``` +Note: This assumes `custom_active_permission` is stored within `account_object`. Actual implementation details left to the implementer. -Example: +The `asserts` is a list of `assert_objects` that are all together evaluated with `and` logic to evaluate a match +``` +asserts = list of assert_object +assert_object = { + argument, // target argument of the operationid + function, // functionid to do the assert + data, // stores data specific to the chosen function + state // if this assert is statefull +} +``` +List of possible asserts are: + +| function | data | state | +| ------------- |:-------------:| -----:| +| `any` | [`list`, `of`, `allowed`, `values`] | stateless | +| `range` | [`min`, `max`] | stateless | +| `limit` | [`value`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | +| `limit_monthly` | [`value`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | + +Example A: Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: ``` custom active authority = { - operationid: 0 (transfer), + valid_from: 7.7.2018 00:00 + valid_to: 8.7.2018 00:00 + operationid: transfer, authority: { threshold: 1 key_auth: [K, 1] account_auth: [] }, - assert: { - to: B - } + asserts: [ + { + argument: to + function: any, + data: [B] + } + ] } ``` That has the consquence now that a a transfer transaction sending funds away from A can be signed with key K as long as the receiver is B. @@ -73,6 +104,16 @@ Requirements to modify the backend includes * Operation-specific authorities (if present) must be evaluated in incoming transactions * Additional committee parameters may be needed to limit the extend of usage of this feature +Note: The implementation must not differentiate the logic, all operations receive the same + +# Milestones +We propose do split the implmentation into two milestones: + +1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `range` and `any` `asserts` +2. Evaluation of stateful asserts (performance) and if positive, implementation of `limit` and `limit_monthly` `asserts` + +This approach allows as well to add other asserts at a later stage (with a new BSIP). + # Discussion To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/1061). @@ -81,6 +122,8 @@ To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/10 Bad publicity in terms of security can have very negative effect on the BTS value. This BSIP allows that traders can e.g. use a trading key, witnesses can use their witness key and a faucet can use a faucet key. If then for some reason the key or witness/faucet server becomes compromised, such a key can do little harm to the account holders, minimizing the risk. +This BSIP opens up a lot of use-cases for the backend as well. + # Copyright This document is placed in the public domain. From 859169559d04f2dd6b92218ddde23f218e8441b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 27 Jul 2018 14:43:51 +0200 Subject: [PATCH 12/89] include more assert descrption and lisght rewriting --- bsip-0040.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 0e74c74..0bf6322 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -40,9 +40,10 @@ The above list of named keys is nothing that is known to the backend as the back # Rational The description here is more on a superficial level and no recommendation how it can best be implemented. -Custom active permission is a list of custom active authorities. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `asserts` than can be used to restrict arguments. When a transaction is signed with such an authority the backend checks if the contained operation has a corresponding custom active authority entry and if so acts as if the active authority of the corresponding account is given. If there are several custom active authorities, any matched one grants this, thus finding the first match is sufficient. It also checks if the arguments are in the allowed range. +Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `asserts` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). +When a signed transaction arrives at the backend iterate the required accounts for each operations. If they have any one custom active authority that matches the given operation, signature and passes all asserts of the custom active authority, then the active authority of the required account is granted. This search can be stopped after finding one match. -A Custom Active Permission looks like follows (in JSON for clarification, backend serializes and stores in a different way): +A `custom_active_permission` looks like follows (in JSON for clarification, backend serializes and stores in a different way): ``` custom_active_permission = list of custom_active_authority items custom_active_authority = { @@ -104,7 +105,7 @@ Requirements to modify the backend includes * Operation-specific authorities (if present) must be evaluated in incoming transactions * Additional committee parameters may be needed to limit the extend of usage of this feature -Note: The implementation must not differentiate the logic, all operations receive the same +Notes: The implementation must not differentiate the logic, all operations receive the same. # Milestones We propose do split the implmentation into two milestones: @@ -122,7 +123,7 @@ To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/10 Bad publicity in terms of security can have very negative effect on the BTS value. This BSIP allows that traders can e.g. use a trading key, witnesses can use their witness key and a faucet can use a faucet key. If then for some reason the key or witness/faucet server becomes compromised, such a key can do little harm to the account holders, minimizing the risk. -This BSIP opens up a lot of use-cases for the backend as well. +This BSIP opens up a lot of use-cases as presented in Motivation section. The intention is to not alter any existing logic of the permission system, which reduces the risk of malfunctioning. # Copyright From 824549eaaaaf272745c0f47219889de3751f389f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 27 Jul 2018 14:52:12 +0200 Subject: [PATCH 13/89] Update bsip-0040.md --- bsip-0040.md | 1 + 1 file changed, 1 insertion(+) diff --git a/bsip-0040.md b/bsip-0040.md index 0bf6322..0693d0b 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -74,6 +74,7 @@ List of possible asserts are: | `range` | [`min`, `max`] | stateless | | `limit` | [`value`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`value`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | +All asserts apply to `int`, `float` and `string`. If `string` should be compared with any number value, use the length of the string instead. Example A: Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: From 71e57c5f6dc2437eec32ca45ac239c1ca571d474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 27 Jul 2018 14:52:29 +0200 Subject: [PATCH 14/89] Update bsip-0040.md --- bsip-0040.md | 1 + 1 file changed, 1 insertion(+) diff --git a/bsip-0040.md b/bsip-0040.md index 0693d0b..08cfe59 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -74,6 +74,7 @@ List of possible asserts are: | `range` | [`min`, `max`] | stateless | | `limit` | [`value`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`value`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | + All asserts apply to `int`, `float` and `string`. If `string` should be compared with any number value, use the length of the string instead. Example A: From 54d0ee678da4d2ed4398e112306344c7ec94b107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 27 Jul 2018 14:52:58 +0200 Subject: [PATCH 15/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 08cfe59..00d815f 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -75,7 +75,7 @@ List of possible asserts are: | `limit` | [`value`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`value`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | -All asserts apply to `int`, `float` and `string`. If `string` should be compared with any number value, use the length of the string instead. +All asserts apply to `int`, `float` and `string`. If `string` should be compared with any number value, use the length of the string instead. Any more sophisticated data types are not included yet. Example A: Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: From 1083311739812f8d9e49d1734bbc1dd1a5865c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 27 Jul 2018 15:00:07 +0200 Subject: [PATCH 16/89] Update bsip-0040.md --- bsip-0040.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 00d815f..b9fd811 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -72,10 +72,11 @@ List of possible asserts are: | ------------- |:-------------:| -----:| | `any` | [`list`, `of`, `allowed`, `values`] | stateless | | `range` | [`min`, `max`] | stateless | +| `length` | [`min`, `max`] | stateless | | `limit` | [`value`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`value`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | -All asserts apply to `int`, `float` and `string`. If `string` should be compared with any number value, use the length of the string instead. Any more sophisticated data types are not included yet. +All asserts apply to `int`, `string` and `object_ids`. There is no type converstion, incompatible type means assert failure. Any more sophisticated data types are not included yet. The `length` assert is specific to `string`, whereas `range`, `limit` and `limit_monthly` is only applicable to `int`. Example A: Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: @@ -112,7 +113,7 @@ Notes: The implementation must not differentiate the logic, all operations recei # Milestones We propose do split the implmentation into two milestones: -1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `range` and `any` `asserts` +1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `range`, `length` and `any` `asserts` 2. Evaluation of stateful asserts (performance) and if positive, implementation of `limit` and `limit_monthly` `asserts` This approach allows as well to add other asserts at a later stage (with a new BSIP). From 189ceec7b177d2d5f321396ba59bbf2ac95dfcbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 27 Jul 2018 15:54:30 +0200 Subject: [PATCH 17/89] Update bsip-0040.md --- bsip-0040.md | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index b9fd811..0a6869d 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -43,6 +43,8 @@ The description here is more on a superficial level and no recommendation how it Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `asserts` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When a signed transaction arrives at the backend iterate the required accounts for each operations. If they have any one custom active authority that matches the given operation, signature and passes all asserts of the custom active authority, then the active authority of the required account is granted. This search can be stopped after finding one match. +### Custom active permission + A `custom_active_permission` looks like follows (in JSON for clarification, backend serializes and stores in a different way): ``` custom_active_permission = list of custom_active_authority items @@ -56,6 +58,8 @@ custom_active_authority = { ``` Note: This assumes `custom_active_permission` is stored within `account_object`. Actual implementation details left to the implementer. +### Possible asserts + The `asserts` is a list of `assert_objects` that are all together evaluated with `and` logic to evaluate a match ``` asserts = list of assert_object @@ -73,12 +77,29 @@ List of possible asserts are: | `any` | [`list`, `of`, `allowed`, `values`] | stateless | | `range` | [`min`, `max`] | stateless | | `length` | [`min`, `max`] | stateless | -| `limit` | [`value`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | -| `limit_monthly` | [`value`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | +| `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | +| `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | -All asserts apply to `int`, `string` and `object_ids`. There is no type converstion, incompatible type means assert failure. Any more sophisticated data types are not included yet. The `length` assert is specific to `string`, whereas `range`, `limit` and `limit_monthly` is only applicable to `int`. +All asserts apply to `int`, `string` and `object_ids`. There is no type converstion, incompatible type means assert failure. Any more sophisticated data types are not included yet. -Example A: +#### `any` +Stateless assert, all argument types. Value of argument must be equal to one of values in the list + +#### `range` +Stateless assert, only `int` type arguments. Value must be inbetween `min` and `max`, inclusive. One of the bounds can be empty to indicate unlimited. + +#### `length` +Stateless assert, only `string` type arguments. Length of string (or encrypted string in case of memo) must be within `min` and `max`, inclusive. One of the bounds can be empty to indicate unlimited. + +#### `limit` +Statefull assert, only `int` type arguments. When the authority is created, `interval_began` is set to `valid_from` from its custom active authority and `max_cumsum` to `0`. Incoming operations are first tried to match all stateless asserts, +and if all passes continue with statefull asserts. If `now > interval_began + interval_in_sec`, then set `max_cumsum = 0`. +The assert that needs to pass is now `current_cumsum + incoming value <= max_cumsum`. If all asserts are passed, update `current_cumsum` of all involved statefull asserts. + +#### `limit_monthly` +Statefull assert, only `int` type arguments. Analogue to `limit`, but the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). + +### Simple Example Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: ``` custom active authority = { From cb79a4fc137f7cb5ed2f729b77a3e1c620b3fb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 27 Jul 2018 15:57:24 +0200 Subject: [PATCH 18/89] Update bsip-0040.md --- bsip-0040.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 0a6869d..a3a972b 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -93,11 +93,11 @@ Stateless assert, only `string` type arguments. Length of string (or encrypted s #### `limit` Statefull assert, only `int` type arguments. When the authority is created, `interval_began` is set to `valid_from` from its custom active authority and `max_cumsum` to `0`. Incoming operations are first tried to match all stateless asserts, -and if all passes continue with statefull asserts. If `now > interval_began + interval_in_sec`, then set `max_cumsum = 0`. -The assert that needs to pass is now `current_cumsum + incoming value <= max_cumsum`. If all asserts are passed, update `current_cumsum` of all involved statefull asserts. +and if all passes continue with statefull asserts. If `now > interval_began + interval_in_sec`, then set `max_cumsum = 0` and set `interval_began = now`. +The assert that needs to pass is now `current_cumsum + incoming value <= max_cumsum`. If all asserts are passed, update `current_cumsum = current_cumsum + incoming value` of all involved statefull asserts. #### `limit_monthly` -Statefull assert, only `int` type arguments. Analogue to `limit`, but the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). +Statefull assert, only `int` type arguments. Analogue to `limit`, but `interval_began` is initially set to `month(valid_from)` and set to `month(now)` on update, additionally the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). ### Simple Example Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: From e6cc5f125232b766fae8deb350dea5bdbba82710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 27 Jul 2018 21:56:40 +0200 Subject: [PATCH 19/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index a3a972b..d40342d 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -124,7 +124,7 @@ That has the consquence now that a a transfer transaction sending funds away fro # Specifications Requirements to modify the backend includes -* Extend the account object to store custom active permission that includes a list of custom active authorities. Multiple custom active authority entries are possible for one operation +* Extend the account object to store custom active permission that includes a list of custom active authorities. Multiple custom active authority entries are possible for one operation. If the active authority of the account is updated all custom active authorities need to be confirmed in the update, every unconfirmed one is deleted otherwise * Extend `account_update` or create a new operation to allow changing the custom active permission * Operation-specific authorities (if present) must be evaluated in incoming transactions * Additional committee parameters may be needed to limit the extend of usage of this feature From 75faa36dee7fbb46ab274c201973e49a93c3d736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sat, 28 Jul 2018 15:43:41 +0200 Subject: [PATCH 20/89] Update bsip-0040.md --- bsip-0040.md | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index d40342d..dfcce2e 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -39,11 +39,13 @@ The above list of named keys is nothing that is known to the backend as the back # Rational -The description here is more on a superficial level and no recommendation how it can best be implemented. -Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `asserts` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). -When a signed transaction arrives at the backend iterate the required accounts for each operations. If they have any one custom active authority that matches the given operation, signature and passes all asserts of the custom active authority, then the active authority of the required account is granted. This search can be stopped after finding one match. +Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `asserts` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of the required accounts. If all operations within the transaction have a matching `custom active authority` (match means same `operationid`, now is within `valid_to` and `valid_from` and all `asserts` pass), then active authority of the corresponding account is granted. -### Custom active permission +# Specification + +All descriptions in this section are on a pseudo/prosa level and no recommendation how it can best be implemented or serialized. They are meant to facilitate the understanding. + +### Custom active permission and custom active authority A `custom_active_permission` looks like follows (in JSON for clarification, backend serializes and stores in a different way): ``` @@ -58,7 +60,7 @@ custom_active_authority = { ``` Note: This assumes `custom_active_permission` is stored within `account_object`. Actual implementation details left to the implementer. -### Possible asserts +### Asserts The `asserts` is a list of `assert_objects` that are all together evaluated with `and` logic to evaluate a match ``` @@ -120,16 +122,29 @@ custom active authority = { ] } ``` -That has the consquence now that a a transfer transaction sending funds away from A can be signed with key K as long as the receiver is B. +That has the consquence now that a transfer transaction sending funds away from A can be signed with key K as long as the receiver is B. -# Specifications -Requirements to modify the backend includes -* Extend the account object to store custom active permission that includes a list of custom active authorities. Multiple custom active authority entries are possible for one operation. If the active authority of the account is updated all custom active authorities need to be confirmed in the update, every unconfirmed one is deleted otherwise +Note: This is just an illustration of a possible serialization, not a specification of the serialized format. + +### Outline of handling incoming transactions + +When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: +- iterate over required accounts and for each account, iterate over all operations within the transactions that require the active authority of this account +- iterate the `custom_active_authorities` of said account +- if a `custom_active_authority` is found that matches (same `operationid` and passes all `asserts`), remember that and stop iterating the authorities and continue until all operations are checked +- if the account has a `custom active authority` match for every operation in the transaction that requires it, then grant the `active authority` of said account. If no match is found, treat as if no authority was given + +Note: +- A `custom_active_authority` can only grant the `active authority` of the corresponding account, nothing more + +### Modification to the backend +* Extend the account object to store custom active permission that includes a list of custom active authorities. Multiple custom active authority entries are possible for one operation +* If the active authority of the account is updated, all custom active authorities need to be confirmed in the update. Every unconfirmed one is deleted otherwise * Extend `account_update` or create a new operation to allow changing the custom active permission * Operation-specific authorities (if present) must be evaluated in incoming transactions * Additional committee parameters may be needed to limit the extend of usage of this feature -Notes: The implementation must not differentiate the logic, all operations receive the same. +Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion # Milestones We propose do split the implmentation into two milestones: From 5b5e550c280ce27c1b884e8fb799075b0146d0a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sat, 28 Jul 2018 15:56:49 +0200 Subject: [PATCH 21/89] Update bsip-0040.md --- bsip-0040.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index dfcce2e..c88d77e 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -24,9 +24,9 @@ can be restricted. Any successfull hacking or phishing attempt on any of the web wallets that are powered by the BitShares Blockchain is bad publicity. The user needs to be educated in account security, and this BSIP -aims to ensure all technical possibilities are met while being flexible to allow many use-cases. +aims to ensure all technical possibilities are met while being flexible to allow many use-cases. -Examples: +With this BSIP any user can create keys with specific purpose (everything else is prohibited). We list some possibilities below: - Witness Key: Only allows update signing key and publish price feed - Trading Key: Only allows limit orders (arguments restricted to desired markets), update margin position and transfers (arguments restricted to certain accounts) - Proposal Update Key: Approve proposals (2FA comes to mind) From 7ae9f94d73f38c7091df4d37dc543b201cd05a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sat, 28 Jul 2018 16:03:14 +0200 Subject: [PATCH 22/89] Update bsip-0040.md --- bsip-0040.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index c88d77e..edb1f6f 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -47,24 +47,24 @@ All descriptions in this section are on a pseudo/prosa level and no recommendati ### Custom active permission and custom active authority -A `custom_active_permission` looks like follows (in JSON for clarification, backend serializes and stores in a different way): +A `custom_active_permission` looks like follows (in JSON/pseudo for clarification): ``` custom_active_permission = list of custom_active_authority items custom_active_authority = { - valid_from, // this custom active authority is valid starting at this timestamp, defaults to now - valid_to, // this custom active authority is valid until this timestamp, defaults to 1 year - operationid, - authority, - asserts + valid_from, // timestamp when this is active, defaults to now + valid_to, // timestamp when this is invalid, defaults to 1 month + operationid, // operationid of the target operation, + authority, // same as for the existing authortities (multisig with weighted accounts or keys), + asserts // see below } ``` -Note: This assumes `custom_active_permission` is stored within `account_object`. Actual implementation details left to the implementer. +Note: This assumes `custom_active_permission` is stored within `account_object`. Actual implementation details left to the implementer, as long as every `custom_active_permission` can be assigned to exactly one account. ### Asserts The `asserts` is a list of `assert_objects` that are all together evaluated with `and` logic to evaluate a match ``` -asserts = list of assert_object +asserts = list of assert_objects assert_object = { argument, // target argument of the operationid function, // functionid to do the assert From 55aa5b04ebfa4a86701fcfcf72fb7f51ff6a66e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sat, 28 Jul 2018 16:03:49 +0200 Subject: [PATCH 23/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index edb1f6f..9ff181c 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -156,7 +156,7 @@ This approach allows as well to add other asserts at a later stage (with a new B # Discussion -To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/1061). +To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/1061) and [pull request](https://github.com/bitshares/bsips/pull/86). # Summary for Shareholders From ef397f0be18702fa801e7a1efec537bbb77960b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sat, 28 Jul 2018 23:31:57 +0200 Subject: [PATCH 24/89] Update bsip-0040.md --- bsip-0040.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 9ff181c..2d27915 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -77,18 +77,28 @@ List of possible asserts are: | function | data | state | | ------------- |:-------------:| -----:| | `any` | [`list`, `of`, `allowed`, `values`] | stateless | -| `range` | [`min`, `max`] | stateless | +| `none` | [`none`, `of`, `these`, `values`] | stateless | +| `lt, le, gt, ge` | `comparative` | stateless | | `length` | [`min`, `max`] | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | All asserts apply to `int`, `string` and `object_ids`. There is no type converstion, incompatible type means assert failure. Any more sophisticated data types are not included yet. -#### `any` -Stateless assert, all argument types. Value of argument must be equal to one of values in the list +In the following we list possible `asserts`. Mentioning `argument value` refers to the value of the argument of the operation specified `argument` in `assert_object`. -#### `range` -Stateless assert, only `int` type arguments. Value must be inbetween `min` and `max`, inclusive. One of the bounds can be empty to indicate unlimited. +#### `any` +Stateless assert, all argument types. `Argument value` must be equal to one of values in the data list + +#### `none` +Stateless assert, all argument types. `Argument value` must NOT be equal to any of the values in the list. + +#### `lt, le, gt, ge` +Stateless assert, only `int` type arguments. +- `lt`: `Argument value` must be less than `comparitive` +- `lt`: `Argument value` must be less than or equal to `comparitive` +- `lt`: `Argument value` must be greater than `comparitive` +- `lt`: `Argument value` must be greater than or equal to `comparitive` #### `length` Stateless assert, only `string` type arguments. Length of string (or encrypted string in case of memo) must be within `min` and `max`, inclusive. One of the bounds can be empty to indicate unlimited. From bcfa32f90ca55d717048ce9b9a70cf1ccf2309e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sat, 28 Jul 2018 23:38:48 +0200 Subject: [PATCH 25/89] Update bsip-0040.md --- bsip-0040.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bsip-0040.md b/bsip-0040.md index 2d27915..a62ba5f 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -82,6 +82,7 @@ List of possible asserts are: | `length` | [`min`, `max`] | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | +| `contains` | [`list`, `of`, `allowed`, `fields`] | stateless | All asserts apply to `int`, `string` and `object_ids`. There is no type converstion, incompatible type means assert failure. Any more sophisticated data types are not included yet. @@ -111,6 +112,9 @@ The assert that needs to pass is now `current_cumsum + incoming value <= max_cum #### `limit_monthly` Statefull assert, only `int` type arguments. Analogue to `limit`, but `interval_began` is initially set to `month(valid_from)` and set to `month(now)` on update, additionally the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). +#### `contains_only` +Stateless assert, only for dictionary type objects like `options`. The `argument` of the operation is a dictionary type objects and is only allowed to contain the attributes in the data list. + ### Simple Example Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: ``` From 5da66a4c34a2fbf6eac2a16f89b22eb104ed7675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sat, 28 Jul 2018 23:43:28 +0200 Subject: [PATCH 26/89] Update bsip-0040.md --- bsip-0040.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index a62ba5f..41fd2df 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -82,9 +82,9 @@ List of possible asserts are: | `length` | [`min`, `max`] | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | -| `contains` | [`list`, `of`, `allowed`, `fields`] | stateless | +| `contains_only` | [`list`, `of`, `allowed`, `fields`] | stateless | -All asserts apply to `int`, `string` and `object_ids`. There is no type converstion, incompatible type means assert failure. Any more sophisticated data types are not included yet. +There is no implicit type conversion when attempting to assert, incompatible type means assert failure. In the following we list possible `asserts`. Mentioning `argument value` refers to the value of the argument of the operation specified `argument` in `assert_object`. @@ -96,10 +96,10 @@ Stateless assert, all argument types. `Argument value` must NOT be equal to any #### `lt, le, gt, ge` Stateless assert, only `int` type arguments. -- `lt`: `Argument value` must be less than `comparitive` -- `lt`: `Argument value` must be less than or equal to `comparitive` -- `lt`: `Argument value` must be greater than `comparitive` -- `lt`: `Argument value` must be greater than or equal to `comparitive` +- `lt`: `Argument value` must be less than `comparative` +- `le`: `Argument value` must be less than or equal to `comparative` +- `gt`: `Argument value` must be greater than `comparative` +- `ge`: `Argument value` must be greater than or equal to `comparative` #### `length` Stateless assert, only `string` type arguments. Length of string (or encrypted string in case of memo) must be within `min` and `max`, inclusive. One of the bounds can be empty to indicate unlimited. @@ -163,8 +163,8 @@ Notes: The implementation must not differentiate on which operation the custom a # Milestones We propose do split the implmentation into two milestones: -1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `range`, `length` and `any` `asserts` -2. Evaluation of stateful asserts (performance) and if positive, implementation of `limit` and `limit_monthly` `asserts` +1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none`, `lt, le, gt, ge` and `length` `asserts` +2. Evaluation of stateful and more sophisticated asserts in terms of performance and if positive, implementation of `limit`, `limit_monthly` and `contains_only` `asserts` This approach allows as well to add other asserts at a later stage (with a new BSIP). From 6c64b50d23f169e2d06722600263bfc2500ff77a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sat, 28 Jul 2018 23:53:05 +0200 Subject: [PATCH 27/89] Update bsip-0040.md --- bsip-0040.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 41fd2df..a384f19 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -39,7 +39,7 @@ The above list of named keys is nothing that is known to the backend as the back # Rational -Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `asserts` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of the required accounts. If all operations within the transaction have a matching `custom active authority` (match means same `operationid`, now is within `valid_to` and `valid_from` and all `asserts` pass), then active authority of the corresponding account is granted. +Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `asserts` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of its required accounts. Check for every required account of the transaction if all its belonging operations have at least one positively matched `custom active authority` (match means same `operationid`, now is within `valid_to` and `valid_from` and all `asserts` pass), and if so grant the active authority of the corresponding account. # Specification @@ -145,7 +145,7 @@ Note: This is just an illustration of a possible serialization, not a specificat When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: - iterate over required accounts and for each account, iterate over all operations within the transactions that require the active authority of this account - iterate the `custom_active_authorities` of said account -- if a `custom_active_authority` is found that matches (same `operationid` and passes all `asserts`), remember that and stop iterating the authorities and continue until all operations are checked +- if a `custom_active_authority` is found that matches (same `operationid`, now is within `valid_to` and `valid_from` and passes all `asserts`), remember that and stop iterating the authorities and continue until all operations are checked - if the account has a `custom active authority` match for every operation in the transaction that requires it, then grant the `active authority` of said account. If no match is found, treat as if no authority was given Note: From 8207e247216a8d08bc608be8413bd77a6c65d04d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 00:01:37 +0200 Subject: [PATCH 28/89] Update bsip-0040.md --- bsip-0040.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index a384f19..8aec251 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -39,11 +39,11 @@ The above list of named keys is nothing that is known to the backend as the back # Rational -Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `asserts` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of its required accounts. Check for every required account of the transaction if all its belonging operations have at least one positively matched `custom active authority` (match means same `operationid`, now is within `valid_to` and `valid_from` and all `asserts` pass), and if so grant the active authority of the corresponding account. +Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `asserts` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of its required accounts. Check for every required account of the transaction if all its belonging operations have at least one positively matched `custom active authority` (match means its `authority` is granted through present signatures, same `operationid`, now is within `valid_to` and `valid_from` and all `asserts` pass), and if so grant the active authority of the corresponding account. # Specification -All descriptions in this section are on a pseudo/prosa level and no recommendation how it can best be implemented or serialized. They are meant to facilitate the understanding. +All descriptions in this section are on a pseudo/prosa level and no recommendation how it can best be implemented or serialized. They are meant to facilitate the understanding. If anything in the looping process or order of evaluation is unsuitable for actual implementation, changes can be made accordingly as long the same functionality is achieved. ### Custom active permission and custom active authority @@ -145,7 +145,7 @@ Note: This is just an illustration of a possible serialization, not a specificat When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: - iterate over required accounts and for each account, iterate over all operations within the transactions that require the active authority of this account - iterate the `custom_active_authorities` of said account -- if a `custom_active_authority` is found that matches (same `operationid`, now is within `valid_to` and `valid_from` and passes all `asserts`), remember that and stop iterating the authorities and continue until all operations are checked +- if a `custom_active_authority` is found that matches (match means its `authority` is granted through present signatures, same `operationid`, now is within `valid_to` and `valid_from` and passes all `asserts`), remember that and stop iterating the authorities and continue until all operations are checked - if the account has a `custom active authority` match for every operation in the transaction that requires it, then grant the `active authority` of said account. If no match is found, treat as if no authority was given Note: From e2d902290a6768ed2a81a6f316a8d01ec4232003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 00:16:52 +0200 Subject: [PATCH 29/89] Update bsip-0040.md --- bsip-0040.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 8aec251..13d43be 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -115,7 +115,7 @@ Statefull assert, only `int` type arguments. Analogue to `limit`, but `interval_ #### `contains_only` Stateless assert, only for dictionary type objects like `options`. The `argument` of the operation is a dictionary type objects and is only allowed to contain the attributes in the data list. -### Simple Example +### Example: Simple transfer Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: ``` custom active authority = { @@ -151,6 +151,15 @@ When a signed transaction arrives and before the backend evaluates if all necess Note: - A `custom_active_authority` can only grant the `active authority` of the corresponding account, nothing more +### Example: Checking for custom active authorities + +Assume Account A, B and C. Now A has two `custom active authorities`: + + - `custom active authority 1`: Allow Account B to transfer asset X to D + - `custom active authority 2`: Allow Account C to transfer asset X to D + +The incoming transaction now contains `transfer 100 asset X from A to D, signed by all signatures required for active authority of C`. The required accounts (meaning required active authority) for the transaction is Account A. Backend would start considering `custom active authority 1` and check if active authority of account B is present through signatures. It is not, thus continue by checking if authority of `custom active authority 2` is present, which it is. Acive authority of Account A is granted and normal authority checks are continued. Since the required accounts is Account A, and the given accounts is also Account A through `custom active authority 2`, the transaction is executed. + ### Modification to the backend * Extend the account object to store custom active permission that includes a list of custom active authorities. Multiple custom active authority entries are possible for one operation * If the active authority of the account is updated, all custom active authorities need to be confirmed in the update. Every unconfirmed one is deleted otherwise From fccca2076168a5af3e8654f061b4913cc74602e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 00:18:01 +0200 Subject: [PATCH 30/89] Update bsip-0040.md --- bsip-0040.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 13d43be..73f6f69 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -115,7 +115,7 @@ Statefull assert, only `int` type arguments. Analogue to `limit`, but `interval_ #### `contains_only` Stateless assert, only for dictionary type objects like `options`. The `argument` of the operation is a dictionary type objects and is only allowed to contain the attributes in the data list. -### Example: Simple transfer +#### Example: Simple transfer Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: ``` custom active authority = { @@ -151,14 +151,20 @@ When a signed transaction arrives and before the backend evaluates if all necess Note: - A `custom_active_authority` can only grant the `active authority` of the corresponding account, nothing more -### Example: Checking for custom active authorities +#### Example: Checking for custom active authorities Assume Account A, B and C. Now A has two `custom active authorities`: - `custom active authority 1`: Allow Account B to transfer asset X to D - `custom active authority 2`: Allow Account C to transfer asset X to D -The incoming transaction now contains `transfer 100 asset X from A to D, signed by all signatures required for active authority of C`. The required accounts (meaning required active authority) for the transaction is Account A. Backend would start considering `custom active authority 1` and check if active authority of account B is present through signatures. It is not, thus continue by checking if authority of `custom active authority 2` is present, which it is. Acive authority of Account A is granted and normal authority checks are continued. Since the required accounts is Account A, and the given accounts is also Account A through `custom active authority 2`, the transaction is executed. +The incoming transaction now contains `transfer 100 asset X from A to D, signed by all signatures required for active authority of C`. +The required accounts (meaning required active authority) for the transaction is Account A. +Backend would start considering `custom active authority 1` and check if active authority of account B is present through signatures. +It is not, thus continue by checking if authority of `custom active authority 2` is present, which it is. +Acive authority of Account A is granted and normal authority checks are continued. +Since the required accounts is Account A, and the given accounts is also Account A through `custom active authority 2`, +the transaction is executed. ### Modification to the backend * Extend the account object to store custom active permission that includes a list of custom active authorities. Multiple custom active authority entries are possible for one operation From 2bcc40ae04d6492819698b2bab4f87c21d090549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 00:20:00 +0200 Subject: [PATCH 31/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 73f6f69..6c31e69 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -178,7 +178,7 @@ Notes: The implementation must not differentiate on which operation the custom a # Milestones We propose do split the implmentation into two milestones: -1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none`, `lt, le, gt, ge` and `length` `asserts` +1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none`, `lt, le, gt, ge` and `length` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` 2. Evaluation of stateful and more sophisticated asserts in terms of performance and if positive, implementation of `limit`, `limit_monthly` and `contains_only` `asserts` This approach allows as well to add other asserts at a later stage (with a new BSIP). From 4349e8da45d71bbb0688dfeefc1d9b255e9ef5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 00:22:22 +0200 Subject: [PATCH 32/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 6c31e69..b87b5ce 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -179,7 +179,7 @@ Notes: The implementation must not differentiate on which operation the custom a We propose do split the implmentation into two milestones: 1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none`, `lt, le, gt, ge` and `length` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` -2. Evaluation of stateful and more sophisticated asserts in terms of performance and if positive, implementation of `limit`, `limit_monthly` and `contains_only` `asserts` +2. Evaluation of stateful asserts `limit`, `limit_monthly` and more sophisticated assert `contains_only` in terms of performance. If positively evaluated, implement This approach allows as well to add other asserts at a later stage (with a new BSIP). From 2051ff38f81dd866a0ebdb883f262866348bc309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 00:28:32 +0200 Subject: [PATCH 33/89] Update bsip-0040.md --- bsip-0040.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index b87b5ce..24e2516 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -79,7 +79,6 @@ List of possible asserts are: | `any` | [`list`, `of`, `allowed`, `values`] | stateless | | `none` | [`none`, `of`, `these`, `values`] | stateless | | `lt, le, gt, ge` | `comparative` | stateless | -| `length` | [`min`, `max`] | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | | `contains_only` | [`list`, `of`, `allowed`, `fields`] | stateless | @@ -95,7 +94,7 @@ Stateless assert, all argument types. `Argument value` must be equal to one of v Stateless assert, all argument types. `Argument value` must NOT be equal to any of the values in the list. #### `lt, le, gt, ge` -Stateless assert, only `int` type arguments. +Stateless assert, applies to `int` and `string` type arguments. If argument is `string` type, use its length as `argument value`. - `lt`: `Argument value` must be less than `comparative` - `le`: `Argument value` must be less than or equal to `comparative` - `gt`: `Argument value` must be greater than `comparative` @@ -178,7 +177,7 @@ Notes: The implementation must not differentiate on which operation the custom a # Milestones We propose do split the implmentation into two milestones: -1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none`, `lt, le, gt, ge` and `length` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` +1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` 2. Evaluation of stateful asserts `limit`, `limit_monthly` and more sophisticated assert `contains_only` in terms of performance. If positively evaluated, implement This approach allows as well to add other asserts at a later stage (with a new BSIP). From 6df4a3824bb5f8bf578244ebb3c183a7834cfebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 07:10:44 +0200 Subject: [PATCH 34/89] remove length, add price as explicit allowed conversion --- bsip-0040.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 24e2516..fd7df57 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -47,7 +47,7 @@ All descriptions in this section are on a pseudo/prosa level and no recommendati ### Custom active permission and custom active authority -A `custom_active_permission` looks like follows (in JSON/pseudo for clarification): +A `custom_active_permission` looks like follows (in JSON-like/pseudo for clarification): ``` custom_active_permission = list of custom_active_authority items custom_active_authority = { @@ -94,15 +94,17 @@ Stateless assert, all argument types. `Argument value` must be equal to one of v Stateless assert, all argument types. `Argument value` must NOT be equal to any of the values in the list. #### `lt, le, gt, ge` -Stateless assert, applies to `int` and `string` type arguments. If argument is `string` type, use its length as `argument value`. +Stateless assert. Allows explicit type converstion: +- `int` type: use as is +- `string` type: user `length` as `argument value` +- `price` struct `{base = {amount, asset_id}, quote = {amount, asset_id}}`: convert to float price `argument value = base.amount/quote.amount` + +The different asserts read as: - `lt`: `Argument value` must be less than `comparative` - `le`: `Argument value` must be less than or equal to `comparative` - `gt`: `Argument value` must be greater than `comparative` - `ge`: `Argument value` must be greater than or equal to `comparative` -#### `length` -Stateless assert, only `string` type arguments. Length of string (or encrypted string in case of memo) must be within `min` and `max`, inclusive. One of the bounds can be empty to indicate unlimited. - #### `limit` Statefull assert, only `int` type arguments. When the authority is created, `interval_began` is set to `valid_from` from its custom active authority and `max_cumsum` to `0`. Incoming operations are first tried to match all stateless asserts, and if all passes continue with statefull asserts. If `now > interval_began + interval_in_sec`, then set `max_cumsum = 0` and set `interval_began = now`. From ba625b1cd303f318e75defb43bcd8a5faf2df958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 07:43:14 +0200 Subject: [PATCH 35/89] remove contains only, and add attibute_assert --- bsip-0040.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index fd7df57..fff721a 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -81,11 +81,11 @@ List of possible asserts are: | `lt, le, gt, ge` | `comparative` | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | -| `contains_only` | [`list`, `of`, `allowed`, `fields`] | stateless | +| `may_mutate` | `attribute_to_assert` = [{`attribute_identifier`: `any of above assert_objects`}] | stateless | There is no implicit type conversion when attempting to assert, incompatible type means assert failure. -In the following we list possible `asserts`. Mentioning `argument value` refers to the value of the argument of the operation specified `argument` in `assert_object`. +In the following we list possible `asserts`. Mentioning `argument value` refers to the value of the argument of the operation specified `argument` in `assert_object`. The logic does not differentiate if an `argument` is optional or mandatory. All asserts imply: If the `argument` is given, it must pass the `assert`. If the `argument` is not given, assert is implicitly passed. #### `any` Stateless assert, all argument types. `Argument value` must be equal to one of values in the data list @@ -113,8 +113,11 @@ The assert that needs to pass is now `current_cumsum + incoming value <= max_cum #### `limit_monthly` Statefull assert, only `int` type arguments. Analogue to `limit`, but `interval_began` is initially set to `month(valid_from)` and set to `month(now)` on update, additionally the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). -#### `contains_only` -Stateless assert, only for dictionary type objects like `options`. The `argument` of the operation is a dictionary type objects and is only allowed to contain the attributes in the data list. +#### `attribute_assert` +Stateless assert, only for dictionary type objects. The `attribute_to_assert` list contains mappings between attributes and asserts that they must fulfill, if present in the dictionary. + +Note: +- Assume `asset_update_operation`. All attributes of its `options` must be filled on update call. This assert can not be used to realize a "may only change attribute xzy of `options`". This would require that the logic knows which of the arguments are reflected on-chain and it knows how to query it for every operation that contains `options`. If `options` are to be restricted with this assert, all values that should not change would need be fixated by defining a `any` assert for those attributes, while having e.g. a `lt` assert for the one attribute that is allowed to change. #### Example: Simple transfer Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: From 1d4aa4266b2a1fef707d70f1a038587213f178a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 07:46:33 +0200 Subject: [PATCH 36/89] Update bsip-0040.md --- bsip-0040.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index fff721a..a9a27ac 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -81,9 +81,9 @@ List of possible asserts are: | `lt, le, gt, ge` | `comparative` | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | -| `may_mutate` | `attribute_to_assert` = [{`attribute_identifier`: `any of above assert_objects`}] | stateless | +| `attribute_assert` | `attribute_to_assert` = [{`attribute_identifier`: `any of above assert_objects`}] | stateless | -There is no implicit type conversion when attempting to assert, incompatible type means assert failure. +There is no implicit type conversion when attempting to assert, incompatible type means assert failure. If required, a field can be added that stores the assumed type of the argument (if conversion fails, assert fails). In the following we list possible `asserts`. Mentioning `argument value` refers to the value of the argument of the operation specified `argument` in `assert_object`. The logic does not differentiate if an `argument` is optional or mandatory. All asserts imply: If the `argument` is given, it must pass the `assert`. If the `argument` is not given, assert is implicitly passed. From 523ed86eabbfec43400c62445ed6b579995cf0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 07:58:18 +0200 Subject: [PATCH 37/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index a9a27ac..9948025 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -83,7 +83,7 @@ List of possible asserts are: | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | | `attribute_assert` | `attribute_to_assert` = [{`attribute_identifier`: `any of above assert_objects`}] | stateless | -There is no implicit type conversion when attempting to assert, incompatible type means assert failure. If required, a field can be added that stores the assumed type of the argument (if conversion fails, assert fails). +There is no implicit type conversion when attempting to assert, incompatible type means assert failure. If required, a field can be added that stores the assumed type of the argument (if conversion fails, assert fails). If an argument has no asset, it is unrestricted and may be given (or not for optional arguments) with any value. In the following we list possible `asserts`. Mentioning `argument value` refers to the value of the argument of the operation specified `argument` in `assert_object`. The logic does not differentiate if an `argument` is optional or mandatory. All asserts imply: If the `argument` is given, it must pass the `assert`. If the `argument` is not given, assert is implicitly passed. From 07b6fa080d951076c3771b8a6b8a4a52e74ae2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 08:07:44 +0200 Subject: [PATCH 38/89] Update bsip-0040.md --- bsip-0040.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 9948025..fc4cc38 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -182,8 +182,8 @@ Notes: The implementation must not differentiate on which operation the custom a # Milestones We propose do split the implmentation into two milestones: -1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` -2. Evaluation of stateful asserts `limit`, `limit_monthly` and more sophisticated assert `contains_only` in terms of performance. If positively evaluated, implement +1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` +2. Evaluation of stateful asserts `limit` and `limit_monthly` in terms of performance. If positively evaluated, implement This approach allows as well to add other asserts at a later stage (with a new BSIP). From ab5500dfda2251994919451198612ac971f9a723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 09:57:58 +0200 Subject: [PATCH 39/89] attribute assert nesting --- bsip-0040.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index fc4cc38..4ef2eb0 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -81,7 +81,7 @@ List of possible asserts are: | `lt, le, gt, ge` | `comparative` | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | -| `attribute_assert` | `attribute_to_assert` = [{`attribute_identifier`: `any of above assert_objects`}] | stateless | +| `attribute_assert` | `attribute_to_assert` = [{`attribute_identifier`: `any assert_objects`}] | stateless | There is no implicit type conversion when attempting to assert, incompatible type means assert failure. If required, a field can be added that stores the assumed type of the argument (if conversion fails, assert fails). If an argument has no asset, it is unrestricted and may be given (or not for optional arguments) with any value. @@ -114,7 +114,7 @@ The assert that needs to pass is now `current_cumsum + incoming value <= max_cum Statefull assert, only `int` type arguments. Analogue to `limit`, but `interval_began` is initially set to `month(valid_from)` and set to `month(now)` on update, additionally the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). #### `attribute_assert` -Stateless assert, only for dictionary type objects. The `attribute_to_assert` list contains mappings between attributes and asserts that they must fulfill, if present in the dictionary. +Stateless assert, only for dictionary type objects. The `attribute_to_assert` list contains mappings between attributes and asserts that they must fulfill, if present in the dictionary. Allows nesting of `attribute_assert`. Note: - Assume `asset_update_operation`. All attributes of its `options` must be filled on update call. This assert can not be used to realize a "may only change attribute xzy of `options`". This would require that the logic knows which of the arguments are reflected on-chain and it knows how to query it for every operation that contains `options`. If `options` are to be restricted with this assert, all values that should not change would need be fixated by defining a `any` assert for those attributes, while having e.g. a `lt` assert for the one attribute that is allowed to change. From 0e8e9ad705e2fe3663e656ebf29194cbe4ba3d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 29 Jul 2018 15:39:59 +0200 Subject: [PATCH 40/89] add economics --- bsip-0040.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 4ef2eb0..31e8885 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -52,7 +52,7 @@ A `custom_active_permission` looks like follows (in JSON-like/pseudo for clarifi custom_active_permission = list of custom_active_authority items custom_active_authority = { valid_from, // timestamp when this is active, defaults to now - valid_to, // timestamp when this is invalid, defaults to 1 month + valid_to, // timestamp when this is invalid, defaults to 1 year operationid, // operationid of the target operation, authority, // same as for the existing authortities (multisig with weighted accounts or keys), asserts // see below @@ -144,6 +144,12 @@ That has the consquence now that a transfer transaction sending funds away from Note: This is just an illustration of a possible serialization, not a specification of the serialized format. +### Economics + +Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. +We propose that the transaction fee for the creation is tied to the duration of the custom active authority. +Furthermore, normal accounts can only create custom active authoritites with a duration of maximum 1 year. LTM can do any duration and also unlimited, but the transaction fee is capped at duration of 2 years. + ### Outline of handling incoming transactions When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: @@ -180,7 +186,7 @@ the transaction is executed. Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion # Milestones -We propose do split the implmentation into two milestones: +We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: 1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` 2. Evaluation of stateful asserts `limit` and `limit_monthly` in terms of performance. If positively evaluated, implement From e145ede26a88f0383d8b064074ad7a6a9caa97fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 07:50:58 +0200 Subject: [PATCH 41/89] add wording and defition of match for authority --- bsip-0040.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 31e8885..d33f5ca 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -60,13 +60,22 @@ custom_active_authority = { ``` Note: This assumes `custom_active_permission` is stored within `account_object`. Actual implementation details left to the implementer, as long as every `custom_active_permission` can be assigned to exactly one account. +#### Wording + +A `custom active permission` contains a list of `custom active authority`. `Custom active authority` can match an operation of an incoming, signed transaction. The wording *matching* refers to: +- `operationid` is equal to the id of the incoming operation +- assigned account of parent `custom active permission` is in the required accounts of the operation +- the `authority` of the `custom_active_authority` is given by the signatures of the transaction +- `now` is within `valid_to` and `valid_from` +- all `asserts` pass positively + ### Asserts The `asserts` is a list of `assert_objects` that are all together evaluated with `and` logic to evaluate a match ``` -asserts = list of assert_objects +asserts = list of (argument_identifier, assert_object) tuples +argument_identifier = // target unknown, can be argument of operation, or in a nested dictionary like struct assert_object = { - argument, // target argument of the operationid function, // functionid to do the assert data, // stores data specific to the chosen function state // if this assert is statefull @@ -132,11 +141,10 @@ custom active authority = { account_auth: [] }, asserts: [ - { - argument: to + (to, { function: any, data: [B] - } + }) // this restricts the argument identified with "to" ] } ``` @@ -155,7 +163,7 @@ Furthermore, normal accounts can only create custom active authoritites with a d When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: - iterate over required accounts and for each account, iterate over all operations within the transactions that require the active authority of this account - iterate the `custom_active_authorities` of said account -- if a `custom_active_authority` is found that matches (match means its `authority` is granted through present signatures, same `operationid`, now is within `valid_to` and `valid_from` and passes all `asserts`), remember that and stop iterating the authorities and continue until all operations are checked +- if a `custom_active_authority` is found that matches , remember that and stop iterating the authorities and continue until all operations are checked - if the account has a `custom active authority` match for every operation in the transaction that requires it, then grant the `active authority` of said account. If no match is found, treat as if no authority was given Note: From d5e6f75ae9939a664b04393e7ca7acfe9bfd046e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 07:51:45 +0200 Subject: [PATCH 42/89] change dict to tuple --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index d33f5ca..7e21838 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -90,7 +90,7 @@ List of possible asserts are: | `lt, le, gt, ge` | `comparative` | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | -| `attribute_assert` | `attribute_to_assert` = [{`attribute_identifier`: `any assert_objects`}] | stateless | +| `attribute_assert` | `attribute_to_assert` = [(`attribute_identifier`, `any assert_objects`)] | stateless | There is no implicit type conversion when attempting to assert, incompatible type means assert failure. If required, a field can be added that stores the assumed type of the argument (if conversion fails, assert fails). If an argument has no asset, it is unrestricted and may be given (or not for optional arguments) with any value. From 15a051489460dcac2c97fbad1a5e578f36ddef38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 08:34:41 +0200 Subject: [PATCH 43/89] more details on attribute_assert and where permission is stored --- bsip-0040.md | 53 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 7e21838..4d9d459 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -49,7 +49,10 @@ All descriptions in this section are on a pseudo/prosa level and no recommendati A `custom_active_permission` looks like follows (in JSON-like/pseudo for clarification): ``` -custom_active_permission = list of custom_active_authority items +custom_active_permission = { + account_id, // account that is assigned to this permission + authorities = list of custom_active_authority items +} custom_active_authority = { valid_from, // timestamp when this is active, defaults to now valid_to, // timestamp when this is invalid, defaults to 1 year @@ -58,9 +61,7 @@ custom_active_authority = { asserts // see below } ``` -Note: This assumes `custom_active_permission` is stored within `account_object`. Actual implementation details left to the implementer, as long as every `custom_active_permission` can be assigned to exactly one account. - -#### Wording +Note: This assumes `custom_active_permission` is stored in a separate index. Actual implementation details left to the implementer, as long as every `custom_active_permission` can be assigned to exactly one account. A `custom active permission` contains a list of `custom active authority`. `Custom active authority` can match an operation of an incoming, signed transaction. The wording *matching* refers to: - `operationid` is equal to the id of the incoming operation @@ -71,10 +72,12 @@ A `custom active permission` contains a list of `custom active authority`. `Cust ### Asserts -The `asserts` is a list of `assert_objects` that are all together evaluated with `and` logic to evaluate a match +The `asserts` field is a list of restrictions consisting of argument to assert mappings. +An tuple of `(argument_identifier, assert_object[, logical_link])` is called a restriction on an argument. +All asserts within one restriction are evaluated per default with `and` logic, `or` logic can be put by specifying the `logical_link`. The `asserts` field is specified as follows: ``` -asserts = list of (argument_identifier, assert_object) tuples -argument_identifier = // target unknown, can be argument of operation, or in a nested dictionary like struct +asserts = list of (argument_identifier, [list of assert_object], logical_link) tuples +argument_identifier = // target variable, can be argument of operation, or attribute in case of nesting assert_object = { function, // functionid to do the assert data, // stores data specific to the chosen function @@ -90,11 +93,18 @@ List of possible asserts are: | `lt, le, gt, ge` | `comparative` | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | -| `attribute_assert` | `attribute_to_assert` = [(`attribute_identifier`, `any assert_objects`)] | stateless | +| `attribute_assert` | `attribute_to_assert` = [list of restrictions] | stateless | -There is no implicit type conversion when attempting to assert, incompatible type means assert failure. If required, a field can be added that stores the assumed type of the argument (if conversion fails, assert fails). If an argument has no asset, it is unrestricted and may be given (or not for optional arguments) with any value. +Following cases must hold for a restriction: +- if there is no value given (e.g. an optional argument, or nested value not given), the assert passes (no change, no violation) +- if the expected type of the argument does not match the given type (no implicit type conversion), assert fails +- if the assert fails, the restriction fails -In the following we list possible `asserts`. Mentioning `argument value` refers to the value of the argument of the operation specified `argument` in `assert_object`. The logic does not differentiate if an `argument` is optional or mandatory. All asserts imply: If the `argument` is given, it must pass the `assert`. If the `argument` is not given, assert is implicitly passed. +Note: +- If required a field can be added that stores the assumed type of the argument +- If arguments are given by the operation that have no restriction they can have any value + +In the following we list possible `assert_objects`. Mentioning `argument value` refers to the value of the argument of the operation specified by `argument_identifier` of a restriction. . All asserts imply: If the `argument` is given, it must pass the `assert`. If the `argument` is not given, assert is implicitly passed. #### `any` Stateless assert, all argument types. `Argument value` must be equal to one of values in the data list @@ -123,10 +133,10 @@ The assert that needs to pass is now `current_cumsum + incoming value <= max_cum Statefull assert, only `int` type arguments. Analogue to `limit`, but `interval_began` is initially set to `month(valid_from)` and set to `month(now)` on update, additionally the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). #### `attribute_assert` -Stateless assert, only for dictionary type objects. The `attribute_to_assert` list contains mappings between attributes and asserts that they must fulfill, if present in the dictionary. Allows nesting of `attribute_assert`. +Stateless assert, only for dictionary type objects. The `attribute_to_assert` list contains restrictions that all must assert positively. Allows nesting of `attribute_assert`. -Note: -- Assume `asset_update_operation`. All attributes of its `options` must be filled on update call. This assert can not be used to realize a "may only change attribute xzy of `options`". This would require that the logic knows which of the arguments are reflected on-chain and it knows how to query it for every operation that contains `options`. If `options` are to be restricted with this assert, all values that should not change would need be fixated by defining a `any` assert for those attributes, while having e.g. a `lt` assert for the one attribute that is allowed to change. +#### Example: Nested arguments like `options` +Assume `asset_update_operation`. All attributes of its `options` must be filled on update call. This assert can not be used to realize a "may only change attribute xzy of `options`". This would require that the logic knows which of the arguments are reflected on-chain and it knows how to query it for every operation that contains `options`. If `options` are to be restricted with this assert, all values that should not change would need be fixated by defining an `any` assert for those attributes, while having e.g. a `lt` assert for the one attribute that is allowed to change. #### Example: Simple transfer Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: @@ -152,12 +162,6 @@ That has the consquence now that a transfer transaction sending funds away from Note: This is just an illustration of a possible serialization, not a specification of the serialized format. -### Economics - -Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. -We propose that the transaction fee for the creation is tied to the duration of the custom active authority. -Furthermore, normal accounts can only create custom active authoritites with a duration of maximum 1 year. LTM can do any duration and also unlimited, but the transaction fee is capped at duration of 2 years. - ### Outline of handling incoming transactions When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: @@ -185,14 +189,21 @@ Since the required accounts is Account A, and the given accounts is also Account the transaction is executed. ### Modification to the backend -* Extend the account object to store custom active permission that includes a list of custom active authorities. Multiple custom active authority entries are possible for one operation +* Add a new index or extend the account object to store custom active permission are assigned to an account and contain a list of custom active authorities. Multiple custom active authority entries are possible for one operation * If the active authority of the account is updated, all custom active authorities need to be confirmed in the update. Every unconfirmed one is deleted otherwise -* Extend `account_update` or create a new operation to allow changing the custom active permission +* Provide operations: `install_custom_active_authority`, `update_custom_active_authority`, `delete_custom_active_authority` to allow changing the custom active permission (3 operation to allow custom transaction fees and avoid having to send the complete list of all authorities for every update) * Operation-specific authorities (if present) must be evaluated in incoming transactions * Additional committee parameters may be needed to limit the extend of usage of this feature Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion +### Economics + +Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: +- `install_custom_active_authority`: Tied to the duration of the custom active authority. +Normal accounts can only create custom active authoritites with a duration of maximum 1 year. LTM can do any duration and also unlimited, but the transaction fee is capped at duration of 2 years. +- `update_custom_active_authority` and `delete_custom_active_authority`: Similar to `account_update` + # Milestones We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: From d77a526aace1928bdfaf37e5cff730218edb5291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 08:38:30 +0200 Subject: [PATCH 44/89] consistent use of "list of" --- bsip-0040.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 4d9d459..0a313d1 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -76,7 +76,7 @@ The `asserts` field is a list of restrictions consisting of argument to assert m An tuple of `(argument_identifier, assert_object[, logical_link])` is called a restriction on an argument. All asserts within one restriction are evaluated per default with `and` logic, `or` logic can be put by specifying the `logical_link`. The `asserts` field is specified as follows: ``` -asserts = list of (argument_identifier, [list of assert_object], logical_link) tuples +asserts = list of (argument_identifier, list of assert_object, logical_link) tuples argument_identifier = // target variable, can be argument of operation, or attribute in case of nesting assert_object = { function, // functionid to do the assert @@ -93,7 +93,7 @@ List of possible asserts are: | `lt, le, gt, ge` | `comparative` | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | -| `attribute_assert` | `attribute_to_assert` = [list of restrictions] | stateless | +| `attribute_assert` | `attribute_to_assert` = list of restrictions | stateless | Following cases must hold for a restriction: - if there is no value given (e.g. an optional argument, or nested value not given), the assert passes (no change, no violation) From 6c7a90a097270402599c36ec5286a4992f99fe1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 08:54:41 +0200 Subject: [PATCH 45/89] Update bsip-0040.md --- bsip-0040.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 0a313d1..d99c14b 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -93,7 +93,7 @@ List of possible asserts are: | `lt, le, gt, ge` | `comparative` | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | -| `attribute_assert` | `attribute_to_assert` = list of restrictions | stateless | +| `attribute_assert` | list of restrictions | stateless | Following cases must hold for a restriction: - if there is no value given (e.g. an optional argument, or nested value not given), the assert passes (no change, no violation) @@ -189,6 +189,7 @@ Since the required accounts is Account A, and the given accounts is also Account the transaction is executed. ### Modification to the backend + * Add a new index or extend the account object to store custom active permission are assigned to an account and contain a list of custom active authorities. Multiple custom active authority entries are possible for one operation * If the active authority of the account is updated, all custom active authorities need to be confirmed in the update. Every unconfirmed one is deleted otherwise * Provide operations: `install_custom_active_authority`, `update_custom_active_authority`, `delete_custom_active_authority` to allow changing the custom active permission (3 operation to allow custom transaction fees and avoid having to send the complete list of all authorities for every update) @@ -205,6 +206,7 @@ Normal accounts can only create custom active authoritites with a duration of ma - `update_custom_active_authority` and `delete_custom_active_authority`: Similar to `account_update` # Milestones + We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: 1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` From 41a2403875ec03f1254fdaac5b7b10cd27db685a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 12:41:56 +0200 Subject: [PATCH 46/89] Update bsip-0040.md --- bsip-0040.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index d99c14b..df77d42 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -115,8 +115,7 @@ Stateless assert, all argument types. `Argument value` must NOT be equal to any #### `lt, le, gt, ge` Stateless assert. Allows explicit type converstion: - `int` type: use as is -- `string` type: user `length` as `argument value` -- `price` struct `{base = {amount, asset_id}, quote = {amount, asset_id}}`: convert to float price `argument value = base.amount/quote.amount` +- `string` type: use `length` of string as `argument value` The different asserts read as: - `lt`: `Argument value` must be less than `comparative` From cf72eaa2d7e3d53f40300070a036cfb3a0d3c41c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 14:39:45 +0200 Subject: [PATCH 47/89] add logical assert --- bsip-0040.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index df77d42..1db253d 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -73,17 +73,16 @@ A `custom active permission` contains a list of `custom active authority`. `Cust ### Asserts The `asserts` field is a list of restrictions consisting of argument to assert mappings. -An tuple of `(argument_identifier, assert_object[, logical_link])` is called a restriction on an argument. -All asserts within one restriction are evaluated per default with `and` logic, `or` logic can be put by specifying the `logical_link`. The `asserts` field is specified as follows: +A dictionary-type object like ``` -asserts = list of (argument_identifier, list of assert_object, logical_link) tuples -argument_identifier = // target variable, can be argument of operation, or attribute in case of nesting assert_object = { - function, // functionid to do the assert - data, // stores data specific to the chosen function - state // if this assert is statefull + function, // argument_identifier + argument, // constant value, or pointer to a dynamic value (argument of the operation, or attribute when nested) + data, // data specific to the function } ``` +is called a restriction. All asserts within one restriction are evaluated per default with `AND` logic. + List of possible asserts are: | function | data | state | @@ -94,6 +93,7 @@ List of possible asserts are: | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | | `attribute_assert` | list of restrictions | stateless | +| `logical` | list of restrictions | stateless | Following cases must hold for a restriction: - if there is no value given (e.g. an optional argument, or nested value not given), the assert passes (no change, no violation) @@ -134,6 +134,11 @@ Statefull assert, only `int` type arguments. Analogue to `limit`, but `interval_ #### `attribute_assert` Stateless assert, only for dictionary type objects. The `attribute_to_assert` list contains restrictions that all must assert positively. Allows nesting of `attribute_assert`. +#### `logical` +Stateless assert, only for dictionary type objects. The data is a list of restrictions, `argument` defines the logical link +- `OR`: If one of the restrictions in data asserts positively +- `AND`: If ALL restrictions in data assert positively + #### Example: Nested arguments like `options` Assume `asset_update_operation`. All attributes of its `options` must be filled on update call. This assert can not be used to realize a "may only change attribute xzy of `options`". This would require that the logic knows which of the arguments are reflected on-chain and it knows how to query it for every operation that contains `options`. If `options` are to be restricted with this assert, all values that should not change would need be fixated by defining an `any` assert for those attributes, while having e.g. a `lt` assert for the one attribute that is allowed to change. @@ -150,10 +155,11 @@ custom active authority = { account_auth: [] }, asserts: [ - (to, { + { function: any, + argument: to, data: [B] - }) // this restricts the argument identified with "to" + } // this restricts the argument identified with "to" ] } ``` From f0d16bb517af614f6f759bc8fee2841d81ee15e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 15:00:51 +0200 Subject: [PATCH 48/89] Update bsip-0040.md --- bsip-0040.md | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 1db253d..43562a9 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -39,7 +39,7 @@ The above list of named keys is nothing that is known to the backend as the back # Rational -Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `asserts` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of its required accounts. Check for every required account of the transaction if all its belonging operations have at least one positively matched `custom active authority` (match means its `authority` is granted through present signatures, same `operationid`, now is within `valid_to` and `valid_from` and all `asserts` pass), and if so grant the active authority of the corresponding account. +Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `restrictions` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of its required accounts. Check for every required account of the transaction if all its belonging operations have at least one positively matched `custom active authority` (match means its `authority` is granted through present signatures, same `operation_id`, now is within `valid_to` and `valid_from` and none of the `restrictions` is violated), and if so grant the active authority of the corresponding account. # Specification @@ -47,43 +47,43 @@ All descriptions in this section are on a pseudo/prosa level and no recommendati ### Custom active permission and custom active authority -A `custom_active_permission` looks like follows (in JSON-like/pseudo for clarification): +A `custom active permission` contains a list of `custom active authorities` and looks like follows (in JSON-like/pseudo for clarification): ``` custom_active_permission = { account_id, // account that is assigned to this permission - authorities = list of custom_active_authority items + authorities = list of custom_active_authority objects } custom_active_authority = { valid_from, // timestamp when this is active, defaults to now valid_to, // timestamp when this is invalid, defaults to 1 year - operationid, // operationid of the target operation, + operation_id, // operation id of the target operation, authority, // same as for the existing authortities (multisig with weighted accounts or keys), - asserts // see below + restrictions // see below } ``` Note: This assumes `custom_active_permission` is stored in a separate index. Actual implementation details left to the implementer, as long as every `custom_active_permission` can be assigned to exactly one account. -A `custom active permission` contains a list of `custom active authority`. `Custom active authority` can match an operation of an incoming, signed transaction. The wording *matching* refers to: -- `operationid` is equal to the id of the incoming operation -- assigned account of parent `custom active permission` is in the required accounts of the operation +A `custom active authority` is matched against operations of an incoming, signed transaction. The wording *matching* refers to: +- `operation_id` is equal to the id of the incoming operation +- `account_id` is in the required accounts of the operation - the `authority` of the `custom_active_authority` is given by the signatures of the transaction -- `now` is within `valid_to` and `valid_from` -- all `asserts` pass positively +- timestamp `now` is within `valid_to` and `valid_from` +- all `restrictions` assert positively -### Asserts +### Restrictions -The `asserts` field is a list of restrictions consisting of argument to assert mappings. +The `restrictions` field is a list of restrictions consisting of argument to assert mappings. A dictionary-type object like ``` -assert_object = { +restriction = { function, // argument_identifier argument, // constant value, or pointer to a dynamic value (argument of the operation, or attribute when nested) data, // data specific to the function } ``` -is called a restriction. All asserts within one restriction are evaluated per default with `AND` logic. +is called a restriction, that can assert itself positively (passed) or negatively (violated). All restrictions are evaluated per default with `AND` logic to determine if the whole list has asserted positively. -List of possible asserts are: +List of possible restrictions are: | function | data | state | | ------------- |:-------------:| -----:| @@ -96,15 +96,16 @@ List of possible asserts are: | `logical` | list of restrictions | stateless | Following cases must hold for a restriction: -- if there is no value given (e.g. an optional argument, or nested value not given), the assert passes (no change, no violation) -- if the expected type of the argument does not match the given type (no implicit type conversion), assert fails -- if the assert fails, the restriction fails +- if there is no value given (e.g. an optional argument, or nested value not given), the restrictions is passed (no change, no violation) +- if the expected type of the argument does not match the given type (no implicit type conversion), the restriction is violated +- if the function of the restriction asserts negatively, the restriction is violated Note: - If required a field can be added that stores the assumed type of the argument - If arguments are given by the operation that have no restriction they can have any value -In the following we list possible `assert_objects`. Mentioning `argument value` refers to the value of the argument of the operation specified by `argument_identifier` of a restriction. . All asserts imply: If the `argument` is given, it must pass the `assert`. If the `argument` is not given, assert is implicitly passed. +In the following we list possible `restriction`s. Mentioning `argument value` in the text below refers to the value of +the argument of the operation specified by `argument` of a restriction. #### `any` Stateless assert, all argument types. `Argument value` must be equal to one of values in the data list @@ -126,18 +127,18 @@ The different asserts read as: #### `limit` Statefull assert, only `int` type arguments. When the authority is created, `interval_began` is set to `valid_from` from its custom active authority and `max_cumsum` to `0`. Incoming operations are first tried to match all stateless asserts, and if all passes continue with statefull asserts. If `now > interval_began + interval_in_sec`, then set `max_cumsum = 0` and set `interval_began = now`. -The assert that needs to pass is now `current_cumsum + incoming value <= max_cumsum`. If all asserts are passed, update `current_cumsum = current_cumsum + incoming value` of all involved statefull asserts. +The assert that needs to pass is now `current_cumsum + incoming value <= max_cumsum`. If all `asserts` of this `custom_active_authority` pass, update `current_cumsum = current_cumsum + incoming value`. #### `limit_monthly` Statefull assert, only `int` type arguments. Analogue to `limit`, but `interval_began` is initially set to `month(valid_from)` and set to `month(now)` on update, additionally the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). #### `attribute_assert` -Stateless assert, only for dictionary type objects. The `attribute_to_assert` list contains restrictions that all must assert positively. Allows nesting of `attribute_assert`. +Stateless assert, only for dictionary type objects. The data list contains restrictions that all must pass, the reference for the `argument` of the child restriction is nested into the attributes of the parent dictionary type object. Allows nesting of `attribute_assert`. #### `logical` Stateless assert, only for dictionary type objects. The data is a list of restrictions, `argument` defines the logical link -- `OR`: If one of the restrictions in data asserts positively -- `AND`: If ALL restrictions in data assert positively +- `OR`: If one of the restrictions in data passes, this restriction passes +- `AND`: If ALL restrictions in data pass, this restriction passes #### Example: Nested arguments like `options` Assume `asset_update_operation`. All attributes of its `options` must be filled on update call. This assert can not be used to realize a "may only change attribute xzy of `options`". This would require that the logic knows which of the arguments are reflected on-chain and it knows how to query it for every operation that contains `options`. If `options` are to be restricted with this assert, all values that should not change would need be fixated by defining an `any` assert for those attributes, while having e.g. a `lt` assert for the one attribute that is allowed to change. @@ -148,7 +149,7 @@ Assume account A and B and some unrelated key K. Furthermore A has a custom acti custom active authority = { valid_from: 7.7.2018 00:00 valid_to: 8.7.2018 00:00 - operationid: transfer, + operation_id: transfer, authority: { threshold: 1 key_auth: [K, 1] @@ -215,7 +216,7 @@ Normal accounts can only create custom active authoritites with a duration of ma We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: 1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` -2. Evaluation of stateful asserts `limit` and `limit_monthly` in terms of performance. If positively evaluated, implement +2. Implement stateful asserts `limit` and `limit_monthly` and `logical` This approach allows as well to add other asserts at a later stage (with a new BSIP). From 63f6ddc6e3820f6ff73e809acdbb0f6b85314610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 15:18:43 +0200 Subject: [PATCH 49/89] Include either or example --- bsip-0040.md | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 43562a9..13ff0b2 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -102,7 +102,6 @@ Following cases must hold for a restriction: Note: - If required a field can be added that stores the assumed type of the argument -- If arguments are given by the operation that have no restriction they can have any value In the following we list possible `restriction`s. Mentioning `argument value` in the text below refers to the value of the argument of the operation specified by `argument` of a restriction. @@ -152,14 +151,14 @@ custom active authority = { operation_id: transfer, authority: { threshold: 1 - key_auth: [K, 1] + key_auth: [key K, 1] account_auth: [] }, - asserts: [ + restrictions: [ { function: any, argument: to, - data: [B] + data: [account B] } // this restricts the argument identified with "to" ] } @@ -168,6 +167,85 @@ That has the consquence now that a transfer transaction sending funds away from Note: This is just an illustration of a possible serialization, not a specification of the serialized format. +#### Example: Either or +Assume account A, B and C and asset X and asset Y. Furthermore A has a custom active authority in the following way: +``` +custom active authority = { + valid_from: 7.7.2018 00:00 + valid_to: 8.7.2018 00:00 + operation_id: transfer, + authority: { + threshold: 1 + key_auth: [] + account_auth: [account B, 1] + }, + restrictions: cut_out +} + +cut_out =[ + { + function: logical, + argument: OR, + data: [ either_list, or_list ] + } +] + +either_list = + [ + { + function: attribute_assert, + argument: amount, + data: [ + { + function: lt, + argument: amount, + data: 10000 + }, + { + function: any, + argument: asset_id, + data: [ asset X ] + } + ] + }, + { + function: any, + argument: to, + data: [ account C ] + } + ] + +or_list = + [ + { + function: attribute_assert, + argument: amount, + data: [ + { + function: le, + argument: amount, + data: 20000 + }, + { + function: any, + argument: asset_id, + data: [ asset Y ] + } + ] + }, + { + function: any, + argument: to, + data: [ account C ] + } + ] +``` +That has the consquence now that a transfer transaction sending funds away from A can be signed with with active authority of account B if +- it sends less than 10000 of asset X to account C +- it sends less than or equal to 20000 of asset Y to account C + +Note: This is just an illustration of a possible serialization, not a specification of the serialized format. + ### Outline of handling incoming transactions When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: From b7282a531f81a3aff216882334ae612556f14764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 15:21:09 +0200 Subject: [PATCH 50/89] fix formatting of new example --- bsip-0040.md | 72 ++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 13ff0b2..beb3b84 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -191,54 +191,54 @@ cut_out =[ ] either_list = - [ +[ + { + function: attribute_assert, + argument: amount, + data: [ { - function: attribute_assert, - argument: amount, - data: [ - { - function: lt, - argument: amount, - data: 10000 - }, - { - function: any, - argument: asset_id, - data: [ asset X ] - } - ] + function: lt, + argument: amount, + data: 10000 }, { - function: any, - argument: to, - data: [ account C ] + function: any, + argument: asset_id, + data: [ asset X ] } ] + }, + { + function: any, + argument: to, + data: [ account C ] + } +] or_list = - [ +[ + { + function: attribute_assert, + argument: amount, + data: [ { - function: attribute_assert, - argument: amount, - data: [ - { - function: le, - argument: amount, - data: 20000 - }, - { - function: any, - argument: asset_id, - data: [ asset Y ] - } - ] + function: le, + argument: amount, + data: 20000 }, { - function: any, - argument: to, - data: [ account C ] + function: any, + argument: asset_id, + data: [ asset Y ] } ] + }, + { + function: any, + argument: to, + data: [ account C ] + } +] ``` That has the consquence now that a transfer transaction sending funds away from A can be signed with with active authority of account B if - it sends less than 10000 of asset X to account C From 9b07069a8fcf5c7a926d93e71a3942bb253519b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 15:24:31 +0200 Subject: [PATCH 51/89] include milestone differentation --- bsip-0040.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index beb3b84..9075c52 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -37,6 +37,8 @@ With this BSIP any user can create keys with specific purpose (everything else i The above list of named keys is nothing that is known to the backend as the backend should have an abstract implementation. The UI could provide a button "Create Trading Key" that properly configures the respective custom active permission entry. +This BSIP will be split into two parts that will be voted on serparately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 give finer control of how to combine restrictions and will also allow statefull restrictions (e.g. allow market orders up to some amount for every month). + # Rational Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `restrictions` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of its required accounts. Check for every required account of the transaction if all its belonging operations have at least one positively matched `custom active authority` (match means its `authority` is granted through present signatures, same `operation_id`, now is within `valid_to` and `valid_from` and none of the `restrictions` is violated), and if so grant the active authority of the corresponding account. @@ -182,7 +184,7 @@ custom active authority = { restrictions: cut_out } -cut_out =[ +cut_out = [ { function: logical, argument: OR, @@ -244,7 +246,9 @@ That has the consquence now that a transfer transaction sending funds away from - it sends less than 10000 of asset X to account C - it sends less than or equal to 20000 of asset Y to account C -Note: This is just an illustration of a possible serialization, not a specification of the serialized format. +Note: +- This is just an illustration of a possible serialization, not a specification of the serialized format. +- This is not included in the first Milestone ### Outline of handling incoming transactions From 12355d607a3109b85a66adab9069edd433d5508d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 15:29:19 +0200 Subject: [PATCH 52/89] clarify milestone procedure --- bsip-0040.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 9075c52..df75900 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -37,7 +37,7 @@ With this BSIP any user can create keys with specific purpose (everything else i The above list of named keys is nothing that is known to the backend as the backend should have an abstract implementation. The UI could provide a button "Create Trading Key" that properly configures the respective custom active permission entry. -This BSIP will be split into two parts that will be voted on serparately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 give finer control of how to combine restrictions and will also allow statefull restrictions (e.g. allow market orders up to some amount for every month). +This BSIP will be split into two parts that will be voted on serparately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows statefull restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions. Milestone 2 and 3 will be put up for voting if Milestone 1 proves successful. # Rational @@ -95,7 +95,7 @@ List of possible restrictions are: | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | | `attribute_assert` | list of restrictions | stateless | -| `logical` | list of restrictions | stateless | +| `logical` | list of restrictions lists | stateless | Following cases must hold for a restriction: - if there is no value given (e.g. an optional argument, or nested value not given), the restrictions is passed (no change, no violation) @@ -136,10 +136,9 @@ Statefull assert, only `int` type arguments. Analogue to `limit`, but `interval_ #### `attribute_assert` Stateless assert, only for dictionary type objects. The data list contains restrictions that all must pass, the reference for the `argument` of the child restriction is nested into the attributes of the parent dictionary type object. Allows nesting of `attribute_assert`. -#### `logical` -Stateless assert, only for dictionary type objects. The data is a list of restrictions, `argument` defines the logical link -- `OR`: If one of the restrictions in data passes, this restriction passes -- `AND`: If ALL restrictions in data pass, this restriction passes +#### `logical_or` +Stateless assert, only for dictionary type objects. The data is a list of restrictions lists, i.e. +`data = [ [restriction 1, restriction 2], [restriction 3, restriction 4], ... ]`. If one of the restrictions sub-lists in data passes as whole, this restriction passes. #### Example: Nested arguments like `options` Assume `asset_update_operation`. All attributes of its `options` must be filled on update call. This assert can not be used to realize a "may only change attribute xzy of `options`". This would require that the logic knows which of the arguments are reflected on-chain and it knows how to query it for every operation that contains `options`. If `options` are to be restricted with this assert, all values that should not change would need be fixated by defining an `any` assert for those attributes, while having e.g. a `lt` assert for the one attribute that is allowed to change. @@ -186,8 +185,7 @@ custom active authority = { cut_out = [ { - function: logical, - argument: OR, + function: logical_or, data: [ either_list, or_list ] } ] @@ -298,7 +296,8 @@ Normal accounts can only create custom active authoritites with a duration of ma We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: 1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` -2. Implement stateful asserts `limit` and `limit_monthly` and `logical` +2. Implement stateful asserts `limit` and `limit_monthly` +3. Implement `logical_or` This approach allows as well to add other asserts at a later stage (with a new BSIP). From 2222ceab619dc4df3324ad16a16e24afa85bf2e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 15:35:12 +0200 Subject: [PATCH 53/89] moved examples out of specifications --- bsip-0040.md | 109 +++++++++++++++++++++++++++------------------------ 1 file changed, 57 insertions(+), 52 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index df75900..972387c 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -140,11 +140,59 @@ Stateless assert, only for dictionary type objects. The data list contains restr Stateless assert, only for dictionary type objects. The data is a list of restrictions lists, i.e. `data = [ [restriction 1, restriction 2], [restriction 3, restriction 4], ... ]`. If one of the restrictions sub-lists in data passes as whole, this restriction passes. +### Outline of handling incoming transactions + +When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: +- iterate over required accounts and for each account, iterate over all operations within the transactions that require the active authority of this account +- iterate the `custom_active_authorities` of said account +- if a `custom_active_authority` is found that matches , remember that and stop iterating the authorities and continue until all operations are checked +- if the account has a `custom active authority` match for every operation in the transaction that requires it, then grant the `active authority` of said account. If no match is found, treat as if no authority was given + +Note: +- A `custom_active_authority` can only grant the `active authority` of the corresponding account, nothing more + +### Modification to the backend + +* Add a new index or extend the account object to store custom active permission are assigned to an account and contain a list of custom active authorities. Multiple custom active authority entries are possible for one operation +* If the active authority of the account is updated, all custom active authorities need to be confirmed in the update. Every unconfirmed one is deleted otherwise +* Provide operations: `install_custom_active_authority`, `update_custom_active_authority`, `delete_custom_active_authority` to allow changing the custom active permission (3 operation to allow custom transaction fees and avoid having to send the complete list of all authorities for every update) +* Operation-specific authorities (if present) must be evaluated in incoming transactions +* Additional committee parameters may be needed to limit the extend of usage of this feature + +Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion + +### Economics + +Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: +- `install_custom_active_authority`: Tied to the duration of the custom active authority. +Normal accounts can only create custom active authoritites with a duration of maximum 1 year. LTM can do any duration and also unlimited, but the transaction fee is capped at duration of 2 years. +- `update_custom_active_authority` and `delete_custom_active_authority`: Similar to `account_update` + +# Milestones + +We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: + +1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` +2. Implement stateful asserts `limit` and `limit_monthly` +3. Implement `logical_or` + +This approach allows as well to add other asserts at a later stage (with a new BSIP). + +# Discussion + +To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/1061) and [pull request](https://github.com/bitshares/bsips/pull/86). + +# Examples + +These examples are for illustration and no specification of actual serialization. + + #### Example: Nested arguments like `options` Assume `asset_update_operation`. All attributes of its `options` must be filled on update call. This assert can not be used to realize a "may only change attribute xzy of `options`". This would require that the logic knows which of the arguments are reflected on-chain and it knows how to query it for every operation that contains `options`. If `options` are to be restricted with this assert, all values that should not change would need be fixated by defining an `any` assert for those attributes, while having e.g. a `lt` assert for the one attribute that is allowed to change. #### Example: Simple transfer -Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way: +Assume account A and B and some unrelated key K. +The custom active authority should be put that transfer transaction sending funds away from A can be signed with key K as long as the receiver is B. More concrete, the authority would look like ``` custom active authority = { valid_from: 7.7.2018 00:00 @@ -164,12 +212,16 @@ custom active authority = { ] } ``` -That has the consquence now that a transfer transaction sending funds away from A can be signed with key K as long as the receiver is B. +Note: This is included with the first Milestone -Note: This is just an illustration of a possible serialization, not a specification of the serialized format. #### Example: Either or -Assume account A, B and C and asset X and asset Y. Furthermore A has a custom active authority in the following way: +Assume account A, B and C and asset X and asset Y. The custom active authority should now achieve + that a transfer transaction sending funds away from A can be signed with with active authority of account B if +- it sends less than 10000 of asset X to account C +- it sends less than or equal to 20000 of asset Y to account C + +More concrete, the authority would look like ``` custom active authority = { valid_from: 7.7.2018 00:00 @@ -240,24 +292,8 @@ or_list = } ] ``` -That has the consquence now that a transfer transaction sending funds away from A can be signed with with active authority of account B if -- it sends less than 10000 of asset X to account C -- it sends less than or equal to 20000 of asset Y to account C +Note: This is included with the third Milestone -Note: -- This is just an illustration of a possible serialization, not a specification of the serialized format. -- This is not included in the first Milestone - -### Outline of handling incoming transactions - -When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: -- iterate over required accounts and for each account, iterate over all operations within the transactions that require the active authority of this account -- iterate the `custom_active_authorities` of said account -- if a `custom_active_authority` is found that matches , remember that and stop iterating the authorities and continue until all operations are checked -- if the account has a `custom active authority` match for every operation in the transaction that requires it, then grant the `active authority` of said account. If no match is found, treat as if no authority was given - -Note: -- A `custom_active_authority` can only grant the `active authority` of the corresponding account, nothing more #### Example: Checking for custom active authorities @@ -274,37 +310,6 @@ Acive authority of Account A is granted and normal authority checks are continue Since the required accounts is Account A, and the given accounts is also Account A through `custom active authority 2`, the transaction is executed. -### Modification to the backend - -* Add a new index or extend the account object to store custom active permission are assigned to an account and contain a list of custom active authorities. Multiple custom active authority entries are possible for one operation -* If the active authority of the account is updated, all custom active authorities need to be confirmed in the update. Every unconfirmed one is deleted otherwise -* Provide operations: `install_custom_active_authority`, `update_custom_active_authority`, `delete_custom_active_authority` to allow changing the custom active permission (3 operation to allow custom transaction fees and avoid having to send the complete list of all authorities for every update) -* Operation-specific authorities (if present) must be evaluated in incoming transactions -* Additional committee parameters may be needed to limit the extend of usage of this feature - -Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion - -### Economics - -Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: -- `install_custom_active_authority`: Tied to the duration of the custom active authority. -Normal accounts can only create custom active authoritites with a duration of maximum 1 year. LTM can do any duration and also unlimited, but the transaction fee is capped at duration of 2 years. -- `update_custom_active_authority` and `delete_custom_active_authority`: Similar to `account_update` - -# Milestones - -We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: - -1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` -2. Implement stateful asserts `limit` and `limit_monthly` -3. Implement `logical_or` - -This approach allows as well to add other asserts at a later stage (with a new BSIP). - -# Discussion - -To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/1061) and [pull request](https://github.com/bitshares/bsips/pull/86). - # Summary for Shareholders Bad publicity in terms of security can have very negative effect on the BTS value. This BSIP allows that traders can e.g. use a trading key, witnesses can use their witness key and a faucet can use a faucet key. If then for some reason the key or witness/faucet server becomes compromised, such a key can do little harm to the account holders, minimizing the risk. From b1864f8a8a56c17f234768a4179ba5c9448894bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 15:38:47 +0200 Subject: [PATCH 54/89] moving around --- bsip-0040.md | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 972387c..c734a61 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -151,6 +151,13 @@ When a signed transaction arrives and before the backend evaluates if all necess Note: - A `custom_active_authority` can only grant the `active authority` of the corresponding account, nothing more +### Economics + +Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: +- `install_custom_active_authority`: Tied to the duration of the custom active authority. +Normal accounts can only create custom active authoritites with a duration of maximum 1 year. LTM can do any duration and also unlimited, but the transaction fee is capped at duration of 2 years. +- `update_custom_active_authority` and `delete_custom_active_authority`: Similar to `account_update` + ### Modification to the backend * Add a new index or extend the account object to store custom active permission are assigned to an account and contain a list of custom active authorities. Multiple custom active authority entries are possible for one operation @@ -161,23 +168,6 @@ Note: Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion -### Economics - -Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: -- `install_custom_active_authority`: Tied to the duration of the custom active authority. -Normal accounts can only create custom active authoritites with a duration of maximum 1 year. LTM can do any duration and also unlimited, but the transaction fee is capped at duration of 2 years. -- `update_custom_active_authority` and `delete_custom_active_authority`: Similar to `account_update` - -# Milestones - -We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: - -1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` -2. Implement stateful asserts `limit` and `limit_monthly` -3. Implement `logical_or` - -This approach allows as well to add other asserts at a later stage (with a new BSIP). - # Discussion To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/1061) and [pull request](https://github.com/bitshares/bsips/pull/86). @@ -310,6 +300,17 @@ Acive authority of Account A is granted and normal authority checks are continue Since the required accounts is Account A, and the given accounts is also Account A through `custom active authority 2`, the transaction is executed. +# Milestones + +We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: + +1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` +2. Implement stateful asserts `limit` and `limit_monthly` +3. Implement `logical_or` + +This approach allows as well to add other asserts at a later stage (with a new BSIP). + + # Summary for Shareholders Bad publicity in terms of security can have very negative effect on the BTS value. This BSIP allows that traders can e.g. use a trading key, witnesses can use their witness key and a faucet can use a faucet key. If then for some reason the key or witness/faucet server becomes compromised, such a key can do little harm to the account holders, minimizing the risk. From 03f24f0fb36f0ca144d0a77a7b938266bc2b5c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 30 Jul 2018 16:16:18 +0200 Subject: [PATCH 55/89] more cleaning up --- bsip-0040.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index c734a61..7b9fa6d 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -79,7 +79,7 @@ A dictionary-type object like ``` restriction = { function, // argument_identifier - argument, // constant value, or pointer to a dynamic value (argument of the operation, or attribute when nested) + argument, // pointer to a dynamic value (argument of the operation, or attribute when nested) data, // data specific to the function } ``` @@ -95,7 +95,7 @@ List of possible restrictions are: | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | | `attribute_assert` | list of restrictions | stateless | -| `logical` | list of restrictions lists | stateless | +| `logical_or` | list of restrictions lists | stateless | Following cases must hold for a restriction: - if there is no value given (e.g. an optional argument, or nested value not given), the restrictions is passed (no change, no violation) @@ -138,7 +138,7 @@ Stateless assert, only for dictionary type objects. The data list contains restr #### `logical_or` Stateless assert, only for dictionary type objects. The data is a list of restrictions lists, i.e. -`data = [ [restriction 1, restriction 2], [restriction 3, restriction 4], ... ]`. If one of the restrictions sub-lists in data passes as whole, this restriction passes. +`data = [ [restriction 1, restriction 2], [restriction 3, restriction 4], ... ]`. If one of the restrictions sub-lists in data passes as whole, this restriction passes. In above miniexample that would mean if `restriction 1` and `restriction 2` pass, the whole `logical_or` restriction is considered to be passed as well. ### Outline of handling incoming transactions @@ -156,7 +156,8 @@ Note: Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: - `install_custom_active_authority`: Tied to the duration of the custom active authority. Normal accounts can only create custom active authoritites with a duration of maximum 1 year. LTM can do any duration and also unlimited, but the transaction fee is capped at duration of 2 years. -- `update_custom_active_authority` and `delete_custom_active_authority`: Similar to `account_update` +- `update_custom_active_authority`: Base fee similar to `account_update` plus dynamic one for any duration changes +- `delete_custom_active_authority`: Cheap similar to `limit_order_cancel` ### Modification to the backend @@ -222,16 +223,14 @@ custom active authority = { key_auth: [] account_auth: [account B, 1] }, - restrictions: cut_out + restrictions: [ + { + function: logical_or, + data: [ either_list, or_list ] + } + ] } -cut_out = [ - { - function: logical_or, - data: [ either_list, or_list ] - } -] - either_list = [ { From 8dce3724c530deb6deb84debfc523883f8f90c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Thu, 2 Aug 2018 16:37:31 +0200 Subject: [PATCH 56/89] change typos --- bsip-0040.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 7b9fa6d..45c456c 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -37,7 +37,7 @@ With this BSIP any user can create keys with specific purpose (everything else i The above list of named keys is nothing that is known to the backend as the backend should have an abstract implementation. The UI could provide a button "Create Trading Key" that properly configures the respective custom active permission entry. -This BSIP will be split into two parts that will be voted on serparately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows statefull restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions. Milestone 2 and 3 will be put up for voting if Milestone 1 proves successful. +This BSIP will be split into two parts that will be voted on separately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows stateful restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions. Milestone 2 and 3 will be put up for voting if Milestone 1 proves successful. # Rational @@ -56,10 +56,10 @@ custom_active_permission = { authorities = list of custom_active_authority objects } custom_active_authority = { - valid_from, // timestamp when this is active, defaults to now - valid_to, // timestamp when this is invalid, defaults to 1 year + valid_from, // timestamp when this is active + valid_to, // timestamp when this is invalid operation_id, // operation id of the target operation, - authority, // same as for the existing authortities (multisig with weighted accounts or keys), + authority, // same as for the existing authotities (multisig with weighted accounts or keys), restrictions // see below } ``` @@ -98,7 +98,7 @@ List of possible restrictions are: | `logical_or` | list of restrictions lists | stateless | Following cases must hold for a restriction: -- if there is no value given (e.g. an optional argument, or nested value not given), the restrictions is passed (no change, no violation) +- if there is no value given (e.g. an optional argument, or nested value not given), the restrictions is passed (even if the underlying operation understands the absence of a key as instructions to delete it on-chain, see bitshares/bitshares-core#838) - if the expected type of the argument does not match the given type (no implicit type conversion), the restriction is violated - if the function of the restriction asserts negatively, the restriction is violated @@ -115,7 +115,7 @@ Stateless assert, all argument types. `Argument value` must be equal to one of v Stateless assert, all argument types. `Argument value` must NOT be equal to any of the values in the list. #### `lt, le, gt, ge` -Stateless assert. Allows explicit type converstion: +Stateless assert. Allows explicit type conversion: - `int` type: use as is - `string` type: use `length` of string as `argument value` @@ -126,12 +126,12 @@ The different asserts read as: - `ge`: `Argument value` must be greater than or equal to `comparative` #### `limit` -Statefull assert, only `int` type arguments. When the authority is created, `interval_began` is set to `valid_from` from its custom active authority and `max_cumsum` to `0`. Incoming operations are first tried to match all stateless asserts, -and if all passes continue with statefull asserts. If `now > interval_began + interval_in_sec`, then set `max_cumsum = 0` and set `interval_began = now`. +Stateful assert, only `int` type arguments. When the authority is created, `interval_began` is set to `valid_from` from its custom active authority and `max_cumsum` to `0`. Incoming operations are first tried to match all stateless asserts, +and if all passes continue with stateful asserts. If `now > interval_began + interval_in_sec`, then set `max_cumsum = 0` and set `interval_began = now`. The assert that needs to pass is now `current_cumsum + incoming value <= max_cumsum`. If all `asserts` of this `custom_active_authority` pass, update `current_cumsum = current_cumsum + incoming value`. #### `limit_monthly` -Statefull assert, only `int` type arguments. Analogue to `limit`, but `interval_began` is initially set to `month(valid_from)` and set to `month(now)` on update, additionally the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). +Stateful assert, only `int` type arguments. Analogue to `limit`, but `interval_began` is initially set to `month(valid_from)` and set to `month(now)` on update, additionally the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). #### `attribute_assert` Stateless assert, only for dictionary type objects. The data list contains restrictions that all must pass, the reference for the `argument` of the child restriction is nested into the attributes of the parent dictionary type object. Allows nesting of `attribute_assert`. From 34d0086b63a31318e84c8aaee45dd13c2650aa8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Thu, 2 Aug 2018 16:41:11 +0200 Subject: [PATCH 57/89] clarify month call --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 45c456c..7e7347f 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -131,7 +131,7 @@ and if all passes continue with stateful asserts. If `now > interval_began + int The assert that needs to pass is now `current_cumsum + incoming value <= max_cumsum`. If all `asserts` of this `custom_active_authority` pass, update `current_cumsum = current_cumsum + incoming value`. #### `limit_monthly` -Stateful assert, only `int` type arguments. Analogue to `limit`, but `interval_began` is initially set to `month(valid_from)` and set to `month(now)` on update, additionally the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). +Stateful assert, only `int` type arguments. Analogue to `limit`, but `interval_began` is initially set to `month(valid_from)` and set to `month(now)` on update, additionally the time assert is `month(now) >= interval_began + interval_in_months` (include logic for month overflow when year changes). The `month(now)` call assumes zulu time to calculate month number. #### `attribute_assert` Stateless assert, only for dictionary type objects. The data list contains restrictions that all must pass, the reference for the `argument` of the child restriction is nested into the attributes of the parent dictionary type object. Allows nesting of `attribute_assert`. From 651e00c5eb533f380284d7d3ea53b064f9702314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Thu, 2 Aug 2018 16:48:58 +0200 Subject: [PATCH 58/89] Update bsip-0040.md --- bsip-0040.md | 1 + 1 file changed, 1 insertion(+) diff --git a/bsip-0040.md b/bsip-0040.md index 7e7347f..17b81a7 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -165,6 +165,7 @@ Normal accounts can only create custom active authoritites with a duration of ma * If the active authority of the account is updated, all custom active authorities need to be confirmed in the update. Every unconfirmed one is deleted otherwise * Provide operations: `install_custom_active_authority`, `update_custom_active_authority`, `delete_custom_active_authority` to allow changing the custom active permission (3 operation to allow custom transaction fees and avoid having to send the complete list of all authorities for every update) * Operation-specific authorities (if present) must be evaluated in incoming transactions +* Remove expired custom_active_authorities on maintenance * Additional committee parameters may be needed to limit the extend of usage of this feature Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion From 8893727844982aa81dfd201c025a5faf99b2aba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Thu, 2 Aug 2018 16:50:23 +0200 Subject: [PATCH 59/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 17b81a7..8b6c03e 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -37,7 +37,7 @@ With this BSIP any user can create keys with specific purpose (everything else i The above list of named keys is nothing that is known to the backend as the backend should have an abstract implementation. The UI could provide a button "Create Trading Key" that properly configures the respective custom active permission entry. -This BSIP will be split into two parts that will be voted on separately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows stateful restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions. Milestone 2 and 3 will be put up for voting if Milestone 1 proves successful. +This BSIP will be split into three parts that will be voted on separately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows stateful restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions. Milestone 2 and 3 will be put up for voting if Milestone 1 proves successful. # Rational From 5d92967586dcf744f225332925ce74b4a6ee07e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Thu, 2 Aug 2018 21:55:41 +0200 Subject: [PATCH 60/89] add enabled flag --- bsip-0040.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 8b6c03e..8ae06e6 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -26,7 +26,7 @@ Any successfull hacking or phishing attempt on any of the web wallets that are p BitShares Blockchain is bad publicity. The user needs to be educated in account security, and this BSIP aims to ensure all technical possibilities are met while being flexible to allow many use-cases. -With this BSIP any user can create keys with specific purpose (everything else is prohibited). We list some possibilities below: +With this BSIP any user can create additional keys with specific purpose (everything else is prohibited). We list some possibilities below: - Witness Key: Only allows update signing key and publish price feed - Trading Key: Only allows limit orders (arguments restricted to desired markets), update margin position and transfers (arguments restricted to certain accounts) - Proposal Update Key: Approve proposals (2FA comes to mind) @@ -37,11 +37,13 @@ With this BSIP any user can create keys with specific purpose (everything else i The above list of named keys is nothing that is known to the backend as the backend should have an abstract implementation. The UI could provide a button "Create Trading Key" that properly configures the respective custom active permission entry. +Note: The user can still use the active authority just like used to, no change in existing behavior. The named keys only give an additional possibility. For example: The user can login the UI using the private key of such a named key. Then he only as access to the operations that this named key grants. He can still login with the existing password to gain full access (similar a local wallet can be created that only contains the named key). + This BSIP will be split into three parts that will be voted on separately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows stateful restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions. Milestone 2 and 3 will be put up for voting if Milestone 1 proves successful. # Rational -Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `restrictions` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of its required accounts. Check for every required account of the transaction if all its belonging operations have at least one positively matched `custom active authority` (match means its `authority` is granted through present signatures, same `operation_id`, now is within `valid_to` and `valid_from` and none of the `restrictions` is violated), and if so grant the active authority of the corresponding account. +Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `restrictions` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of its required accounts. Check for every required account of the transaction if all its belonging operations have at least one positively matched `custom active authority` (match means its `authority` is granted through present signatures, same `operation_id`, now is within `valid_to` and `valid_from` and none of the `restrictions` is violated), and if so grant the active authority of the corresponding account. # Specification @@ -56,6 +58,7 @@ custom_active_permission = { authorities = list of custom_active_authority objects } custom_active_authority = { + enabled, // status of this authority, true or false. true when created valid_from, // timestamp when this is active valid_to, // timestamp when this is invalid operation_id, // operation id of the target operation, @@ -162,7 +165,7 @@ Normal accounts can only create custom active authoritites with a duration of ma ### Modification to the backend * Add a new index or extend the account object to store custom active permission are assigned to an account and contain a list of custom active authorities. Multiple custom active authority entries are possible for one operation -* If the active authority of the account is updated, all custom active authorities need to be confirmed in the update. Every unconfirmed one is deleted otherwise +* If the active authority of the account is updated, all custom active authorities are disabled and must be enabled again with using `update_custom_active_authority` * Provide operations: `install_custom_active_authority`, `update_custom_active_authority`, `delete_custom_active_authority` to allow changing the custom active permission (3 operation to allow custom transaction fees and avoid having to send the complete list of all authorities for every update) * Operation-specific authorities (if present) must be evaluated in incoming transactions * Remove expired custom_active_authorities on maintenance From b8f269187ee375d043bbf20167c1edcc0fdcc892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 3 Aug 2018 07:58:30 +0200 Subject: [PATCH 61/89] include new comments --- bsip-0040.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 8ae06e6..8c2e5b8 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -101,8 +101,9 @@ List of possible restrictions are: | `logical_or` | list of restrictions lists | stateless | Following cases must hold for a restriction: +- when the `custom_active_authority` is installed, the basic argument types (without nesting) are checked, and installing denying if not matching - if there is no value given (e.g. an optional argument, or nested value not given), the restrictions is passed (even if the underlying operation understands the absence of a key as instructions to delete it on-chain, see bitshares/bitshares-core#838) -- if the expected type of the argument does not match the given type (no implicit type conversion), the restriction is violated +- if the expected type of the argument does not match the given type (no implicit type conversion), the restriction is violated (needed for nested `attribute_assert`) - if the function of the restriction asserts negatively, the restriction is violated Note: @@ -157,18 +158,21 @@ Note: ### Economics Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: -- `install_custom_active_authority`: Tied to the duration of the custom active authority. -Normal accounts can only create custom active authoritites with a duration of maximum 1 year. LTM can do any duration and also unlimited, but the transaction fee is capped at duration of 2 years. +- `install_custom_active_authority`: Normal accounts can only create custom active authoritites with a duration of maximum 1 year, LTM can do any duration. Two options come to mind: + - A fixed high fee independent of authorities content + - Tied to the duration and complexity of the custom active authority. Transaction fee is then `fee = flat_fee + basic_fee * duration` where `basic_fee` is calculated according to complexity (e.g. size of authority, number of restrictions and etc.). Fee is capped at 1 year for LTM. - `update_custom_active_authority`: Base fee similar to `account_update` plus dynamic one for any duration changes - `delete_custom_active_authority`: Cheap similar to `limit_order_cancel` ### Modification to the backend * Add a new index or extend the account object to store custom active permission are assigned to an account and contain a list of custom active authorities. Multiple custom active authority entries are possible for one operation -* If the active authority of the account is updated, all custom active authorities are disabled and must be enabled again with using `update_custom_active_authority` * Provide operations: `install_custom_active_authority`, `update_custom_active_authority`, `delete_custom_active_authority` to allow changing the custom active permission (3 operation to allow custom transaction fees and avoid having to send the complete list of all authorities for every update) +* If the active authority of the account is updated, all custom active authorities are disabled and must be manually specified / re-enabled. User can either + 1. keep the authorities enabled by specifying them in a list of `custom_active_authorities` in `extensions` of `account_update_operation` + 2. enable them again afterwards by using `update_custom_active_authority` * Operation-specific authorities (if present) must be evaluated in incoming transactions -* Remove expired custom_active_authorities on maintenance +* Remove expired custom_active_authorities on maintenance if they are expired for longer than one month * Additional committee parameters may be needed to limit the extend of usage of this feature Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion From 871b93dfe64176c6be6b0faec1c0e751eeaf8509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 3 Aug 2018 08:10:17 +0200 Subject: [PATCH 62/89] more detail for Example: Simple transfer --- bsip-0040.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 8c2e5b8..c1ac3ff 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -191,7 +191,7 @@ Assume `asset_update_operation`. All attributes of its `options` must be filled #### Example: Simple transfer Assume account A and B and some unrelated key K. -The custom active authority should be put that transfer transaction sending funds away from A can be signed with key K as long as the receiver is B. More concrete, the authority would look like +The custom active authority should be put such that a transfer transaction sending funds away from A can be signed with key K, as long as the receiver is B. More concrete, the authority would look like ``` custom active authority = { valid_from: 7.7.2018 00:00 @@ -211,7 +211,17 @@ custom active authority = { ] } ``` -Note: This is included with the first Milestone +Exemplatory outcomes: +- Transfer asset X with amount Y from account A to account B, signed with Key K: Accepted +- Transfer asset X with amount Y from account B to account A, signed with Key K: Denied +- Transfer asset X with amount Y from account A to account C, signed with Key K: Denied +- Transfer asset X with amount Y from account A to account B, signed with active authority of B: Denied +- Transfer asset X with amount Y from account A to account B, signed with active authority of A: Accepted +- Create a proposal that includes operation 'transfer asset X with amount Y from account A to account B', signed with Key K: Denied + +Note: +- This is included with the first Milestone +- Normal permission logic is not altered. Account A can still sign the a transfer from account A to account B with its active authority #### Example: Either or From d036c8cf7238d6c40f09b547193d02458ce4c3ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 3 Aug 2018 08:11:08 +0200 Subject: [PATCH 63/89] calrify child operations of proposals --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index c1ac3ff..d001c33 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -147,7 +147,7 @@ Stateless assert, only for dictionary type objects. The data is a list of restri ### Outline of handling incoming transactions When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: -- iterate over required accounts and for each account, iterate over all operations within the transactions that require the active authority of this account +- iterate over required accounts and for each account, iterate over all operations (child operations of proposal are not iterated, only the proposal) within the transactions that require the active authority of this account - iterate the `custom_active_authorities` of said account - if a `custom_active_authority` is found that matches , remember that and stop iterating the authorities and continue until all operations are checked - if the account has a `custom active authority` match for every operation in the transaction that requires it, then grant the `active authority` of said account. If no match is found, treat as if no authority was given From ecf22d4735aae61f48ba9ef1e0c3333d453c10ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 3 Aug 2018 08:14:16 +0200 Subject: [PATCH 64/89] add reviewers --- bsip-0040.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index d001c33..e0d5355 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -1,9 +1,12 @@ BSIP: 0040 Title: Custom active permissions Authors: + Stefan Schießl + Reviewers: Alex Megalokonomos Fabian Schuh - Stefan Schießl + Abit + Peter Conrad Status: Draft Type: Protocol Created: 2018-07-25 From 7d1468e0164dd0919cfa2438ffffdd681bd01e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 3 Aug 2018 08:25:35 +0200 Subject: [PATCH 65/89] updated Outline of handling incoming transactions --- bsip-0040.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index e0d5355..f7e2744 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -150,13 +150,15 @@ Stateless assert, only for dictionary type objects. The data is a list of restri ### Outline of handling incoming transactions When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: -- iterate over required accounts and for each account, iterate over all operations (child operations of proposal are not iterated, only the proposal) within the transactions that require the active authority of this account -- iterate the `custom_active_authorities` of said account -- if a `custom_active_authority` is found that matches , remember that and stop iterating the authorities and continue until all operations are checked -- if the account has a `custom active authority` match for every operation in the transaction that requires it, then grant the `active authority` of said account. If no match is found, treat as if no authority was given +- iterate over `required accounts` + - iterate over all `operations` (child operations of proposal are not iterated, only the proposal) within the transactions that require the active authority of this account + - iterate the `custom_active_authorities` of this account, and if it matches, remember that and continue with next `operation` + - if a `custom active authority` match was found for every operation in the loop, grant the `active authority` of this account Note: - A `custom_active_authority` can only grant the `active authority` of the corresponding account, nothing more +- The actual active authority of a required account can still be given as before, existing behavior is not to be changed +- This for illustration, not actual implementation instructions ### Economics From d9466f2ac47fcbe2e88917b39107a25deb04e2fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 3 Aug 2018 08:26:15 +0200 Subject: [PATCH 66/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index f7e2744..0a848e1 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -151,7 +151,7 @@ Stateless assert, only for dictionary type objects. The data is a list of restri When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following: - iterate over `required accounts` - - iterate over all `operations` (child operations of proposal are not iterated, only the proposal) within the transactions that require the active authority of this account + - iterate over all `operations` (child operations of proposal are not included) within the transactions that require the active authority of this account - iterate the `custom_active_authorities` of this account, and if it matches, remember that and continue with next `operation` - if a `custom active authority` match was found for every operation in the loop, grant the `active authority` of this account From 5ddc6cddf56aa7595220090a0f9ec3bddd3a65b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 5 Aug 2018 17:39:39 +0200 Subject: [PATCH 67/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 0a848e1..e074e2b 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -2,7 +2,7 @@ Title: Custom active permissions Authors: Stefan Schießl - Reviewers: + Contributors and Reviewers: Alex Megalokonomos Fabian Schuh Abit From 40b7ae44d9b7b728f47fb46bfa18267ae3b205ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Tue, 7 Aug 2018 22:04:32 +0200 Subject: [PATCH 68/89] proposals can be created by anyone --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index e074e2b..9255b71 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -222,7 +222,7 @@ Exemplatory outcomes: - Transfer asset X with amount Y from account A to account C, signed with Key K: Denied - Transfer asset X with amount Y from account A to account B, signed with active authority of B: Denied - Transfer asset X with amount Y from account A to account B, signed with active authority of A: Accepted -- Create a proposal that includes operation 'transfer asset X with amount Y from account A to account B', signed with Key K: Denied +- Create a proposal that includes operation 'transfer asset X with amount Y from account A to account B', signed with Key K: Accepted. Anyone can create a proposal. Note: - This is included with the first Milestone From 552b5c4bfaf660f8ac4a076e7f559b57b12bd1b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Tue, 7 Aug 2018 22:34:03 +0200 Subject: [PATCH 69/89] include multi-sig example --- bsip-0040.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 9255b71..70f2518 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -222,12 +222,20 @@ Exemplatory outcomes: - Transfer asset X with amount Y from account A to account C, signed with Key K: Denied - Transfer asset X with amount Y from account A to account B, signed with active authority of B: Denied - Transfer asset X with amount Y from account A to account B, signed with active authority of A: Accepted -- Create a proposal that includes operation 'transfer asset X with amount Y from account A to account B', signed with Key K: Accepted. Anyone can create a proposal. +- Create a proposal that includes operation 'transfer asset X with amount Y from account A to account B, signed with Key K: Accepted. Anyone can create a proposal. Note: - This is included with the first Milestone - Normal permission logic is not altered. Account A can still sign the a transfer from account A to account B with its active authority +#### Involving multi-sig + +Account A has multi-sig active authority of account B and C. Account A has a custom active authority that grants key K transfer priviliges (any asset to any account). Account B has a custom active authority that grants key L transfer priviliges (any asset to any account). + +The transaction contains a transfer from A to account D. Required active authority of this operation is A. +- Signed by B and C: Accepted +- Signed by L and C: Denied. The custom active authority of B does not match, only applies for transfers with B as sender +- Signed by K: Accepted, basically bypassing multisig. This is intended, as the multisig needs to approve the installment of the custom active authority in the first place #### Example: Either or Assume account A, B and C and asset X and asset Y. The custom active authority should now achieve From 6a00164534bc7be75518f6b27822914e6ad04e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Wed, 8 Aug 2018 16:48:25 +0200 Subject: [PATCH 70/89] Update bsip-0040.md --- bsip-0040.md | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 70f2518..9ce13f7 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -46,7 +46,12 @@ This BSIP will be split into three parts that will be voted on separately (see M # Rational -Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `restrictions` than can be used to restrict arguments and is only valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of its required accounts. Check for every required account of the transaction if all its belonging operations have at least one positively matched `custom active authority` (match means its `authority` is granted through present signatures, same `operation_id`, now is within `valid_to` and `valid_from` and none of the `restrictions` is violated), and if so grant the active authority of the corresponding account. +Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, +an `authority` (just like with active permission) and `restrictions` than can be used to restrict arguments and is only +valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks +for each operation if there is a `custom active authority` for any of its required accounts. Check for every required +account of the transaction if all its belonging operations have at least one positively matched `custom active authority` +(see Specifications for definition of "matching"), and if so behave as if the active authority of the corresponding account is present (recursive authorities are excluded, see Examples). # Specification @@ -153,10 +158,10 @@ When a signed transaction arrives and before the backend evaluates if all necess - iterate over `required accounts` - iterate over all `operations` (child operations of proposal are not included) within the transactions that require the active authority of this account - iterate the `custom_active_authorities` of this account, and if it matches, remember that and continue with next `operation` - - if a `custom active authority` match was found for every operation in the loop, grant the `active authority` of this account + - if a `custom active authority` match was found for every operation in the loop, behave as if the `active authority` of this account is present for the correspoding operations Note: -- A `custom_active_authority` can only grant the `active authority` of the corresponding account, nothing more +- A `custom_active_authority` can only grant the `active authority` of the corresponding account for the matching operation, nothing more - The actual active authority of a required account can still be given as before, existing behavior is not to be changed - This for illustration, not actual implementation instructions @@ -237,6 +242,27 @@ The transaction contains a transfer from A to account D. Required active authori - Signed by L and C: Denied. The custom active authority of B does not match, only applies for transfers with B as sender - Signed by K: Accepted, basically bypassing multisig. This is intended, as the multisig needs to approve the installment of the custom active authority in the first place +#### Recursive active authority + +Suppose Alice has a custom active authority with key K for transfers to Charlie. Bob has Alice as his active authority account. Suppose a transaction containing two operations + +1. transfer 1 BTS from Alice to Charlie +2. transfer 1000 BTS from Bob to some other account + +Cases: +- Transaction is signed by K + - Operation 1. requires Alice as active authority, and there is a matching custom active authority, thus this operation would be allowed to execute + - Operation 2. requires Bob as active authority. Even though Bob has Alice as active authority, K can NOT grant recursively the active authority of Bob + - The whole transaction is denied +- Transaction is signed by K and A + - Operation 1. requires Alice as active authority and is also directly present, is allowed + - Operation 2. requires Bob as active authority, which is indirectly present through A, execution is allowed (existing logic) + - The whole transaction is denied because too many signatures are present (existing logic) +- Transaction is signed by K and B + - Operation 1. requires Alice as active authority, and there is a matching custom active authority, thus this operation would be allowed to execute + - Operation 2. requires Bob as active authority and is also directly present, is allowed + - Transaction may execute + #### Example: Either or Assume account A, B and C and asset X and asset Y. The custom active authority should now achieve that a transfer transaction sending funds away from A can be signed with with active authority of account B if @@ -326,7 +352,7 @@ The incoming transaction now contains `transfer 100 asset X from A to D, signed The required accounts (meaning required active authority) for the transaction is Account A. Backend would start considering `custom active authority 1` and check if active authority of account B is present through signatures. It is not, thus continue by checking if authority of `custom active authority 2` is present, which it is. -Acive authority of Account A is granted and normal authority checks are continued. +Behave as if active authority of Account A is present for the matched operation and continue with normal authority checks. Since the required accounts is Account A, and the given accounts is also Account A through `custom active authority 2`, the transaction is executed. From 5dcf316a63687feaae1130ea41f51b773fb342b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Thu, 9 Aug 2018 10:44:26 +0200 Subject: [PATCH 71/89] Update bsip-0040.md --- bsip-0040.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 9ce13f7..47e030d 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -158,10 +158,10 @@ When a signed transaction arrives and before the backend evaluates if all necess - iterate over `required accounts` - iterate over all `operations` (child operations of proposal are not included) within the transactions that require the active authority of this account - iterate the `custom_active_authorities` of this account, and if it matches, remember that and continue with next `operation` - - if a `custom active authority` match was found for every operation in the loop, behave as if the `active authority` of this account is present for the correspoding operations + - if a `custom active authority` match was found for every operation in the loop, behave as if the `active authority` of this account is present for the corresponding operations Note: -- A `custom_active_authority` can only grant the `active authority` of the corresponding account for the matching operation, nothing more +- A `custom_active_authority` can only grant the `active authority` of the required account of the corresponding operation, nothing more - The actual active authority of a required account can still be given as before, existing behavior is not to be changed - This for illustration, not actual implementation instructions From 3ac2159691d267ed45ac875044f4ee9620a7b024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Thu, 9 Aug 2018 10:53:53 +0200 Subject: [PATCH 72/89] update economics --- bsip-0040.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 47e030d..7e738d4 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -171,9 +171,13 @@ Adding a custom active authority means increased effort for the backend, and wit - `install_custom_active_authority`: Normal accounts can only create custom active authoritites with a duration of maximum 1 year, LTM can do any duration. Two options come to mind: - A fixed high fee independent of authorities content - Tied to the duration and complexity of the custom active authority. Transaction fee is then `fee = flat_fee + basic_fee * duration` where `basic_fee` is calculated according to complexity (e.g. size of authority, number of restrictions and etc.). Fee is capped at 1 year for LTM. -- `update_custom_active_authority`: Base fee similar to `account_update` plus dynamic one for any duration changes +- `update_custom_active_authority`: Base fee similar to `account_update` plus dynamic one for any duration changes, no payback if duration in decreased. - `delete_custom_active_authority`: Cheap similar to `limit_order_cancel` +This logic forces the user to think about the desired duration and enforces to put it rather too short than too long. +If a custom active is expired, or considered to be too short, extending it is easily doable. +After expired, the custom active becomes disabled and can still be enabled again with a new period, paying the fee for that new period. + ### Modification to the backend * Add a new index or extend the account object to store custom active permission are assigned to an account and contain a list of custom active authorities. Multiple custom active authority entries are possible for one operation From f1f97550ff64f69a8ddcd5a8202798d8a32dca9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Thu, 9 Aug 2018 11:09:37 +0200 Subject: [PATCH 73/89] add length and eq to number comparison --- bsip-0040.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bsip-0040.md b/bsip-0040.md index 7e738d4..048a49a 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -130,12 +130,15 @@ Stateless assert, all argument types. `Argument value` must NOT be equal to any Stateless assert. Allows explicit type conversion: - `int` type: use as is - `string` type: use `length` of string as `argument value` +- `object` type: use `size` of object as `argument value` +- `list` type: use `length` of the list as `argument value` The different asserts read as: - `lt`: `Argument value` must be less than `comparative` - `le`: `Argument value` must be less than or equal to `comparative` - `gt`: `Argument value` must be greater than `comparative` - `ge`: `Argument value` must be greater than or equal to `comparative` +- `eq`: `Argument value` must equal to `comparative` #### `limit` Stateful assert, only `int` type arguments. When the authority is created, `interval_began` is set to `valid_from` from its custom active authority and `max_cumsum` to `0`. Incoming operations are first tried to match all stateless asserts, From 0919eae319d91e81c12339cf578fafd06a8f854b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Thu, 9 Aug 2018 11:10:04 +0200 Subject: [PATCH 74/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 048a49a..8fb7a07 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -102,7 +102,7 @@ List of possible restrictions are: | ------------- |:-------------:| -----:| | `any` | [`list`, `of`, `allowed`, `values`] | stateless | | `none` | [`none`, `of`, `these`, `values`] | stateless | -| `lt, le, gt, ge` | `comparative` | stateless | +| `lt, le, gt, ge, eq` | `comparative` | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | | `attribute_assert` | list of restrictions | stateless | From 78100ed43f4e446c4effd89fe165db92913d631f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Thu, 9 Aug 2018 11:19:19 +0200 Subject: [PATCH 75/89] add `contains, not_contains` --- bsip-0040.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bsip-0040.md b/bsip-0040.md index 8fb7a07..77ba3cc 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -103,6 +103,7 @@ List of possible restrictions are: | `any` | [`list`, `of`, `allowed`, `values`] | stateless | | `none` | [`none`, `of`, `these`, `values`] | stateless | | `lt, le, gt, ge, eq` | `comparative` | stateless | +| `contains, not_contains` | [`list`, `of`, `values`] | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | | `attribute_assert` | list of restrictions | stateless | @@ -140,6 +141,11 @@ The different asserts read as: - `ge`: `Argument value` must be greater than or equal to `comparative` - `eq`: `Argument value` must equal to `comparative` +#### `contains, not_contains` +Stateless assert, for `list` type arguments. +- `contains`: The `argument value` must contain all items specified by `data`, but can contain more +- `not_contains`: The `argument value` must NOT contain any of the items specified by `data`, but can contain others + #### `limit` Stateful assert, only `int` type arguments. When the authority is created, `interval_began` is set to `valid_from` from its custom active authority and `max_cumsum` to `0`. Incoming operations are first tried to match all stateless asserts, and if all passes continue with stateful asserts. If `now > interval_began + interval_in_sec`, then set `max_cumsum = 0` and set `interval_began = now`. From a1ce8ab255c3a78232ed2d8c8b78fa3b721a35a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Thu, 9 Aug 2018 11:20:37 +0200 Subject: [PATCH 76/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 77ba3cc..6b1caaf 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -373,7 +373,7 @@ the transaction is executed. We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: -1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` +1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge`, `contains, not_contains` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` 2. Implement stateful asserts `limit` and `limit_monthly` 3. Implement `logical_or` From e9c8e9bc88749f16200fad8b8cc497ca8e3e8a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 10 Aug 2018 06:56:05 +0200 Subject: [PATCH 77/89] add neq --- bsip-0040.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 6b1caaf..a33801e 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -102,7 +102,7 @@ List of possible restrictions are: | ------------- |:-------------:| -----:| | `any` | [`list`, `of`, `allowed`, `values`] | stateless | | `none` | [`none`, `of`, `these`, `values`] | stateless | -| `lt, le, gt, ge, eq` | `comparative` | stateless | +| `lt, le, gt, ge, eq, neq` | `comparative` | stateless | | `contains, not_contains` | [`list`, `of`, `values`] | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | @@ -127,7 +127,7 @@ Stateless assert, all argument types. `Argument value` must be equal to one of v #### `none` Stateless assert, all argument types. `Argument value` must NOT be equal to any of the values in the list. -#### `lt, le, gt, ge` +#### `lt, le, gt, ge, eq, neq` Stateless assert. Allows explicit type conversion: - `int` type: use as is - `string` type: use `length` of string as `argument value` @@ -140,6 +140,7 @@ The different asserts read as: - `gt`: `Argument value` must be greater than `comparative` - `ge`: `Argument value` must be greater than or equal to `comparative` - `eq`: `Argument value` must equal to `comparative` +- `eq`: `Argument value` must NOT be equal to `comparative` #### `contains, not_contains` Stateless assert, for `list` type arguments. @@ -373,7 +374,7 @@ the transaction is executed. We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: -1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge`, `contains, not_contains` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` +1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge, eq, neq`, `contains, not_contains` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` 2. Implement stateful asserts `limit` and `limit_monthly` 3. Implement `logical_or` From f9c2df5d355d53851a4794c2a61a367b5f833cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 10 Aug 2018 06:59:30 +0200 Subject: [PATCH 78/89] Clarify duration --- bsip-0040.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index a33801e..ccd10d2 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -180,7 +180,8 @@ Note: Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: - `install_custom_active_authority`: Normal accounts can only create custom active authoritites with a duration of maximum 1 year, LTM can do any duration. Two options come to mind: - A fixed high fee independent of authorities content - - Tied to the duration and complexity of the custom active authority. Transaction fee is then `fee = flat_fee + basic_fee * duration` where `basic_fee` is calculated according to complexity (e.g. size of authority, number of restrictions and etc.). Fee is capped at 1 year for LTM. + - Tied to the duration and complexity of the custom active authority. Transaction fee is then `fee = flat_fee + basic_fee * duration` where `basic_fee` is calculated according to complexity (e.g. size of authority, number of restrictions and etc.). Fee is capped at 1 year for LTM, `duration` refers to the time that is still left, not the actual duration + (i.e. `date_to - max(now, date_from)`) - `update_custom_active_authority`: Base fee similar to `account_update` plus dynamic one for any duration changes, no payback if duration in decreased. - `delete_custom_active_authority`: Cheap similar to `limit_order_cancel` From bd2af374af1b8679426f68d2471e1b40793570f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 10 Aug 2018 07:15:18 +0200 Subject: [PATCH 79/89] If beneficial for performance or complexity sections --- bsip-0040.md | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index ccd10d2..17793a6 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -103,7 +103,7 @@ List of possible restrictions are: | `any` | [`list`, `of`, `allowed`, `values`] | stateless | | `none` | [`none`, `of`, `these`, `values`] | stateless | | `lt, le, gt, ge, eq, neq` | `comparative` | stateless | -| `contains, not_contains` | [`list`, `of`, `values`] | stateless | +| `contains_all, contains_none` | [`list`, `of`, `values`] | stateless | | `limit` | [`max_cumsum`, `interval_in_sec`] | [`current_cumsum`, `interval_began`] | | `limit_monthly` | [`max_cumsum`, `interval_in_months`] | [`current_cumsum`, `interval_began`] | | `attribute_assert` | list of restrictions | stateless | @@ -117,15 +117,22 @@ Following cases must hold for a restriction: Note: - If required a field can be added that stores the assumed type of the argument +- This list of restrictions may be redefined to improve clarity, performance or to reduce complexity of implementation while maintaining the intended functionality In the following we list possible `restriction`s. Mentioning `argument value` in the text below refers to the value of the argument of the operation specified by `argument` of a restriction. #### `any` -Stateless assert, all argument types. `Argument value` must be equal to one of values in the data list +Stateless assert, all argument types. `Argument value` must be equal to one of values in the data list. + +Note +- If beneficial for performance or complexity an additional operator `equal` can be implemented that only compares to one. #### `none` -Stateless assert, all argument types. `Argument value` must NOT be equal to any of the values in the list. +Stateless assert, all argument types. `Argument value` must NOT be equal to any of the values in the list. + +Note +- If beneficial for performance or complexity an additional operator `not_equal` can be implemented that only compares to one. #### `lt, le, gt, ge, eq, neq` Stateless assert. Allows explicit type conversion: @@ -140,12 +147,16 @@ The different asserts read as: - `gt`: `Argument value` must be greater than `comparative` - `ge`: `Argument value` must be greater than or equal to `comparative` - `eq`: `Argument value` must equal to `comparative` -- `eq`: `Argument value` must NOT be equal to `comparative` +- `neq`: `Argument value` must NOT be equal to `comparative` -#### `contains, not_contains` +Note +- `eq` and `neq` are implicit number comparators and not to be mistaken by a strict left must equal right operator, just like `lt, le, gt, ge` (for example, comparing `1 > list object` would have no sense) +- If beneficial for performance or complexity the implicit type conversions can be removed and distinct operators introduced that do not have implicit type conversions + +#### `contains_all, contains_none` Stateless assert, for `list` type arguments. -- `contains`: The `argument value` must contain all items specified by `data`, but can contain more -- `not_contains`: The `argument value` must NOT contain any of the items specified by `data`, but can contain others +- `contains_all`: The `argument value` must contain all items specified by `data`, but can contain more +- `contains_none`: The `argument value` must NOT contain any of the items specified by `data`, but can contain others #### `limit` Stateful assert, only `int` type arguments. When the authority is created, `interval_began` is set to `valid_from` from its custom active authority and `max_cumsum` to `0`. Incoming operations are first tried to match all stateless asserts, @@ -375,7 +386,7 @@ the transaction is executed. We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: -1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge, eq, neq`, `contains, not_contains` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` +1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge, eq, neq`, `contains_all, contains_none` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` 2. Implement stateful asserts `limit` and `limit_monthly` 3. Implement `logical_or` From 0c43bfd8bab11e72fdb6ee002d4f91efd3c4ecaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 10 Aug 2018 07:26:10 +0200 Subject: [PATCH 80/89] Update bsip-0040.md --- bsip-0040.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 17793a6..ea935ec 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -186,20 +186,6 @@ Note: - The actual active authority of a required account can still be given as before, existing behavior is not to be changed - This for illustration, not actual implementation instructions -### Economics - -Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: -- `install_custom_active_authority`: Normal accounts can only create custom active authoritites with a duration of maximum 1 year, LTM can do any duration. Two options come to mind: - - A fixed high fee independent of authorities content - - Tied to the duration and complexity of the custom active authority. Transaction fee is then `fee = flat_fee + basic_fee * duration` where `basic_fee` is calculated according to complexity (e.g. size of authority, number of restrictions and etc.). Fee is capped at 1 year for LTM, `duration` refers to the time that is still left, not the actual duration - (i.e. `date_to - max(now, date_from)`) -- `update_custom_active_authority`: Base fee similar to `account_update` plus dynamic one for any duration changes, no payback if duration in decreased. -- `delete_custom_active_authority`: Cheap similar to `limit_order_cancel` - -This logic forces the user to think about the desired duration and enforces to put it rather too short than too long. -If a custom active is expired, or considered to be too short, extending it is easily doable. -After expired, the custom active becomes disabled and can still be enabled again with a new period, paying the fee for that new period. - ### Modification to the backend * Add a new index or extend the account object to store custom active permission are assigned to an account and contain a list of custom active authorities. Multiple custom active authority entries are possible for one operation @@ -213,6 +199,21 @@ After expired, the custom active becomes disabled and can still be enabled again Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion + +# Economics + +Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: +- `install_custom_active_authority`: Normal accounts can only create custom active authoritites with a duration of maximum 1 year, LTM can do any duration. Two options come to mind: + - A fixed high fee independent of authorities content + - Tied to the duration and complexity of the custom active authority. Transaction fee is then `fee = flat_fee + basic_fee * duration` where `basic_fee` is calculated according to complexity (e.g. size of authority, number of restrictions and etc.). Fee is capped at 1 year for LTM, `duration` refers to the time that is still left, not the actual duration + (i.e. `date_to - max(now, date_from)`) +- `update_custom_active_authority`: Base fee similar to `account_update` plus dynamic one for any duration changes, no payback if duration in decreased. +- `delete_custom_active_authority`: Cheap similar to `limit_order_cancel` + +This logic forces the user to think about the desired duration and enforces to put it rather too short than too long. +If a custom active is expired, or considered to be too short, extending it is easily doable. +After expired, the custom active becomes disabled and can still be enabled again with a new period, paying the fee for that new period. + # Discussion To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/1061) and [pull request](https://github.com/bitshares/bsips/pull/86). From 0f2a4335160f19f48743df9fd80990d4a4976751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 10 Aug 2018 07:27:42 +0200 Subject: [PATCH 81/89] Update bsip-0040.md --- bsip-0040.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bsip-0040.md b/bsip-0040.md index ea935ec..58efbcd 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -23,6 +23,8 @@ permission contains a list of operationid-to-authority mappings that each grant operation as if it were the active permission of the account. Additionally, the arguments of said operation can be restricted. +For the non-technical reader the section Specification can be skipped. + # Motivation Any successfull hacking or phishing attempt on any of the web wallets that are powered by the From 982348ca5d890dbd5a6ddd1efeea1c15ae5cbec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 10 Aug 2018 13:53:57 +0200 Subject: [PATCH 82/89] add `remaining_executions` --- bsip-0040.md | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 58efbcd..0589e1f 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -44,17 +44,21 @@ The above list of named keys is nothing that is known to the backend as the back Note: The user can still use the active authority just like used to, no change in existing behavior. The named keys only give an additional possibility. For example: The user can login the UI using the private key of such a named key. Then he only as access to the operations that this named key grants. He can still login with the existing password to gain full access (similar a local wallet can be created that only contains the named key). -This BSIP will be split into three parts that will be voted on separately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows stateful restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions. Milestone 2 and 3 will be put up for voting if Milestone 1 proves successful. +This BSIP will be split into three parts that will be voted on separately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows stateful restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions and Milestone 4 allows to set a number of allowed executions per authority (makes the `custom active authorities` more dependent on the chain state). Milestone 2, 3 and 4 will be put up for voting if Milestone 1 proves successful. # Rational Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, -an `authority` (just like with active permission) and `restrictions` than can be used to restrict arguments and is only -valid a certain time period (`valid_from` and `valid_to`). When handling incoming signed transactions, the backend checks +an `authority` (just like with active permission) and `restrictions` than can be used to restrict arguments. +Furthermore, such a `custom active authority` is only valid in a specified time period (`valid_from` and `valid_to`). +When handling incoming signed transactions, the backend checks for each operation if there is a `custom active authority` for any of its required accounts. Check for every required account of the transaction if all its belonging operations have at least one positively matched `custom active authority` (see Specifications for definition of "matching"), and if so behave as if the active authority of the corresponding account is present (recursive authorities are excluded, see Examples). +Note: If Milestone 4 is implemented, a `custom active authority` can be valid in the above-mentioned time period and/or +for a number of executions defined by `remaining_executions`. The user can choose to restrict both or only the number of executions, but the number of executions can only be unlimited (not set) only if a time period is specified. + # Specification All descriptions in this section are on a pseudo/prosa level and no recommendation how it can best be implemented or serialized. They are meant to facilitate the understanding. If anything in the looping process or order of evaluation is unsuitable for actual implementation, changes can be made accordingly as long the same functionality is achieved. @@ -68,12 +72,13 @@ custom_active_permission = { authorities = list of custom_active_authority objects } custom_active_authority = { - enabled, // status of this authority, true or false. true when created - valid_from, // timestamp when this is active - valid_to, // timestamp when this is invalid - operation_id, // operation id of the target operation, - authority, // same as for the existing authotities (multisig with weighted accounts or keys), - restrictions // see below + enabled, // status of this authority, true or false. true when created + valid_from, // timestamp when this is active + valid_to, // timestamp when this is invalid + remaining_executions, // number of allowed executions + operation_id, // operation id of the target operation, + authority, // same as for the existing authotities (multisig with weighted accounts or keys), + restrictions // see below } ``` Note: This assumes `custom_active_permission` is stored in a separate index. Actual implementation details left to the implementer, as long as every `custom_active_permission` can be assigned to exactly one account. @@ -83,6 +88,7 @@ A `custom active authority` is matched against operations of an incoming, signed - `account_id` is in the required accounts of the operation - the `authority` of the `custom_active_authority` is given by the signatures of the transaction - timestamp `now` is within `valid_to` and `valid_from` +- `remaining_executions` is either not set or > 0 (only Milestone 4) - all `restrictions` assert positively ### Restrictions @@ -181,7 +187,7 @@ When a signed transaction arrives and before the backend evaluates if all necess - iterate over `required accounts` - iterate over all `operations` (child operations of proposal are not included) within the transactions that require the active authority of this account - iterate the `custom_active_authorities` of this account, and if it matches, remember that and continue with next `operation` - - if a `custom active authority` match was found for every operation in the loop, behave as if the `active authority` of this account is present for the corresponding operations + - if a `custom active authority` match was found for every operation in the loop, behave as if the `active authority` of this account is present for the corresponding operations. Decrease `remaining_executions` by one if set (only Milestone 4) Note: - A `custom_active_authority` can only grant the `active authority` of the required account of the corresponding operation, nothing more @@ -201,7 +207,6 @@ Note: Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion - # Economics Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: @@ -392,6 +397,7 @@ We propose do split the implmentation into two milestones. Each milestone will b 1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge, eq, neq`, `contains_all, contains_none` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` 2. Implement stateful asserts `limit` and `limit_monthly` 3. Implement `logical_or` +4. Implement `remaining_executions` This approach allows as well to add other asserts at a later stage (with a new BSIP). From 64338a4340c0b35b0e9ec7934773d923da81e038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 10 Aug 2018 13:55:17 +0200 Subject: [PATCH 83/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 0589e1f..3e57d0d 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -44,7 +44,7 @@ The above list of named keys is nothing that is known to the backend as the back Note: The user can still use the active authority just like used to, no change in existing behavior. The named keys only give an additional possibility. For example: The user can login the UI using the private key of such a named key. Then he only as access to the operations that this named key grants. He can still login with the existing password to gain full access (similar a local wallet can be created that only contains the named key). -This BSIP will be split into three parts that will be voted on separately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows stateful restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions and Milestone 4 allows to set a number of allowed executions per authority (makes the `custom active authorities` more dependent on the chain state). Milestone 2, 3 and 4 will be put up for voting if Milestone 1 proves successful. +This BSIP will be split into parts that will be voted on separately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows stateful restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions and Milestone 4 allows to set a number of allowed executions per authority (introduces an additional on-chain dependency). Milestone 2, 3 and 4 will be put up for voting if Milestone 1 proves successful. # Rational From 02bb9e521bace05be9600e509711dcf83dd59442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 10 Aug 2018 14:07:07 +0200 Subject: [PATCH 84/89] Milestone 4 in separate section --- bsip-0040.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 3e57d0d..69fb79a 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -46,6 +46,8 @@ Note: The user can still use the active authority just like used to, no change i This BSIP will be split into parts that will be voted on separately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows stateful restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions and Milestone 4 allows to set a number of allowed executions per authority (introduces an additional on-chain dependency). Milestone 2, 3 and 4 will be put up for voting if Milestone 1 proves successful. +Note: The impact of Milestone 4 is explained in its own section to not hinder the reading flow + # Rational Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, @@ -56,9 +58,6 @@ for each operation if there is a `custom active authority` for any of its requir account of the transaction if all its belonging operations have at least one positively matched `custom active authority` (see Specifications for definition of "matching"), and if so behave as if the active authority of the corresponding account is present (recursive authorities are excluded, see Examples). -Note: If Milestone 4 is implemented, a `custom active authority` can be valid in the above-mentioned time period and/or -for a number of executions defined by `remaining_executions`. The user can choose to restrict both or only the number of executions, but the number of executions can only be unlimited (not set) only if a time period is specified. - # Specification All descriptions in this section are on a pseudo/prosa level and no recommendation how it can best be implemented or serialized. They are meant to facilitate the understanding. If anything in the looping process or order of evaluation is unsuitable for actual implementation, changes can be made accordingly as long the same functionality is achieved. @@ -75,7 +74,6 @@ custom_active_authority = { enabled, // status of this authority, true or false. true when created valid_from, // timestamp when this is active valid_to, // timestamp when this is invalid - remaining_executions, // number of allowed executions operation_id, // operation id of the target operation, authority, // same as for the existing authotities (multisig with weighted accounts or keys), restrictions // see below @@ -88,7 +86,6 @@ A `custom active authority` is matched against operations of an incoming, signed - `account_id` is in the required accounts of the operation - the `authority` of the `custom_active_authority` is given by the signatures of the transaction - timestamp `now` is within `valid_to` and `valid_from` -- `remaining_executions` is either not set or > 0 (only Milestone 4) - all `restrictions` assert positively ### Restrictions @@ -187,7 +184,7 @@ When a signed transaction arrives and before the backend evaluates if all necess - iterate over `required accounts` - iterate over all `operations` (child operations of proposal are not included) within the transactions that require the active authority of this account - iterate the `custom_active_authorities` of this account, and if it matches, remember that and continue with next `operation` - - if a `custom active authority` match was found for every operation in the loop, behave as if the `active authority` of this account is present for the corresponding operations. Decrease `remaining_executions` by one if set (only Milestone 4) + - if a `custom active authority` match was found for every operation in the loop, behave as if the `active authority` of this account is present for the corresponding operations. Note: - A `custom_active_authority` can only grant the `active authority` of the required account of the corresponding operation, nothing more @@ -207,6 +204,17 @@ Note: Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion +### Milestone 4: Number of executions + +If Milestone 4 is implemented, a `custom active authority` receives an additional field `remaining_executions` to +specify the allowed number of executions. +The user can choose to restrict the valid time period and/or the number of executions, but the number of executions can only +be unlimited (not set) if a time period is specified. A `custom active authority` then matches if the time period is +valid or not set, and `remaining_executions` is either not set or > 0. When a `custom active authority` successfully grants +the active authority for the corresponding operation and the whole transaction is executed, `remaining_executions` is +decreased by one. If it becomes zero, the `custom active authority` becomes disabled. +If the `custom active authority` does not get replenished by the user within one month, it will be deleted. + # Economics Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: @@ -221,6 +229,8 @@ This logic forces the user to think about the desired duration and enforces to p If a custom active is expired, or considered to be too short, extending it is easily doable. After expired, the custom active becomes disabled and can still be enabled again with a new period, paying the fee for that new period. +Note: For Milestone 4 the install fee would be dependent on the number of executions if no time period is set. + # Discussion To be found in the [issue](https://github.com/bitshares/bitshares-core/issues/1061) and [pull request](https://github.com/bitshares/bsips/pull/86). @@ -399,9 +409,6 @@ We propose do split the implmentation into two milestones. Each milestone will b 3. Implement `logical_or` 4. Implement `remaining_executions` -This approach allows as well to add other asserts at a later stage (with a new BSIP). - - # Summary for Shareholders Bad publicity in terms of security can have very negative effect on the BTS value. This BSIP allows that traders can e.g. use a trading key, witnesses can use their witness key and a faucet can use a faucet key. If then for some reason the key or witness/faucet server becomes compromised, such a key can do little harm to the account holders, minimizing the risk. From 1d0a341e61afd80ff757d6c3be6744de2ae9a88c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 10 Aug 2018 14:08:02 +0200 Subject: [PATCH 85/89] Update bsip-0040.md --- bsip-0040.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index 69fb79a..096a005 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -46,8 +46,6 @@ Note: The user can still use the active authority just like used to, no change i This BSIP will be split into parts that will be voted on separately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows stateful restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions and Milestone 4 allows to set a number of allowed executions per authority (introduces an additional on-chain dependency). Milestone 2, 3 and 4 will be put up for voting if Milestone 1 proves successful. -Note: The impact of Milestone 4 is explained in its own section to not hinder the reading flow - # Rational Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, @@ -62,6 +60,8 @@ account of the transaction if all its belonging operations have at least one pos All descriptions in this section are on a pseudo/prosa level and no recommendation how it can best be implemented or serialized. They are meant to facilitate the understanding. If anything in the looping process or order of evaluation is unsuitable for actual implementation, changes can be made accordingly as long the same functionality is achieved. +Note: The impact of Milestone 4 is explained in its own subsection to not hinder the reading flow + ### Custom active permission and custom active authority A `custom active permission` contains a list of `custom active authorities` and looks like follows (in JSON-like/pseudo for clarification): From e749319cace5ed0d43f8ce4abfcb2c8003a13527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Fri, 10 Aug 2018 22:42:02 +0200 Subject: [PATCH 86/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 096a005..ddabb8d 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -222,7 +222,7 @@ Adding a custom active authority means increased effort for the backend, and wit - A fixed high fee independent of authorities content - Tied to the duration and complexity of the custom active authority. Transaction fee is then `fee = flat_fee + basic_fee * duration` where `basic_fee` is calculated according to complexity (e.g. size of authority, number of restrictions and etc.). Fee is capped at 1 year for LTM, `duration` refers to the time that is still left, not the actual duration (i.e. `date_to - max(now, date_from)`) -- `update_custom_active_authority`: Base fee similar to `account_update` plus dynamic one for any duration changes, no payback if duration in decreased. +- `update_custom_active_authority`: Base fee similar to `account_update` plus dynamic one for any duration increase, no payback if duration in decreased (increase/decrease is evaluated on both interval ends separately) - `delete_custom_active_authority`: Cheap similar to `limit_order_cancel` This logic forces the user to think about the desired duration and enforces to put it rather too short than too long. From 51d46dae435fbf8bb2dbdf029cec186f0ac7d285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Sun, 12 Aug 2018 20:45:24 +0200 Subject: [PATCH 87/89] Update bsip-0040.md --- bsip-0040.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bsip-0040.md b/bsip-0040.md index ddabb8d..77a2c9f 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -220,7 +220,7 @@ If the `custom active authority` does not get replenished by the user within one Adding a custom active authority means increased effort for the backend, and with a stateful one also the need for more storage. Proposed transaction fees: - `install_custom_active_authority`: Normal accounts can only create custom active authoritites with a duration of maximum 1 year, LTM can do any duration. Two options come to mind: - A fixed high fee independent of authorities content - - Tied to the duration and complexity of the custom active authority. Transaction fee is then `fee = flat_fee + basic_fee * duration` where `basic_fee` is calculated according to complexity (e.g. size of authority, number of restrictions and etc.). Fee is capped at 1 year for LTM, `duration` refers to the time that is still left, not the actual duration + - Tied to the duration and complexity of the custom active authority. Transaction fee is then `fee = flat_fee + basic_fee * duration` where `basic_fee` is calculated according to complexity (e.g. size of authority, number of restrictions and etc.). The period `duration` refers to the time that is still left, not the set duration (i.e. `date_to - max(now, date_from)`) - `update_custom_active_authority`: Base fee similar to `account_update` plus dynamic one for any duration increase, no payback if duration in decreased (increase/decrease is evaluated on both interval ends separately) - `delete_custom_active_authority`: Cheap similar to `limit_order_cancel` @@ -229,7 +229,8 @@ This logic forces the user to think about the desired duration and enforces to p If a custom active is expired, or considered to be too short, extending it is easily doable. After expired, the custom active becomes disabled and can still be enabled again with a new period, paying the fee for that new period. -Note: For Milestone 4 the install fee would be dependent on the number of executions if no time period is set. +Note: +- For Milestone 4 the install fee would be dependent on the number of executions if no time period is set. # Discussion From b5602911ada17004882251c95d9edf610eef3816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 13 Aug 2018 13:00:04 +0200 Subject: [PATCH 88/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index 77a2c9f..a152673 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -46,7 +46,7 @@ Note: The user can still use the active authority just like used to, no change i This BSIP will be split into parts that will be voted on separately (see Milestones section). All of the above keys are possible with Milestone 1. Milestone 2 allows stateful restrictions (e.g. allow market orders up to some amount for every month), Milestone 3 gives finer control of how to combine restrictions and Milestone 4 allows to set a number of allowed executions per authority (introduces an additional on-chain dependency). Milestone 2, 3 and 4 will be put up for voting if Milestone 1 proves successful. -# Rational +# Rationale Custom active permission is a list of `custom active authorities`. A `custom active authority` contains an `operation_id`, an `authority` (just like with active permission) and `restrictions` than can be used to restrict arguments. From b0dfaa54adbfa8d61a2b0a5d1571746be57abe5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schie=C3=9Fl?= Date: Mon, 13 Aug 2018 13:01:42 +0200 Subject: [PATCH 89/89] Update bsip-0040.md --- bsip-0040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsip-0040.md b/bsip-0040.md index a152673..9332eaf 100644 --- a/bsip-0040.md +++ b/bsip-0040.md @@ -403,7 +403,7 @@ the transaction is executed. # Milestones -We propose do split the implmentation into two milestones. Each milestone will be voted on as a separate BSIP: +We propose do split the implentation into multiple milestones. Each milestone will be voted on separately: 1. Implementation of basic functionaliy to allow custom active permissions and authorities, including `any`, `none` and `lt, le, gt, ge, eq, neq`, `contains_all, contains_none` and `attribute_assert` `asserts`. If deemed necessary by developpers, reduce to only allow one key or one account for every `custom active authority` 2. Implement stateful asserts `limit` and `limit_monthly`