Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add value to context #1434

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
51 changes: 51 additions & 0 deletions x/contracts/runtime/call_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,57 @@ func TestCallContext(t *testing.T) {
require.Nil(result)
}

func TestValueContext(t *testing.T) {
require := require.New(t)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

contract0ID := ids.GenerateTestID()
contract0Address := codec.CreateAddress(0, contract0ID)
stringedID0 := string(contract0ID[:])

defaultActorAddress := codec.Address{}

value := uint64(123456)

testStateManager := &TestStateManager{
ContractsMap: map[string][]byte{},
AccountMap: map[codec.Address]string{contract0Address: stringedID0},
Balances: map[codec.Address]uint64{defaultActorAddress: value},
}

err := testStateManager.CompileAndSetContract(ContractID(stringedID0), "call_contract")
require.NoError(err)

r := NewRuntime(
NewConfig(),
logging.NoLog{},
).WithDefaults(
CallInfo{
Contract: contract0Address,
State: testStateManager,
Fuel: 1000000,
})

result, err := r.WithValue(value).CallContract(
ctx,
&CallInfo{
Actor: r.defaultCallInfo.Actor,
FunctionName: "value_check",
})
require.NoError(err)
require.Equal(value, into[uint64](result))

result, err = r.CallContract(
ctx,
&CallInfo{
FunctionName: "value_check",
})
require.NoError(err)
require.Equal(uint64(0), into[uint64](result))
}

func TestCallContextPreventOverwrite(t *testing.T) {
require := require.New(t)
ctx := context.Background()
Expand Down
7 changes: 5 additions & 2 deletions x/contracts/runtime/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Context struct {
Actor codec.Address
Height uint64
Timestamp uint64
Value uint64
ActionID ids.ID
}

Expand Down Expand Up @@ -54,11 +55,12 @@ type CallInfo struct {
// the timestamp of the chain at the time this call was made
Timestamp uint64

// the value that is passed to the call context
Value uint64

// the action id that triggered this call
ActionID ids.ID

Value uint64

inst *ContractInstance
}

Expand Down Expand Up @@ -104,6 +106,7 @@ func (p *ContractInstance) call(ctx context.Context, callInfo *CallInfo) ([]byte
Actor: callInfo.Actor,
Height: callInfo.Height,
Timestamp: callInfo.Timestamp,
Value: callInfo.Value,
ActionID: callInfo.ActionID,
}
paramsBytes, err := Serialize(contractCtx)
Expand Down
5 changes: 5 additions & 0 deletions x/contracts/test/contracts/call_contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ pub fn actor_check_external(ctx: &mut Context, target: Address, max_units: Gas)
.expect("failure")
}

#[public]
pub fn value_check(context: &mut Context) -> u64 {
context.value()
}

#[public]
pub fn call_with_param(_: &mut Context, value: i64) -> i64 {
value
Expand Down
14 changes: 14 additions & 0 deletions x/contracts/wasmlanche/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct Context {
actor: Address,
height: u64,
timestamp: u64,
value: u64,
action_id: Id,
state_cache: Cache,
host_accessor: Accessor,
Expand All @@ -47,6 +48,7 @@ mod debug {
actor,
height,
timestamp,
value,
action_id,
state_cache: _,
host_accessor: _,
Expand All @@ -59,6 +61,7 @@ mod debug {
actor,
height,
timestamp,
value,
action_id
)
}
Expand All @@ -71,13 +74,15 @@ impl BorshDeserialize for Context {
let actor = Address::deserialize_reader(reader)?;
let height = u64::deserialize_reader(reader)?;
let timestamp = u64::deserialize_reader(reader)?;
let value = u64::deserialize_reader(reader)?;
let action_id = Id::deserialize_reader(reader)?;

let ctx = Context {
contract_address,
actor,
height,
timestamp,
value,
action_id,
state_cache: Cache::new(),
host_accessor: Accessor::new(),
Expand Down Expand Up @@ -125,6 +130,14 @@ impl Context {
self.timestamp
}

/// Returns the call-value
/// # Panics
/// Panics if the context was not injected
#[must_use]
pub fn value(&self) -> u64 {
self.value
}

/// Returns the action-id
/// # Panics
/// Panics if the context was not injected
Expand Down Expand Up @@ -270,6 +283,7 @@ impl Context {
actor: Address::default(),
height: 0,
timestamp: 0,
value: 0,
action_id: Id::default(),
state_cache: Cache::new(),
host_accessor: Accessor::new(),
Expand Down
2 changes: 2 additions & 0 deletions x/contracts/wasmlanche/tests/wasmtime-integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,15 @@ impl TestCrate {
let mut actor = vec![0; Address::LEN];
let height: u64 = 0;
let timestamp: u64 = 0;
let value: u64 = 0;
let mut action_id = vec![1; ID_LEN];

// this is a hack to create a context since the constructor is private
let mut serialized_context = contract_id;
serialized_context.append(&mut actor);
serialized_context.append(&mut height.to_le_bytes().to_vec());
serialized_context.append(&mut timestamp.to_le_bytes().to_vec());
serialized_context.append(&mut value.to_le_bytes().to_vec());
serialized_context.append(&mut action_id);

self.allocate(serialized_context)
Expand Down
Loading