Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
25c6bcd9
Y
YTBP
项目概览
YottaChain
/
YTBP
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Y
YTBP
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
25c6bcd9
编写于
2月 05, 2018
作者:
W
wanderingbort
提交者:
GitHub
2月 05, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1287 from EOSIO/more_eosio_wasm_constraints
Add more constraints on WASM execution environment
上级
2e65e6c9
5ac26aca
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
371 addition
and
9 deletion
+371
-9
libraries/chain/CMakeLists.txt
libraries/chain/CMakeLists.txt
+1
-0
libraries/chain/include/eosio/chain/wasm_eosio_constraints.hpp
...ries/chain/include/eosio/chain/wasm_eosio_constraints.hpp
+12
-0
libraries/chain/wasm_eosio_constraints.cpp
libraries/chain/wasm_eosio_constraints.cpp
+112
-0
libraries/chain/wasm_interface.cpp
libraries/chain/wasm_interface.cpp
+2
-0
libraries/wasm-jit/Source/WASM/WASMSerialization.cpp
libraries/wasm-jit/Source/WASM/WASMSerialization.cpp
+0
-7
tests/wasm_tests/test_wasts.hpp
tests/wasm_tests/test_wasts.hpp
+75
-1
tests/wasm_tests/wasm_tests.cpp
tests/wasm_tests/wasm_tests.cpp
+169
-1
未找到文件。
libraries/chain/CMakeLists.txt
浏览文件 @
25c6bcd9
...
@@ -9,6 +9,7 @@ add_library( eosio_chain
...
@@ -9,6 +9,7 @@ add_library( eosio_chain
block.cpp
block.cpp
wast_to_wasm.cpp
wast_to_wasm.cpp
wasm_interface.cpp
wasm_interface.cpp
wasm_eosio_constraints.cpp
apply_context.cpp
apply_context.cpp
rate_limiting.cpp
rate_limiting.cpp
...
...
libraries/chain/include/eosio/chain/wasm_eosio_constraints.hpp
0 → 100644
浏览文件 @
25c6bcd9
#pragma once
namespace
IR
{
struct
Module
;
};
namespace
eosio
{
namespace
chain
{
//Throws if something in the module violates
void
validate_eosio_wasm_constraints
(
const
IR
::
Module
&
m
);
}}
libraries/chain/wasm_eosio_constraints.cpp
0 → 100644
浏览文件 @
25c6bcd9
#include <eosio/chain/wasm_eosio_constraints.hpp>
#include <fc/exception/exception.hpp>
#include <eosio/chain/exceptions.hpp>
#include "IR/Module.h"
#include "IR/Operators.h"
namespace
eosio
{
namespace
chain
{
using
namespace
IR
;
struct
nop_opcode_visitor
{
typedef
void
Result
;
#define VISIT_OPCODE(opcode,name,nameString,Imm,...) \
virtual void name(Imm) {}
ENUM_OPERATORS
(
VISIT_OPCODE
)
#undef VISIT_OPCODE
void
unknown
(
Opcode
)
{
FC_THROW_EXCEPTION
(
wasm_execution_error
,
"Smart contract encountered unknown opcode"
);
}
};
struct
eosio_constraints_visitor
:
public
nop_opcode_visitor
{
///Make this some sort of visitor enum to reduce chance of copy pasta errors (but
// the override declaration makes it somewhat safe)
//While it's possible to access beyond 1MiB by giving an offset that's 1MiB-1 and
// an 8 byte data type, that's fine. There will be enough of a guard on the end
// of 1MiB where it's not a problem
void
fail_large_offset
(
U32
offset
)
{
if
(
offset
>=
1024
*
1024
)
FC_THROW_EXCEPTION
(
wasm_execution_error
,
"Smart contract used an invalid large memory store/load offset"
);
}
void
i32_load
(
LoadOrStoreImm
<
2
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i64_load
(
LoadOrStoreImm
<
3
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i32_load8_s
(
LoadOrStoreImm
<
0
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i32_load8_u
(
LoadOrStoreImm
<
0
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i32_load16_s
(
LoadOrStoreImm
<
1
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i32_load16_u
(
LoadOrStoreImm
<
1
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i64_load8_s
(
LoadOrStoreImm
<
0
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i64_load8_u
(
LoadOrStoreImm
<
0
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i64_load16_s
(
LoadOrStoreImm
<
1
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i64_load16_u
(
LoadOrStoreImm
<
1
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i64_load32_s
(
LoadOrStoreImm
<
2
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i64_load32_u
(
LoadOrStoreImm
<
2
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i32_store
(
LoadOrStoreImm
<
2
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i64_store
(
LoadOrStoreImm
<
3
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i32_store8
(
LoadOrStoreImm
<
0
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i32_store16
(
LoadOrStoreImm
<
1
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i64_store8
(
LoadOrStoreImm
<
0
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i64_store16
(
LoadOrStoreImm
<
1
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
i64_store32
(
LoadOrStoreImm
<
2
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
f32_load
(
LoadOrStoreImm
<
2
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
f64_load
(
LoadOrStoreImm
<
3
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
f32_store
(
LoadOrStoreImm
<
2
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
void
f64_store
(
LoadOrStoreImm
<
3
>
imm
)
override
{
fail_large_offset
(
imm
.
offset
);
}
#define VISIT_OPCODE(opcode,name,nameString,Imm,...) \
void name(Imm) override { FC_THROW_EXCEPTION(wasm_execution_error, "Smart contracts may not use WASM memory operators"); }
ENUM_MEMORY_OPERATORS
(
VISIT_OPCODE
);
#undef VISIT_OPCODE
};
void
validate_eosio_wasm_constraints
(
const
Module
&
m
)
{
if
(
m
.
memories
.
defs
.
size
()
&&
m
.
memories
.
defs
[
0
].
type
.
size
.
min
>
16
)
FC_THROW_EXCEPTION
(
wasm_execution_error
,
"Smart contract initial memory size must be less than or equal to 1MiB"
);
for
(
const
DataSegment
&
ds
:
m
.
dataSegments
)
{
if
(
ds
.
baseOffset
.
type
!=
InitializerExpression
::
Type
::
i32_const
)
FC_THROW_EXCEPTION
(
wasm_execution_error
,
"Smart contract has unexpected memory base offset type"
);
if
(
static_cast
<
uint32_t
>
(
ds
.
baseOffset
.
i32
)
+
ds
.
data
.
size
()
>
64
*
1024
)
FC_THROW_EXCEPTION
(
wasm_execution_error
,
"Smart contract data segments must lie in first 64KiB"
);
}
if
(
m
.
tables
.
defs
.
size
()
&&
m
.
tables
.
defs
[
0
].
type
.
size
.
min
>
1024
)
FC_THROW_EXCEPTION
(
wasm_execution_error
,
"Smart contract table limited to 1024 elements"
);
unsigned
mutable_globals_total_size
=
0
;
for
(
const
GlobalDef
&
global_def
:
m
.
globals
.
defs
)
{
if
(
!
global_def
.
type
.
isMutable
)
continue
;
switch
(
global_def
.
type
.
valueType
)
{
case
ValueType
::
any
:
case
ValueType
::
num
:
FC_THROW_EXCEPTION
(
wasm_execution_error
,
"Smart contract has unexpected global definition value type"
);
case
ValueType
::
i64
:
case
ValueType
::
f64
:
mutable_globals_total_size
+=
4
;
case
ValueType
::
i32
:
case
ValueType
::
f32
:
mutable_globals_total_size
+=
4
;
}
}
if
(
mutable_globals_total_size
>
1024
)
FC_THROW_EXCEPTION
(
wasm_execution_error
,
"Smart contract has more than 1KiB of mutable globals"
);
//Some of the OperatorDecoderStream users inside of WAVM track the control stack and quit parsing from
// OperatorDecoderStream when the control stack is empty (since that would indicate unreachable code).
// Not doing that here, yet, since it's not clear it's required for the purpose of the validation
eosio_constraints_visitor
visitor
;
for
(
const
FunctionDef
&
fd
:
m
.
functions
.
defs
)
{
OperatorDecoderStream
decoder
(
fd
.
code
);
while
(
decoder
)
{
decoder
.
decodeOp
(
visitor
);
}
}
}
}}
\ No newline at end of file
libraries/chain/wasm_interface.cpp
浏览文件 @
25c6bcd9
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/exceptions.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/core/ignore_unused.hpp>
#include <eosio/chain/wasm_interface_private.hpp>
#include <eosio/chain/wasm_interface_private.hpp>
#include <eosio/chain/wasm_eosio_constraints.hpp>
#include <fc/exception/exception.hpp>
#include <fc/exception/exception.hpp>
#include <fc/crypto/sha1.hpp>
#include <fc/crypto/sha1.hpp>
#include <fc/io/raw.hpp>
#include <fc/io/raw.hpp>
...
@@ -221,6 +222,7 @@ namespace eosio { namespace chain {
...
@@ -221,6 +222,7 @@ namespace eosio { namespace chain {
Serialization
::
MemoryInputStream
stream
((
const
U8
*
)
wasm_binary
,
wasm_binary_size
);
Serialization
::
MemoryInputStream
stream
((
const
U8
*
)
wasm_binary
,
wasm_binary_size
);
#warning TODO: restore checktime injection?
#warning TODO: restore checktime injection?
WASM
::
serializeWithInjection
(
stream
,
*
module
);
WASM
::
serializeWithInjection
(
stream
,
*
module
);
validate_eosio_wasm_constraints
(
*
module
);
root_resolver
resolver
;
root_resolver
resolver
;
LinkResult
link_result
=
linkModule
(
*
module
,
resolver
);
LinkResult
link_result
=
linkModule
(
*
module
,
resolver
);
...
...
libraries/wasm-jit/Source/WASM/WASMSerialization.cpp
浏览文件 @
25c6bcd9
...
@@ -620,13 +620,6 @@ namespace WASM
...
@@ -620,13 +620,6 @@ namespace WASM
Opcode
opcode
;
Opcode
opcode
;
serialize
(
bodyStream
,
opcode
);
serialize
(
bodyStream
,
opcode
);
////disallow memory operations
#define VISIT_OPCODE(_,name,...) \
if(opcode == Opcode::name) \
throw FatalSerializationException("memory instructions not allowed");
ENUM_MEMORY_OPERATORS
(
VISIT_OPCODE
)
#undef VISIT_OPCODE
switch
(
opcode
)
switch
(
opcode
)
{
{
#define VISIT_OPCODE(_,name,nameString,Imm,...) \
#define VISIT_OPCODE(_,name,nameString,Imm,...) \
...
...
tests/wasm_tests/test_wasts.hpp
浏览文件 @
25c6bcd9
...
@@ -96,4 +96,78 @@ static const char grow_memory_wast[] = R"=====(
...
@@ -96,4 +96,78 @@ static const char grow_memory_wast[] = R"=====(
)
)
)
)
)
)
)====="
;
)====="
;
\ No newline at end of file
static
const
char
biggest_memory_wast
[]
=
R"=====(
(module
(import "env" "sbrk" (func $sbrk (param i32) (result i32)))
(table 0 anyfunc)
(memory $0 16)
(export "memory" (memory $0))
(export "apply" (func $apply))
(func $apply (param $0 i64) (param $1 i64)
(drop
(call $sbrk
(i32.const 1)
)
)
)
)
)====="
;
static
const
char
too_big_memory_wast
[]
=
R"=====(
(module
(table 0 anyfunc)
(memory $0 17)
(export "memory" (memory $0))
(export "apply" (func $apply))
(func $apply (param $0 i64) (param $1 i64))
)
)====="
;
static
const
char
valid_sparse_table
[]
=
R"=====(
(module
(table 1024 anyfunc)
(func $apply (param $0 i64) (param $1 i64))
(elem (i32.const 0) $apply)
(elem (i32.const 1022) $apply $apply)
)
)====="
;
static
const
char
too_big_table
[]
=
R"=====(
(module
(table 1025 anyfunc)
(func $apply (param $0 i64) (param $1 i64))
(elem (i32.const 0) $apply)
(elem (i32.const 1022) $apply $apply)
)
)====="
;
static
const
char
memory_init_borderline
[]
=
R"=====(
(module
(memory $0 16)
(data (i32.const 65532) "sup!")
)
)====="
;
static
const
char
memory_init_toolong
[]
=
R"=====(
(module
(memory $0 16)
(data (i32.const 65533) "sup!")
)
)====="
;
static
const
char
memory_init_negative
[]
=
R"=====(
(module
(memory $0 16)
(data (i32.const -1) "sup!")
)
)====="
;
static
const
char
memory_table_import
[]
=
R"=====(
(module
(table (import "foo" "table") 10 anyfunc)
(memory (import "nom" "memory") 0)
)
)====="
;
tests/wasm_tests/wasm_tests.cpp
浏览文件 @
25c6bcd9
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
#include <eosio/chain/exceptions.hpp>
#include <asserter/asserter.wast.hpp>
#include <asserter/asserter.wast.hpp>
#include <asserter/asserter.abi.hpp>
#include <asserter/asserter.abi.hpp>
...
@@ -519,7 +520,7 @@ BOOST_FIXTURE_TEST_CASE( memory_operators, tester ) try {
...
@@ -519,7 +520,7 @@ BOOST_FIXTURE_TEST_CASE( memory_operators, tester ) try {
transfer
(
N
(
inita
),
N
(
current_memory
),
"10.0000 EOS"
,
"memo"
);
transfer
(
N
(
inita
),
N
(
current_memory
),
"10.0000 EOS"
,
"memo"
);
produce_block
();
produce_block
();
set_code
(
N
(
current_memory
),
current_memory_wast
);
BOOST_CHECK_THROW
(
set_code
(
N
(
current_memory
),
current_memory_wast
),
eosio
::
chain
::
wasm_execution_error
);
produce_blocks
(
1
);
produce_blocks
(
1
);
{
{
signed_transaction
trx
;
signed_transaction
trx
;
...
@@ -551,6 +552,173 @@ BOOST_FIXTURE_TEST_CASE( memory_operators, tester ) try {
...
@@ -551,6 +552,173 @@ BOOST_FIXTURE_TEST_CASE( memory_operators, tester ) try {
}
FC_LOG_AND_RETHROW
()
}
FC_LOG_AND_RETHROW
()
//Make sure we can create a wasm with 16 pages, but not grow it any
BOOST_FIXTURE_TEST_CASE
(
big_memory
,
tester
)
try
{
produce_blocks
(
2
);
create_accounts
(
{
N
(
bigmem
)},
asset
::
from_string
(
"1000.0000 EOS"
)
);
transfer
(
N
(
inita
),
N
(
bigmem
),
"10.0000 EOS"
,
"memo"
);
produce_block
();
set_code
(
N
(
bigmem
),
biggest_memory_wast
);
//should pass, 16 pages is fine
produce_blocks
(
1
);
signed_transaction
trx
;
action
act
;
act
.
account
=
N
(
bigmem
);
act
.
name
=
N
();
act
.
authorization
=
vector
<
permission_level
>
{{
N
(
bigmem
),
config
::
active_name
}};
trx
.
actions
.
push_back
(
act
);
set_tapos
(
trx
);
trx
.
sign
(
get_private_key
(
N
(
bigmem
),
"active"
),
chain_id_type
());
//but should not be able to grow beyond 16th page
BOOST_CHECK_THROW
(
push_transaction
(
trx
),
fc
::
exception
);
produce_blocks
(
1
);
//should fail, 17 blocks is no no
BOOST_CHECK_THROW
(
set_code
(
N
(
bigmem
),
too_big_memory_wast
),
eosio
::
chain
::
wasm_execution_error
);
}
FC_LOG_AND_RETHROW
()
BOOST_FIXTURE_TEST_CASE
(
table_init_tests
,
tester
)
try
{
produce_blocks
(
2
);
create_accounts
(
{
N
(
tableinit
)},
asset
::
from_string
(
"1000.0000 EOS"
)
);
transfer
(
N
(
inita
),
N
(
tableinit
),
"10.0000 EOS"
,
"memo"
);
produce_block
();
set_code
(
N
(
tableinit
),
valid_sparse_table
);
produce_blocks
(
1
);
BOOST_CHECK_THROW
(
set_code
(
N
(
tableinit
),
too_big_table
),
eosio
::
chain
::
wasm_execution_error
);
}
FC_LOG_AND_RETHROW
()
BOOST_FIXTURE_TEST_CASE
(
memory_init_border
,
tester
)
try
{
produce_blocks
(
2
);
create_accounts
(
{
N
(
memoryborder
)},
asset
::
from_string
(
"1000.0000 EOS"
)
);
transfer
(
N
(
inita
),
N
(
memoryborder
),
"10.0000 EOS"
,
"memo"
);
produce_block
();
set_code
(
N
(
memoryborder
),
memory_init_borderline
);
produce_blocks
(
1
);
BOOST_CHECK_THROW
(
set_code
(
N
(
memoryborder
),
memory_init_toolong
),
eosio
::
chain
::
wasm_execution_error
);
BOOST_CHECK_THROW
(
set_code
(
N
(
memoryborder
),
memory_init_negative
),
eosio
::
chain
::
wasm_execution_error
);
}
FC_LOG_AND_RETHROW
()
BOOST_FIXTURE_TEST_CASE
(
imports
,
tester
)
try
{
produce_blocks
(
2
);
create_accounts
(
{
N
(
imports
)},
asset
::
from_string
(
"1000.0000 EOS"
)
);
transfer
(
N
(
inita
),
N
(
imports
),
"10.0000 EOS"
,
"memo"
);
produce_block
();
//this will fail to link but that's okay; mainly looking to make sure that the constraint
// system doesn't choke when memories and tables exist only as imports
BOOST_CHECK_THROW
(
set_code
(
N
(
imports
),
memory_table_import
),
fc
::
exception
);
}
FC_LOG_AND_RETHROW
()
BOOST_FIXTURE_TEST_CASE
(
lotso_globals
,
tester
)
try
{
produce_blocks
(
2
);
create_accounts
(
{
N
(
globals
)},
asset
::
from_string
(
"1000.0000 EOS"
)
);
transfer
(
N
(
inita
),
N
(
globals
),
"10.0000 EOS"
,
"memo"
);
produce_block
();
std
::
stringstream
ss
;
ss
<<
"(module "
;
for
(
unsigned
int
i
=
0
;
i
<
85
;
++
i
)
ss
<<
"(global $g"
<<
i
<<
" (mut i32) (i32.const 0))"
<<
"(global $g"
<<
i
+
100
<<
" (mut i64) (i64.const 0))"
;
//that gives us 1020 bytes of mutable globals
//add a few immutable ones for good measure
for
(
unsigned
int
i
=
0
;
i
<
10
;
++
i
)
ss
<<
"(global $g"
<<
i
+
200
<<
" i32 (i32.const 0))"
;
set_code
(
N
(
globals
),
string
(
ss
.
str
()
+
")"
)
.
c_str
());
//1024 should pass
set_code
(
N
(
globals
),
string
(
ss
.
str
()
+
"(global $z (mut i32) (i32.const -12)))"
)
.
c_str
());
//1028 should fail
BOOST_CHECK_THROW
(
set_code
(
N
(
globals
),
string
(
ss
.
str
()
+
"(global $z (mut i64) (i64.const -12)))"
)
.
c_str
()),
eosio
::
chain
::
wasm_execution_error
);;
}
FC_LOG_AND_RETHROW
()
BOOST_FIXTURE_TEST_CASE
(
offset_check
,
tester
)
try
{
produce_blocks
(
2
);
create_accounts
(
{
N
(
offsets
)},
asset
::
from_string
(
"1000.0000 EOS"
)
);
transfer
(
N
(
inita
),
N
(
offsets
),
"10.0000 EOS"
,
"memo"
);
produce_block
();
//floats not tested since they are blocked in the serializer before eosio_constraints
vector
<
string
>
loadops
=
{
"i32.load"
,
"i64.load"
,
/* "f32.load", "f64.load",*/
"i32.load8_s"
,
"i32.load8_u"
,
"i32.load16_s"
,
"i32.load16_u"
,
"i64.load8_s"
,
"i64.load8_u"
,
"i64.load16_s"
,
"i64.load16_u"
,
"i64.load32_s"
,
"i64.load32_u"
};
vector
<
vector
<
string
>>
storeops
=
{
{
"i32.store"
,
"i32"
},
{
"i64.store"
,
"i64"
},
/*{"f32.store", "f32"},
{"f64.store", "f64"},*/
{
"i32.store8"
,
"i32"
},
{
"i32.store16"
,
"i32"
},
{
"i64.store8"
,
"i64"
},
{
"i64.store16"
,
"i64"
},
{
"i64.store32"
,
"i64"
},
};
for
(
const
string
&
s
:
loadops
)
{
std
::
stringstream
ss
;
ss
<<
"(module (memory $0 16) (func $apply (param $0 i64) (param $1 i64) "
;
ss
<<
"(drop ("
<<
s
<<
" offset=1048574 (i32.const 0)))"
;
ss
<<
"))"
;
set_code
(
N
(
offsets
),
ss
.
str
().
c_str
());
produce_block
();
}
for
(
const
vector
<
string
>&
o
:
storeops
)
{
std
::
stringstream
ss
;
ss
<<
"(module (memory $0 16) (func $apply (param $0 i64) (param $1 i64) "
;
ss
<<
"("
<<
o
[
0
]
<<
" offset=1048574 (i32.const 0) ("
<<
o
[
1
]
<<
".const 0))"
;
ss
<<
"))"
;
set_code
(
N
(
offsets
),
ss
.
str
().
c_str
());
produce_block
();
}
for
(
const
string
&
s
:
loadops
)
{
std
::
stringstream
ss
;
ss
<<
"(module (memory $0 16) (func $apply (param $0 i64) (param $1 i64) "
;
ss
<<
"(drop ("
<<
s
<<
" offset=1048580 (i32.const 0)))"
;
ss
<<
"))"
;
BOOST_CHECK_THROW
(
set_code
(
N
(
offsets
),
ss
.
str
().
c_str
()),
eosio
::
chain
::
wasm_execution_error
);
produce_block
();
}
for
(
const
vector
<
string
>&
o
:
storeops
)
{
std
::
stringstream
ss
;
ss
<<
"(module (memory $0 16) (func $apply (param $0 i64) (param $1 i64) "
;
ss
<<
"("
<<
o
[
0
]
<<
" offset=1048580 (i32.const 0) ("
<<
o
[
1
]
<<
".const 0))"
;
ss
<<
"))"
;
BOOST_CHECK_THROW
(
set_code
(
N
(
offsets
),
ss
.
str
().
c_str
()),
eosio
::
chain
::
wasm_execution_error
);
produce_block
();
}
}
FC_LOG_AND_RETHROW
()
BOOST_FIXTURE_TEST_CASE
(
noop
,
tester
)
try
{
BOOST_FIXTURE_TEST_CASE
(
noop
,
tester
)
try
{
produce_blocks
(
2
);
produce_blocks
(
2
);
create_accounts
(
{
N
(
noop
),
N
(
alice
)},
asset
::
from_string
(
"1000.0000 EOS"
)
);
create_accounts
(
{
N
(
noop
),
N
(
alice
)},
asset
::
from_string
(
"1000.0000 EOS"
)
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录