Skip to content
This repository has been archived by the owner on Sep 7, 2023. It is now read-only.

(feature) Default init does not have any parameters #558

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/helloworldstate/logic.ergo
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ contract HelloWorldState over TemplateModel state State {
}
}

clause init(request : MyRequest) : Unit {
clause init() : Unit {
set state State{
counter: 0.0
};
Expand Down
2 changes: 1 addition & 1 deletion examples/initfailtest/logic.ergo
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace org.accordproject.initfailtest

contract InitFailTest over TemplateModel state State {
clause init(request : Request) : Response {
clause init() : Response {
enforce false;
set state State {};
return Response{
Expand Down
4 changes: 2 additions & 2 deletions examples/installment-sale/logic.ergo
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace org.accordproject.installmentsale
import org.accordproject.cicero.runtime.*

contract InstallmentSale over TemplateModel state InstallmentSaleState {
clause init(request : Request) : Response {
clause init() : Response {
set state InstallmentSaleState{
status: "WaitingForFirstDayOfNextMonth",
balance_remaining: contract.INITIAL_DUE,
Expand All @@ -27,7 +27,7 @@ import org.accordproject.cicero.runtime.*
return Response{}
}

clause PayInstallment(request : Installment) : Balance emits PaymentObligation {
clause PayInstallment(request : Installment) : Balance {
// enforce (state.status = "WaitingForFirstDayOfNextMonth"); // Make sure this is only called in the right state
// enforce (contract.MIN_PAYMENT <= state.balance_remaining) and (state.next_payment_month < 23);
// enforce (contract.MIN_PAYMENT <= request.amount); // Underpaying is forbidden
Expand Down
2 changes: 1 addition & 1 deletion examples/installment-sale/logic2.ergo
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
namespace org.accordproject.installmentsale

contract InstallmentSale over TemplateModel state InstallmentSaleState {
clause init(request : InitializeRequest) : InitializeResponse {
clause init() : InitializeResponse {
enforce(request.firstMonth = 3.0)
else throw ErgoErrorResponse{ message: "Month should be initialized to 3.0" };
set state InstallmentSaleState{
Expand Down
2 changes: 1 addition & 1 deletion examples/typechecked/repl_helloworld.ergo
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ contract HelloWorld over HelloWorldClause {
}

set contract HelloWorld over HelloWorldClause{ clauseId : "cl1", name : "Fred Blogs" }
call init(Request{})
call init()
call helloworld(MyRequest{ input : "AccordProject" });call helloworld(MyRequest{ input : "AccordProject" })
4 changes: 2 additions & 2 deletions examples/typechecked/repl_installmentsale.ergo
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ define asset InstallmentSaleContract extends AccordContract {
}

contract InstallmentSale over InstallmentSaleContract state InstallmentSaleState {
clause init(request:Request) : Unit {
clause init() : Unit {
set state InstallmentSaleState{
stateId: "org.accordproject.installmentsale.InstallmentSaleState#1",
status: "WaitingForFirstDayOfNextMonth",
Expand Down Expand Up @@ -105,7 +105,7 @@ set contract InstallmentSale over InstallmentSaleContract{
MIN_PAYMENT : 500.0,
DUE_AT_CLOSING : 500.0
}
call init(Request{})
call init()
call payInstallment(Installment{ amount: 2000.00 })
call payInstallment(Installment{ amount: 2000.00 })
call payInstallment(Installment{ amount: 2000.00 })
Expand Down
2 changes: 1 addition & 1 deletion examples/typechecked/repl_one-time-payment.ergo
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ define asset OneTimePaymentContract extends AccordContract {
}

contract OneTimePayment over OneTimePaymentContract state OneTimePaymentState {
clause init(request : InitRequest) : InitResponse emits PaymentObligation {
clause init() : InitResponse emits PaymentObligation {
emit PaymentObligation{
contract: contract,
promisor: some(contract.buyer),
Expand Down
2 changes: 1 addition & 1 deletion examples/typechecked/repl_promissory-note.ergo
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,6 @@ set contract PromissoryNote over PromissoryNoteContract{
insolvencyDays: 90,
jurisdiction: "New York, NY"
}
call init(Request{})
call init()
call check(Payment{ amountPaid : MonetaryAmount{ doubleValue : 100.0, currencyCode: "USD" } })

14 changes: 7 additions & 7 deletions examples/typechecked/repl_studentloan.ergo
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ contract StudentLoan over LoanModel state LoanState
balance: add_monthly_interest(state.balance, contract.rate)
};
if req.amount <= 0.0 then
emit LoanDefaultEvent {};
return Response {}
emit LoanDefaultEvent {};
return Response {}
else if req.amount >= state.balance then
set state LoanState {balance: 0.0};
emit LoanPaidOffEvent {};
return Response {}
set state LoanState {balance: 0.0};
emit LoanPaidOffEvent {};
return Response {}
else
set state LoanState {balance: state.balance - req.amount};
return Response {}
set state LoanState {balance: state.balance - req.amount};
return Response {}
}
}

Expand Down
2 changes: 1 addition & 1 deletion examples/typechecked/repl_volumediscount.ergo
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ set contract VolumeDiscount over VolumeDiscountContract{
secondRate: 2.9,
thirdRate: 2.8
}
call init(Request{})
call init()
call volumediscount(VolumeDiscountRequest{ netAnnualChargeVolume : 0.4 })

2 changes: 1 addition & 1 deletion mechanization/ErgoC/Lang/ErgoCExpand.v
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ Section ErgoCExpand.
(c:ergoc_contract) : local_name * ergoc_function :=
let template := c.(contractc_template) in
let state := c.(contractc_state) in
let params := (("request"%string, ErgoTypeClassRef prov default_request_absolute_name)::nil) in
let params := nil in
let init_body :=
setState prov (default_state prov)
(EReturn prov (EConst prov dunit))
Expand Down
66 changes: 53 additions & 13 deletions mechanization/Translation/ErgoNNRCtoCicero.v
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ Section ErgoNNRCtoCicero.
+++ `" * @param {" +++ `state_type +++ `"} context.state - the state" +++ eol
+++ `" */" +++ eol.

(** Note: this adjusts the external interface to that currently expected in Cicero. Namely:
(** Note: this adjusts the external interface to what is currently expected by Cicero. Namely:
- This serialized/deserialized ErgoType objects to/from JSON
- This applies the result from the functional call to the call as effects to the input context
- This turns an error response into a JavaScript exception
*)
Definition wrapper_function
Definition wrapper_function_for_clause
(generated:bool)
(fun_name:string)
(request_param:string)
Expand All @@ -67,13 +67,7 @@ Section ErgoNNRCtoCicero.
(clause_name:string)
(eol:estring)
(quotel:estring) : estring :=
let state_init :=
if string_dec clause_name clause_init_name
then
`"{ '$class': 'org.accordproject.cicero.contract.AccordContractState', 'stateId' : 'org.accordproject.cicero.contract.AccordContractState#1' }"
else
`"serializer.toJSON(context.state,{permitResourcesForRelationships:true})"
in
let state_init := `"serializer.toJSON(context.state,{permitResourcesForRelationships:true})" in
(accord_annotation
generated
clause_name
Expand Down Expand Up @@ -105,6 +99,49 @@ Section ErgoNNRCtoCicero.
+++ `" }" +++ eol
+++ `"}" +++ eol.

Definition wrapper_function_for_init
(generated:bool)
(fun_name:string)
(response_type:string)
(emit_type:string)
(state_type:string)
(contract_name:string)
(eol:estring)
(quotel:estring) : estring :=
let state_init := `"{ '$class': 'org.accordproject.cicero.contract.AccordContractState', 'stateId' : 'org.accordproject.cicero.contract.AccordContractState#1' }" in
let request_type := "org.accordproject.cicero.runtime.Request" in
let clause_name := "init" in
(accord_annotation
generated
clause_name
request_type
response_type
emit_type
state_type
eol
quotel)
+++ `"function " +++ `fun_name +++ `"(context) {" +++ eol
+++ `" let pcontext = { 'state': " +++ state_init +++ `", 'contract': serializer.toJSON(context.contract,{permitResourcesForRelationships:true}), 'emit': context.emit, 'now': context.now};" +++ eol
+++ `" //logger.info('ergo context: '+JSON.stringify(pcontext))" +++ eol
+++ `" let result = new " +++ `ErgoCodeGen.javascript_identifier_sanitizer contract_name +++ `"()." +++ `ErgoCodeGen.javascript_identifier_sanitizer clause_name +++ `"(pcontext);" +++ eol
+++ `" if (result.hasOwnProperty('left')) {" +++ eol
+++ `" //logger.info('ergo result: '+JSON.stringify(result))" +++ eol
+++ `" context.response = result.left.response ?" +++ eol
+++ `" serializer.fromJSON(result.left.response, {validate: false, acceptResourcesForRelationships: true},{permitResourcesForRelationships:true})" +++ eol
+++ `" : serializer.fromJSON({ '$class': 'org.accordproject.cicero.runtime.Response' });" +++ eol
+++ `" context.state = serializer.fromJSON(result.left.state, {validate: false, acceptResourcesForRelationships: true});" +++ eol
+++ `" let emitResult = [];" +++ eol
+++ `" for (let i = 0; i < result.left.emit.length; i++) {" +++ eol
+++ `" emitResult.push(serializer.fromJSON(result.left.emit[i], {validate: false, acceptResourcesForRelationships: true}));" +++ eol
+++ `" }" +++ eol
+++ `" context.emit = emitResult;" +++ eol
+++ `" return context;" +++ eol
+++ `" } else {" +++ eol
+++ `" //logger.error('ergo error: '+JSON.stringify(result.right))" +++ eol
+++ `" ciceroError(result);" +++ eol
+++ `" }" +++ eol
+++ `"}" +++ eol.

Definition apply_wrapper_function
(contract_name:string)
(contract_state_type:string)
Expand All @@ -115,8 +152,11 @@ Section ErgoNNRCtoCicero.
let fun_name : string :=
ErgoCodeGen.javascript_identifier_sanitizer contract_name ++ "_"%string ++ ErgoCodeGen.javascript_identifier_sanitizer clause_name
in
wrapper_function false
fun_name request_name request_type response_type emit_type contract_state_type contract_name clause_name eol quotel.
if string_dec clause_name clause_init_name
then `""
else
wrapper_function_for_clause false
fun_name request_name request_type response_type emit_type contract_state_type contract_name clause_name eol quotel.

Definition wrapper_functions
(contract_name:string)
Expand All @@ -136,8 +176,8 @@ Section ErgoNNRCtoCicero.
(eol:estring)
(quotel:estring) : ErgoCodeGen.ejavascript :=
`"" +++ `"const contract = new " +++ `ErgoCodeGen.javascript_identifier_sanitizer contract_name +++ `"();" +++ eol
+++ wrapper_function true "__dispatch" "request" "org.accordproject.cicero.runtime.Request" "org.accordproject.cicero.runtime.Response" "org.accordproject.cicero.runtime.Emit" "org.accordproject.cicero.runtime.State" contract_name clause_main_name eol quotel
+++ wrapper_function true "__init" "request" "org.accordproject.cicero.runtime.Request" "org.accordproject.cicero.runtime.Response" "org.accordproject.cicero.runtime.Emit" "org.accordproject.cicero.runtime.State" contract_name clause_init_name eol quotel.
+++ wrapper_function_for_clause true "__dispatch" "request" "org.accordproject.cicero.runtime.Request" "org.accordproject.cicero.runtime.Response" "org.accordproject.cicero.runtime.Emit" "org.accordproject.cicero.runtime.State" contract_name clause_main_name eol quotel
+++ wrapper_function_for_init true "__init" "org.accordproject.cicero.runtime.Response" "org.accordproject.cicero.runtime.Emit" "org.accordproject.cicero.runtime.State" contract_name eol quotel.

Definition javascript_of_module_with_dispatch
(contract_name:string)
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions packages/ergo-cli/lib/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,15 @@ class Commands {
for (let i = 0; i < requestsPath.length; i++) {
requestsJson.push(JSON.parse(Fs.readFileSync(requestsPath[i], 'utf8')));
}
const firstRequest = requestsJson[0];
let initResponse;
if (statePath === null) {
initResponse = ErgoEngine.init(ergoSources,ctoSources,'es6',contractJson,firstRequest,contractName,currentTime);
initResponse = ErgoEngine.init(ergoSources,ctoSources,'es6',contractJson,contractName,currentTime);
} else {
const stateJson = JSON.parse(Fs.readFileSync(statePath, 'utf8'));
initResponse = ErgoEngine.execute(ergoSources,ctoSources,'es6',contractJson,firstRequest,stateJson,contractName,currentTime);
initResponse = Promise.resolve({ state: stateJson });
}
// Get all the other requests and chain execution through Promise.reduce()
const otherRequests = requestsJson.slice(1, requestsJson.length);
return otherRequests.reduce((promise,requestJson) => {
return requestsJson.reduce((promise,requestJson) => {
return promise.then((result) => {
return ErgoEngine.execute(ergoSources,ctoSources,'es6',contractJson,requestJson,result.state,contractName,currentTime);
});
Expand Down
9,628 changes: 4,813 additions & 4,815 deletions packages/ergo-cli/lib/ergoc-lib.js

Large diffs are not rendered by default.

3,760 changes: 1,880 additions & 1,880 deletions packages/ergo-cli/lib/ergotop-lib.js

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions packages/ergo-cli/test/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,15 @@ describe('ergo', () => {
const ergoPath = Path.resolve(__dirname, 'data/installment-sale', 'logic.ergo');
const ctoPath = Path.resolve(__dirname, 'data/installment-sale', 'model.cto');
const contractPath = Path.resolve(__dirname, 'data/installment-sale', 'contract.json');
const requestInitPath = Path.resolve(__dirname, 'data/installment-sale', 'request-init.json');
const result = await Commands.execute([ergoPath], [ctoPath], contractPath, [requestInitPath], null, 'org.accordproject.installmentsale.InstallmentSale', '1970-01-01T00:00:00Z');
const result = await Commands.execute([ergoPath], [ctoPath], contractPath, [], null, 'org.accordproject.installmentsale.InstallmentSale', '1970-01-01T00:00:00Z');
result.state.balance_remaining.should.equal(10000.00);
});
it('should initialize a smart Ergo contract and execute one request', async function () {
const ergoPath = Path.resolve(__dirname, 'data/installment-sale', 'logic.ergo');
const ctoPath = Path.resolve(__dirname, 'data/installment-sale', 'model.cto');
const contractPath = Path.resolve(__dirname, 'data/installment-sale', 'contract.json');
const requestInitPath = Path.resolve(__dirname, 'data/installment-sale', 'request-init.json');
const requestPath = Path.resolve(__dirname, 'data/installment-sale', 'request.json');
const result = await Commands.execute([ergoPath], [ctoPath], contractPath, [requestInitPath,requestPath], null, 'org.accordproject.installmentsale.InstallmentSale', '1970-01-01T00:00:00Z');
const result = await Commands.execute([ergoPath], [ctoPath], contractPath, [requestPath], null, 'org.accordproject.installmentsale.InstallmentSale', '1970-01-01T00:00:00Z');
result.state.balance_remaining.should.equal(7612.499999999999);
});
});
Expand Down
9,338 changes: 4,668 additions & 4,670 deletions packages/ergo-compiler/lib/ergo-core.js

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions packages/ergo-engine/lib/cucumber-steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function compare(expected,actual) {
* @param {object} contractJson contract data in JSON
* @returns {object} Promise to the initial state of the contract
*/
function init(rootdir, target,ergo,models,contractName,currentTime,contractJson) {
function init(rootdir,target,ergo,models,contractName,currentTime,contractJson) {
const ergoSources = [];
for (let i = 0; i < ergo.length; i++) {
const ergoFile = Path.resolve(rootdir, ergo[i]);
Expand All @@ -83,8 +83,7 @@ function init(rootdir, target,ergo,models,contractName,currentTime,contractJson)
const ctoContent = Fs.readFileSync(ctoFile, 'utf8');
ctoSources.push({ 'name': ctoFile, 'content': ctoContent });
}
const requestJson = { '$class' : 'org.accordproject.cicero.runtime.Request' };
return ErgoEngine.init(ergoSources, ctoSources, target, contractJson, requestJson, contractName, currentTime);
return ErgoEngine.init(ergoSources, ctoSources, target, contractJson, contractName, currentTime);
}

/**
Expand Down
10 changes: 4 additions & 6 deletions packages/ergo-engine/lib/ergo-engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,11 @@ class ErgoEngine {
* @param {string} ergoCode JavaScript code for ergo logic
* @param {string} codeKind either 'es6' or 'es5'
* @param {object} contractJson the contract data in JSON
* @param {object} requestJson the request transaction in JSON
* @param {string} contractName of the contract to initialize
* @param {string} currentTime the definition of 'now'
* @returns {object} Promise to the result of initialization
*/
static initErgoCode(ergoCode,codeKind,contractJson,requestJson,contractName,currentTime) {
static initErgoCode(ergoCode,codeKind,contractJson,contractName,currentTime) {
const now = this.initCurrentTime(currentTime);
const vm = new VM({
timeout: 1000,
Expand All @@ -114,7 +113,7 @@ class ErgoEngine {
});

// add immutables to the context
const params = { 'contract': contractJson, 'request': requestJson, 'state': {}, 'emit': [], 'now': now };
const params = { 'contract': contractJson, 'state': {}, 'emit': [], 'now': now };
vm.freeze(params, 'params'); // Add the context
vm.run(ergoCode); // Load the generated logic
let contract;
Expand Down Expand Up @@ -164,17 +163,16 @@ class ErgoEngine {
* @param {Array<{name:string, content:string}>} ctoSources CTO models
* @param {string} codeKind either 'es6' or 'es5'
* @param {object} contractJson the contract data in JSON
* @param {object} requestJson the request transaction in JSON
* @param {string} contractName of the contract to execute
* @param {string} currentTime the definition of 'now'
* @returns {object} Promise to the result of execution
*/
static init(ergoSources,ctoSources,codeKind,contractJson,requestJson,contractName,currentTime) {
static init(ergoSources,ctoSources,codeKind,contractJson,contractName,currentTime) {
return (Ergo.compile(ergoSources,ctoSources,codeKind,true)).then((ergoCode) => {
if (ergoCode.hasOwnProperty('error')) {
return ergoCode;
} else {
return this.initErgoCode(ergoCode.success,codeKind,contractJson,requestJson,contractName,currentTime);
return this.initErgoCode(ergoCode.success,codeKind,contractJson,contractName,currentTime);
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions packages/ergo-engine/test/ergo-engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ describe('Execute ES6', () => {
const contractJson = JSON.parse(Fs.readFileSync(Path.resolve(__dirname, dir, contract), 'utf8'));
const requestJson = JSON.parse(Fs.readFileSync(Path.resolve(__dirname, dir, request), 'utf8'));
if (state === null) {
const actual = await ErgoEngine.init(ergoSources, ctoSources, 'es6', contractJson, requestJson, contractName, currentTime);
const actual = await ErgoEngine.init(ergoSources, ctoSources, 'es6', contractJson, contractName, currentTime);
return compare(expected,actual);
} else {
const stateJson = JSON.parse(Fs.readFileSync(Path.resolve(__dirname, dir, state), 'utf8'));
Expand Down Expand Up @@ -154,7 +154,7 @@ describe('Execute ES5', () => {
const contractJson = JSON.parse(Fs.readFileSync(Path.resolve(__dirname, dir, contract), 'utf8'));
const requestJson = JSON.parse(Fs.readFileSync(Path.resolve(__dirname, dir, request), 'utf8'));
if (state === null) {
const actual = await ErgoEngine.init(ergoSources, ctoSources, 'es5', contractJson, requestJson, contractName, currentTime);
const actual = await ErgoEngine.init(ergoSources,ctoSources,'es5',contractJson,contractName,currentTime);
return compare(expected,actual);
} else {
const stateJson = JSON.parse(Fs.readFileSync(Path.resolve(__dirname, dir, state), 'utf8'));
Expand Down