more test rig

This commit is contained in:
Richard Holland
2022-05-27 11:03:56 +00:00
parent 4ea852b819
commit e9e407bbf2
10 changed files with 594 additions and 10 deletions

View File

@@ -0,0 +1,83 @@
require('./utils-tests.js').TestRig('ws://localhost:6005').then(t=>
{
const account = t.randomAccount();
t.fundFromGenesis(account).then(()=>
{
t.feeSubmit(account.seed,
{
Account: account.classicAddress,
TransactionType: "SetHook",
Hooks: [
{
Hook: {
CreateCode: t.wasm('makestate.wasm'),
HookApiVersion: 0,
HookNamespace: "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
HookOn: "0000000000000000"
}
},
{ Hook: {
CreateCode: t.wasm('checkstate.wasm'),
HookApiVersion: 0,
HookNamespace: "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
HookOn: "0000000000000000"
}
},
{ Hook: {} },
{ Hook: {} }
]
}).then(x=>
{
t.assertTxnSuccess(x)
t.api.submit(
{
Account: account.classicAddress,
TransactionType: "AccountSet", // trigger hooks
Fee: "100000"
}, {wallet: account}).then(x=>
{
t.assertTxnSuccess(x)
console.log(x);
t.feeSubmit(account.seed,
{
Account: account.classicAddress,
TransactionType: "SetHook",
Hooks: [
{
Hook: {
CreateCode: t.wasm("rmstate.wasm"),
HookApiVersion: 0,
HookNamespace: "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
HookOn: "0000000000000000",
Flags: t.hsfOVERRIDE
},
},
{
Hook: {
Flags: t.hsfOVERRIDE,
CreateCode: ""
}
}
]
}).then(x=>
{
t.assertTxnSuccess(x)
t.api.submit(
{
Account: account.classicAddress,
TransactionType: "AccountSet", // trigger hooks
Fee: "100000"
}, {wallet: account}).then(x=>
{
t.assertTxnSuccess(x);
process.exit(0);
});
});
}).catch(t.err);
}).catch(t.err);
}).catch(t.err);
})

View File

@@ -0,0 +1,115 @@
require('./utils-tests.js').TestRig('ws://localhost:6005').then(t=>{
const holder1 = t.randomAccount();
const holder2 = t.randomAccount();
const holder3 = t.randomAccount();
const holder4 = t.randomAccount();
const issuer = t.randomAccount();
t.fundFromGenesis([issuer, holder1, holder2, holder3, holder4]).then(()=>
{
t.setTshCollect([holder1, holder2, holder3, holder4]).then(()=>
{
t.trustSet(issuer, "IOU", 10000, [holder1,holder2,holder3,holder4]).then(()=>
{
t.feeSubmitAcceptMultiple(
{
TransactionType: "SetHook",
Hooks: [
{
Hook:
{
CreateCode: t.wasm('aaw.wasm'),
HookApiVersion: 0,
HookNamespace: "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
HookOn: "0000000000000000",
Flags: t.hsfCOLLECT
}
}
]
}, [holder1,holder2,holder3,holder4]).then(()=>
{
req = {};
req[holder1.classicAddress] = 500;
req[holder2.classicAddress] = 200;
req[holder3.classicAddress] = 80;
t.issueTokens(issuer, "IOU", req).then(()=>
{
const coffer = (offerer, issuer, currency, iouamount, dropsamount, buying) =>
{
if (typeof(issuer.classicAddress) != 'undefined')
issuer = issuer.classicAddress;
return new Promise((resolve, reject) =>
{
let txn =
{
Account: offerer.classicAddress,
TransactionType: "OfferCreate",
};
let key1 = (buying ? "TakerGets" : "TakerPays");
let key2 = (buying ? "TakerPays" : "TakerGets");
txn[key1] = dropsamount + "";
txn[key2] = {
"currency": currency,
"issuer": issuer,
"value": iouamount + ""
};
t.feeSubmitAccept(offerer.seed, txn).then(x=>
{
console.log(x);
t.assertTxnSuccess(x);
resolve(x);
}).catch(e=>reject(e));
});
};
coffer(holder1, issuer, "IOU", 10, 250000, false).then(()=> // q= 25000
{
coffer(holder2, issuer, "IOU", 12, 100000, false).then(()=> // q= 8333
{
coffer(holder3, issuer, "IOU", 14, 80000, false).then(()=> // q= 5714
{
coffer(holder4, issuer, "IOU", 30, 350000, true).then((x)=>
{
t.ledgerAccept().then(()=>
{
t.fetchMetaHookExecutions(x).then(h=>
{
t.fetchMeta(x).then(m=>
{
t.log(x);
delete m.HookExecutions;
t.log(m);
t.log(h);
console.log("Issuer:", issuer.classicAddress);
console.log("Holder 1: ", holder1.classicAddress);
console.log("Holder 2: ", holder2.classicAddress);
console.log("Holder 3: ", holder3.classicAddress);
console.log("Buyer: ", holder4.classicAddress);
console.log("(cd b; ./rippled book_offers XRP 'IOU/" + issuer.classicAddress + "');");
console.log("(cd b; ./rippled account_lines " + issuer.classicAddress + ");");
process.exit(0);
}).catch(t.err);
}).catch(t.err);
}).catch(t.err);
}).catch(t.err);
}).catch(t.err);
}).catch(t.err);
}).catch(t.err);
}).catch(t.err);
}).catch(t.err);
}).catch(t.err);
}).catch(t.err);
}).catch(t.err);
})

View File

@@ -0,0 +1,55 @@
require('./utils-tests.js').TestRig('ws://localhost:6005').then(t=>{
const holder1 = t.randomAccount();
const issuer = t.randomAccount();
t.fundFromGenesis([issuer, holder1]).then(()=>
{
t.feeSubmitAccept(issuer.seed,
{
Account: issuer.classicAddress,
TransactionType: "SetHook",
Hooks: [
{
Hook:
{
CreateCode: t.wasm('aaw.wasm'),
HookApiVersion: 0,
HookNamespace: "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
HookOn: "0000000000000000",
Flags: t.hsfCOLLECT
}
}
]
}).then(x=>
{
t.assertTxnSuccess(x)
console.log(x);
t.feeSubmitAccept(holder1.seed,
{
Account: holder1.classicAddress,
TransactionType: "TrustSet",
LimitAmount: {
"currency": "IOU",
"issuer": issuer.classicAddress,
"value": "1000"
}
}).then(x=>
{
t.assertTxnSuccess(x)
console.log(x);
t.fetchMetaHookExecutions(x, t.wasmHash('aaw.wasm')).then(m=>
{
t.assert(m.length == 0, "hook executed when it should not");
console.log(m);
process.exit(0);
}).catch(t.err);
}).catch(t.err);
});
}).catch(t.err);
})

View File

@@ -0,0 +1,65 @@
require('./utils-tests.js').TestRig('ws://localhost:6005').then(t=>{
const holder1 = t.randomAccount();
const issuer = t.randomAccount();
t.fundFromGenesis([issuer, holder1]).then(()=>
{
t.feeSubmitAccept(issuer.seed,
{
Account: issuer.classicAddress,
TransactionType: "AccountSet",
SetFlag: t.asfTshCollect
}).then(x=>
{
t.assertTxnSuccess(x)
console.log(x);
t.feeSubmitAccept(issuer.seed,
{
Account: issuer.classicAddress,
TransactionType: "SetHook",
Hooks: [
{
Hook:
{
CreateCode: t.wasm('aaw.wasm'),
HookApiVersion: 0,
HookNamespace: "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
HookOn: "0000000000000000"
}
}
]
}).then(x=>
{
t.assertTxnSuccess(x);
console.log(x);
t.feeSubmitAccept(holder1.seed,
{
Account: holder1.classicAddress,
TransactionType: "TrustSet",
LimitAmount: {
"currency": "IOU",
"issuer": issuer.classicAddress,
"value": "1000"
}
}).then(x=>
{
t.assertTxnSuccess(x)
console.log(x);
t.fetchMetaHookExecutions(x, t.wasmHash('aaw.wasm')).then(m=>
{
console.log(m);
t.assert(m.length == 0, "hook executed when it should not");
process.exit(0);
});
}).catch(t.err);
}).catch(t.err);
});
}).catch(t.err);
})

View File

@@ -52,7 +52,7 @@ require('./utils-tests.js').TestRig('ws://localhost:6005').then(t=>{
console.log(x);
t.fetchMetaHookExecutions(x, t.wasmHash('aaw.wasm')).then(m=>
{
t.assert(m.length == 1, "more than one execution");
t.assert(m.length == 1, "needed exactly one hook execution");
t.assert(m[0].HookReturnCode == 100, "non-weak execution");
console.log(m);
process.exit(0);

View File

@@ -96,7 +96,9 @@ module.exports = {
if (typeof(m) == 'undefined' ||
typeof(m.HookExecutions) == 'undefined' ||
typeof(m.HookExecutions.length) == 'undefined')
reject(m);
{
return resolve([])
}
let ret = [];
@@ -109,6 +111,11 @@ module.exports = {
m.HookExecutions[i].HookExecution.HookInstructionCount =
parseInt(m.HookExecutions[i].HookExecution.HookInstructionCount, 16);
let s = m.HookExecutions[i].HookExecution.HookReturnString;
if (s != '')
m.HookExecutions[i].HookExecution.HookReturnString =
Buffer.from(s, 'hex').toString('utf-8')
ret.push(m.HookExecutions[i].HookExecution);
}
@@ -334,6 +341,138 @@ module.exports = {
});
};
const trustSet = (issuer, currency, limit, holders) =>
{
if (typeof(issuer.classicAddress) != 'undefined')
issuer = issuer.classicAddress;
return new Promise((resolve, reject)=>
{
const doTs = (holder) =>
{
if (holder.length == 0)
return resolve();
let h = holder.shift();
feeSubmitAccept(h.seed,
{
Account: h.classicAddress,
TransactionType: "TrustSet",
LimitAmount: {
"currency": currency + "",
"issuer": issuer,
"value": limit + ""
}
}).then(x=>
{
console.log(x)
assertTxnSuccess(x);
return doTs(holder);
}).catch(e=>reject(e));
};
doTs(holders);
});
};
const issueTokens = (issuer, currency, toWhom) =>
{
return new Promise((resolve, reject) =>
{
const itf = (issuer, currency, toWhom) =>
{
let c = 0;
for (let next in toWhom)
{
c++;
let addr = next;
let amt = toWhom[addr];
delete toWhom[addr];
let txn =
{
Account: issuer.classicAddress,
TransactionType: "Payment",
Amount: {
"currency": currency,
"value": amt + "",
"issuer": issuer.classicAddress
},
Destination: addr
};
feeSubmitAccept(issuer.seed, txn).then(x=>
{
console.log(x);
assertTxnSuccess(x);
return itf(issuer, currency, toWhom);
}).catch(e=>reject(e));
break;
}
if (c == 0)
resolve();
};
return itf(issuer, currency, toWhom);
});
};
const setTshCollect = (accounts) =>
{
return new Promise((resolve, reject) =>
{
const stc = (accounts) =>
{
if (accounts.length == 0)
return resolve();
let acc = accounts.shift();
feeSubmitAccept(acc.seed,
{
Account: acc.classicAddress,
TransactionType: "AccountSet",
SetFlag: 11
}).then(x=>
{
console.log(x);
assertTxnSuccess(x);
return stc(accounts);
}).catch(e=>reject(e));
};
stc(accounts);
});
}
const feeSubmitAcceptMultiple = (txn, accounts) =>
{
return new Promise((resolve, reject) =>
{
const stc = (accounts) =>
{
if (accounts.length == 0)
return resolve();
let acc = accounts.shift();
let txn_to_submit = { ... txn };
txn_to_submit['Account'] = acc.classicAddress;
feeSubmitAccept(acc.seed, txn_to_submit).then(x=>
{
console.log(x);
assertTxnSuccess(x);
return stc(accounts);
}).catch(e=>reject(e));
};
stc(accounts);
});
}
const log = m =>
{
// console.log(JSON.stringify(m, null, 4));
console.dir(m, {depth:null});
}
api.connect().then(()=>
{
resolve({
@@ -365,7 +504,13 @@ module.exports = {
fetchMeta: fetchMeta,
fetchMetaHookExecutions: fetchMetaHookExecutions,
wasmHash: wasmHash,
assert: assert
assert: assert,
trustSet: trustSet,
issueTokens: issueTokens,
log: log,
setTshCollect: setTshCollect,
feeSubmitAcceptMultiple: feeSubmitAcceptMultiple
});
}).catch(err);
});

View File

@@ -0,0 +1,52 @@
// RC: 50 : strong execution
// RC: 100 : weak execution (collect call)
// RC: 150 : again as weak (not collect / after strong)
// RC: 200 : callback execution
#include <stdint.h>
extern int32_t _g (uint32_t id, uint32_t maxiter);
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t hook_again (void);
extern int64_t trace( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
extern int64_t trace_num (uint32_t, uint32_t, uint64_t);
extern int64_t meta_slot(uint32_t);
extern int64_t slot(uint32_t, uint32_t, uint32_t);
#define SBUF(x) (uint32_t)((void*)x), sizeof(x)
int64_t cbak(uint32_t what)
{
accept (SBUF("Callback execution"),200);
}
int64_t hook(uint32_t reserved )
{
if (reserved == 0)
{
hook_again();
accept (SBUF("Strong execution"),50);
}
int64_t result =
meta_slot(1);
trace_num(SBUF("meta_slot(1): "), result);
uint8_t dump[1024];
result = slot(SBUF(dump), 1);
trace_num(SBUF("slot(1): "), result);
trace(SBUF("dumped txmeta:"), dump, result, 1);
if (reserved == 1)
accept(SBUF("Weak execution (COLLECT)"), 100);
else
accept(SBUF("AAW execution"), 150);
_g(1,1); // every hook needs to import guard function and use it at least once
// unreachable
return 0;
}

View File

@@ -1,19 +1,22 @@
all: accept.wasm makestate.wasm makestate2.wasm checkstate.wasm rollback.wasm aaw.wasm
all: accept.wasm makestate.wasm makestate2.wasm checkstate.wasm rollback.wasm aaw.wasm rmstate.wasm
accept.wasm: accept.c
wasmcc accept.c -o accept.wasm -O0 -Wl,--allow-undefined -I../
/root/hook-cleaner-c/cleaner accept.wasm
hook-cleaner accept.wasm
rollback.wasm: rollback.c
wasmcc rollback.c -o rollback.wasm -O0 -Wl,--allow-undefined -I../
/root/hook-cleaner-c/cleaner rollback.wasm
hook-cleaner rollback.wasm
makestate.wasm: makestate.c
wasmcc makestate.c -o makestate.wasm -O0 -Wl,--allow-undefined -I../
/root/hook-cleaner-c/cleaner makestate.wasm
hook-cleaner makestate.wasm
makestate2.wasm: makestate2.c
wasmcc makestate2.c -o makestate2.wasm -O0 -Wl,--allow-undefined -I../
/root/hook-cleaner-c/cleaner makestate2.wasm
hook-cleaner makestate2.wasm
checkstate.wasm: checkstate.c
wasmcc checkstate.c -o checkstate.wasm -O0 -Wl,--allow-undefined -I../
/root/hook-cleaner-c/cleaner checkstate.wasm
hook-cleaner checkstate.wasm
rmstate.wasm: rmstate.c
wasmcc rmstate.c -o rmstate.wasm -O0 -Wl,--allow-undefined -I../
hook-cleaner rmstate.wasm
aaw.wasm: aaw.c
wasmcc aaw.c -o aaw.wasm -O0 -Wl,--allow-undefined -I../
/root/hook-cleaner-c/cleaner aaw.wasm
hook-cleaner aaw.wasm

View File

@@ -0,0 +1,37 @@
#include <stdint.h>
extern int32_t _g (uint32_t id, uint32_t maxiter);
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t state_set (uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len);
extern int64_t trace_num (uint32_t a, uint32_t b, uint64_t i);
#define SBUF(x) x, sizeof(x)
#define GUARD(n) _g(__LINE__, n+1)
int64_t cbak(uint32_t what)
{
return 0;
}
int64_t hook(uint32_t reserved )
{
uint8_t test[] = "hello world!";
uint8_t test2[] = "this is a much longer test string";
trace_num(SBUF("location of test[]:"), test);
uint8_t test_key[32];
for (int i = 0; GUARD(32), i < 32; ++i)
test_key[i] = i;
int64_t result = state_set(SBUF(test), SBUF(test_key));
trace_num(SBUF("state_set result:"), result);
uint8_t zero_key[32];
result = state_set(SBUF(test2), SBUF(zero_key));
trace_num(SBUF("state_set result:"), result);
accept (0,0,0);
_g(1,1); // every hook needs to import guard function and use it at least once
// unreachable
return 0;
}

View File

@@ -0,0 +1,29 @@
#include <stdint.h>
extern int32_t _g (uint32_t id, uint32_t maxiter);
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t state_set (uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len);
extern int64_t trace_num (uint32_t a, uint32_t b, uint64_t i);
#define SBUF(x) x, sizeof(x)
#define GUARD(n) _g(__LINE__, n+1)
int64_t cbak(uint32_t what)
{
return 0;
}
int64_t hook(uint32_t reserved )
{
uint8_t test_key[32];
for (int i = 0; GUARD(32), i < 32; ++i)
test_key[i] = i;
int64_t result = state_set(0,0, SBUF(test_key));
trace_num(SBUF("state_set result:"), result);
accept (0,0,0);
_g(1,1); // every hook needs to import guard function and use it at least once
// unreachable
return 0;
}