"Failure: require-capability: not granted" How do I grant a capability to my module? - pact-lang

I've got a very simple function (increase-count), and I do not want this to be callable by anybody except code in the module. For this, I am using (require-capability (PRIVATE)). As expected, I get the following error.
Error from (api.testnet.chainweb.com): : Failure: require-capability: not granted: (free.guard-test-01.PRIVATE)
How do I grant my module the PRIVATE capability?
(defcap PRIVATE ()
true
)
(defun increase-count (key:string)
;increase the count of a key in a table by 1
(require-capability (PRIVATE))
(update counts-table key {"count": (+ 1 (get-count key))})
)

surround the call increase-count like this:
(with-capability (PRIVATE) (increase-count "abc"))
more in general:
(with-capability (CAP) expr) will evaluate CAP to see whether you can grant it (this is the place where acquisition can fail), and then expr will be evaluated with CAP in scope if you successfully acquire it.
(require-capability (CAP)) is then what you use within the scope of the functions you're trying to enforce CAP is present before you can proceed

Related

Declaring a property test in an interface using a constant defined in the same interface

I am trying to verify a module I have implemented against an interface, where the interface includes a model for a specific function. That model relies on a constant, also defined in the interface. It looks like this:
(interface my-interface
(defconst MAX:decimal 100.0)
(defun id:decimal (amount:decimal)
#model [(property (<= amount MAX))]))
(module my-module GOVERNANCE
(implements my-interface)
(defcap GOVERNANCE ()
true)
(defun id:decimal (amount:decimal)
(enforce (<= amount my-interface.MAX)
(format "{} exceeds the maximum ({})" [ amount, my-interface.MAX ]))
amount))
This results in a failure when running (verify "my-module") a REPL file like this:
(begin-tx)
(load "./tester.pact")
(commit-tx)
(verify "my-module")
Specifically, the error:
:OutputFailure: could not parse (<= amount MAX): couldn't find property variable MAX
If I replace my model with this code then it works:
#model [(property (<= amount 100.0))]
I thought perhaps I needed to qualify the constant, but this fails as well:
#model [(property (<= amount my-interface.MAX))]
with the error message:
:OutputFailure: : could not parse (<= amount my-interface.MAX): in my-interface.MAX, expected property
Oddly enough, I can use the constant if I declare an invariant in a (defschema):
(interface my-interface
(defconst MAX:decimal 100.0)
(defschema my-schema
#model [(invariant (<= total MAX))]
total:decimal))
But, alas, I am not able to use the constant when declaring property tests in functions in the interface. So: how can I refer to a constant defined in my interface in a property test in the same interface?

How to delete a class instance based on if an instance variable returns true?

I have made a fake CRUD-based bank account manager that can create new accounts and also destroy them using the terminal. Just to make clear, this is not a Rails application. I've made a 'fake' MVC structure in vanilla Ruby to understand the basic concept.
I'm having difficulty trying to delete a class instance when the 'destroy' criteria has been satisfied. In this case, if a user wants to destroy a bank account, they need to specify the bank account number of the class instance. I'm not sure if my Ruby method is just incorrectly trying to handle the deletion or if what I am doing is not possible.
Here is method so far:
def delete(account_number)
#accounts.each_with_index do |account, index|
account.include?(account_number) ? account.delete_at(index) : "No account found"
end
end
Here is the error message I am being presented:
`block in delete': undefined method `include?' for #<Account:0x00007fe82c8926c0 #name="test", #account_number="12345", #sort_code="040004", #balance="1234.5"> (NoMethodError)
Essentially, my end goal is for my method to scan the class instance, match #account_number with the account_number passed in the terminal and delete the instance completely. I've been able to do this using 'index' i.e. "delete the 1st in the list" (index + 1) but want to try a more advanced way.
N.B: #accounts is an instance variable set as an array to store the instances.
I would use Array#delete_if when I want to delete an account with a certain name for an array of accounts.
def delete(account_number)
#accounts.delete_if { |account| account.number == account_number }
end
If there is no matching account found then this method keeps the #accounds array unchanged.

Error code: VUTA(3) Error: separate target of the Object_call is not controlled

I'm a complete beginner to Eiffel and I'm implementing a linked list as an exercise. I get the following error in the feature has (which tells you if the list contains v).
Error code: VUTA(3)
Error: separate target of the Object_call is not controlled.
What to do: ensure the target of the call is controlled or is not separate.
Class: MY_LINKED_LIST [G]
Feature: has
Type: Generic #1
Line: 159
then
-> if l_cursor_a.item.is_equal (v) then
Result := True
The weird thing is that when I change the '.is_equal' for a '=' the error is gone. I don't know what 'controlled' in the error description means and what difference to it does make to use '=' in this context. The code is the following:
MY_LINKED_LIST[G]
class
MY_LINKED_LIST[G]
feature -- Access
item: G
require
not off
do
check
off: attached cursor as l_cursor
then
Result := l_cursor.item
end
end
first,
last: detachable like item
feature -- Measurement
count: INTEGER
feature -- Element change
feature -- Status report
index: INTEGER
before: BOOLEAN
after: BOOLEAN
has (v: like item): BOOLEAN
require
local
l_cursor: like cursor
do
from
l_cursor := first_element
until
not attached l_cursor or Result
loop
check
attached l_cursor as l_cursor_a
then
if l_cursor_a.item.is_equal (v) then
Result := True
end
l_cursor := l_cursor_a.next
end
end
ensure
function_not_change_state: item = old item
end
feature {NONE} -- Implementation
cursor,
first_element,
last_element: detachable MY_CELL[G]
end -- class
MY_CELL[G]
class
MY_CELL[G]
feature -- Access
item: G
The error message is related to SCOOP — the model of concurrent programming built into Eiffel. According to it, a feature can be called on a separate object only when the object is controlled. This is achieved when the target of the call is an argument of a feature, or when a special separate instruction is used. In your case, the latter would look like
separate l_cursor_a.item as x do
if x.is_equal (v) then
Result := True
end
end
Why l_cursor_a.item is considered separate in the first place? It has a type G, and the formal generic is unconstrained that is identical to have a constraint detachable separate ANY (so, most probably, the code above would not compile, you would need to make sure x is attached before calling is_equal on it).
The equality operator = does not perform any calls (unless the involved types are expanded, but expanded types are never separate). For reference types (including separate ones), it simply tests whether two references are the same. This explains why the error disappears when is_equal is replaced with =.
An alternative solution to avoid the error message is to change the constraint of the formal generic to be non-separate: MY_LINKED_LIST [G -> detachable ANY].
Side note. The check instruction check attached l_cursor as l_cursor_a then ... seems to be redundant, the compiler should be able to figure out automatically that l_cursor is attached.

Implementation contraint: The class feature only_from_type uses an inline agent

Is there a semantic behind not being able to have an agent into a ensure class routine or is it a current compiler restriction?
only_from_type (some_items: CHAIN[like Current]; a_type: detachable like {ENUMERATE}.measuring_point_type_generation): LINKED_LIST[like Current]
-- extends Result with given some_items which are equal to given type
do
create Result.make
across
some_items is l_item
loop
check
attached_type: attached l_item.type as l_type
then
if attached a_type as l_a_type and then l_type.is_equal (l_a_type) then
Result.extend (l_item)
end
end
end
ensure
some_items.for_all (
agent (an_item: like Current; a_type_2: detachable like {ENUMERATE}.measuring_point_type_generation) do
if attached a_type_2 as l_type_2_a and then
attached an_item.type as l_item_type and then
l_item_type.is_equal (l_type_2_a)
then
Result := True
end
end (a_type)
)
instance_free: Class
end
gives following error
And I think there is a typo here, shouldn't it be Implementation constraint instead of contraint?
Error code: VUCR
Implementation contraint: The class feature only_from_type uses an inline agent.
What to do: Remove the inline agent from the code or make the feature a non-class one.
Class: MEASURING_POINT
Feature: only_from_type
Line: 183
some_items.for_all (
-> agent (an_item: like Current; a_type_2: detachable like {ENUMERATE}.measuring_point_type_generation) do
if attached a_type_2 as l_type_2_a and then
An inline agent (like a regular feature) takes an implicit argument - current object. In a class feature (where it is used in the example), there is no current object. Therefore, an inline agent cannot be called from a class feature.
On the other hand, it might be possible to check that the agent does not use Current, and, therefore, is safe to use in the class feature. The compiler reporting the error does not implement such a functionality, and reports an implementation constraint error instead.

How to call a function with void return using Firedac FDConnection Component in Delphi XE5?

I recently started using the [ExecSQLScalar]1 and [ExecSQL]2 methods of the FDConnection component in Delphi XE5. It's very handy not to need to build a Dataset object, like FDQuery just for simple queries or executions.
However I had a curious problem when executing a function with void return that has internal validations where it can generate exceptions. I'm using a Postgres database.
CREATE FUNCTION can_be_exception()
RETURNS void AS
$$
BEGIN
RAISE EXCEPTION E'fail';
END;
$$
LANGUAGE plpgsql STABLE;
In delphi, I call the ExecSQLScalar function ...
FDConnection1.ExecSQLScalar('select 1');
FDConnection1.ExecSQLScalar('select can_be_exception()');
On first run, I get the following error:
Project TFDConnectionDEMO.exe raised exception class
EPgNativeException with message '[FireDAC][Phys][PG][libpq] ERROR:
fail'.
On the second run, I get a Violation Access error:
Project TFDConnectionDEMO.exe raised exception class $C0000005 with
message 'access violation at 0x00000000: read of address 0x00000000'.
Apparently the error occurs in the line below in unit FireDAC.Comp.Client
function TFDCustomConnection.ExecSQLScalar(const ASQL: String;
const AParams: array of Variant; const ATypes: array of TFieldType): Variant;
var
oCmd: IFDPhysCommand;
begin
oCmd := BaseCreateSQL;
try
if BasePrepareSQL(oCmd, ASQL, AParams, ATypes) or (FExecSQLTab = nil) then begin
FDFree(FExecSQLTab);
...
ignoring the previous error and trying again, another error is displayed...
Project TZConnectionDEMO.exe raised exception class EFDException with
message '[FireDAC][DatS]-24. Row is not nested'.
Searching, I found no response to this error. I figured my mistake would be to call the bank raise_exception function using the ExecSQLScalar function of the FDConnection component. So I tried using FDConnection.ExecSQL and as I imagined, you can not use this if there is a SELECT clause in the parameter.
Is there a better way to call function with void return using FDConnection.ExecSQL? would a BUG be in the component? or would not it be correct to make that kind of call?
Using ExecSQLScalar is fine in this case. This is certainly a bug (which was already fixed, at least in Delphi 10.2.3). As you've correctly pointed out, the problem is in releasing a table storage object instance held by the FExecSQLTab field by using FDFree procedure.
I don't have Delphi XE5 source code but maybe you can see something like this inside (comments about what happened are added by me):
if BasePrepareSQL(oCmd, ASQL, AParams, ATypes) or (FExecSQLTab = nil) then
begin
FDFree(FExecSQLTab); { ← directly calls destructor if object is not nil }
FExecSQLTab := oCmd.Define; { ← no assignment if command execution raises exception }
end;
Problem was that when a SQL command execution raised exception during storage table definition stage (oCmd.Define), reference to previously destroyed storage table object instance (by FDFree) remained stored in the FExecSQLTab field (as a dangling pointer).
Then when a different command was executed that way, FDFree procedure was called just for that dangling pointer. Hence the access violation.
Way to correct this is replacing line e.g. by:
FDFree(FExecSQLTab);
by:
FDFreeAndNil(FExecSQLTab);
which was done in some later Delphi release.

Resources