#How to update contract wasm?

95 messages · Page 1 of 1 (latest)

pale canopy
#

I'm seeing issues using the update_current_contract_wasm host function. I just can't get it to work at all either locally or on network. I posted all the details I have about the issue here. https://github.com/stellar/rs-soroban-env/issues/1089

GitHub

What version are you using? v20.0.0-rc2 What did you do? Called update_current_contract_wasm from a contract in a Rust test that deployed a new version of the contract that had a new function Tried...

#

@past garden @hearty mango Is there something else we need to do when updating contract wasm to commit the change?

#

It just seems like the change isn't finalized/applied.

#

I see the system event indicating an upgrade is taking place:

{
  "ext": "v0",
  "contract_id": "da6f639880f9fad77bffc13d04bbafb27c6e7874650d0b305619cddcea017f59",
  "type_": "system",
  "body": {
    "v0": {
      "topics": [
        {
          "symbol": "executable_update"
        },
        {
          "vec": [
            {
              "symbol": "Wasm"
            },
            {
              "bytes": "bd661542ca3c05f673cdfc52cf8228be595328d313483c65573908e82ddda8ed"
            }
          ]
        },
        {
          "vec": [
            {
              "symbol": "Wasm"
            },
            {
              "bytes": "a14c6e5275afb5faa17776bccf4b0b926dbb522e569f13a1b77f0b350e057392"
            }
          ]
        }
      ],
      "data": {
        "vec": []
      }
    }
  }
}```
past garden
#

Is there something else we need to do when updating contract wasm to commit the change?
transaction has to succeed

#

but I guess if there is an event, it succeeded

#

why do you think it didn't succeed?

pale canopy
#

Because the updated contract is not callable.

#

When I invoke the contract I get old behavior.

#

I know for certain because my update adds a new function, and the new function isn't available.

#

My update also removes a function, but the old function is still available.

#

This is happening locally in Rust tests, and in the deployed network.

past garden
#

interesting, this seems like a regression to me. though IIRC there are tests that perform update and they still pass. is the LE not updated? do you have the full meta of the upgrade op?

#

(I mean the op that should've performed the updgrade)

pale canopy
#

Also, I saved the ledger state, and it's not changing.

#

The fully meta is at the link above.

past garden
#

hmm, meta has no change as well... I'll take a closer look

pale canopy
#

Meta does have the system event though, so it seems like it thinks it is succeeding, but something isn't sticking.

past garden
#

yeah, right

#

also, do you have the contract source code?

pale canopy
#

I'll push the contract to a repo so you can see what I'm doing, but it really is very lightweight, not much here.

past garden
#

I see there is some instance storage - my first suspect would be some bad override of the instance entry

#

ok

pale canopy
#

I'm deploying installer.wasm only, then calling its install function with no params. Then expecting to be able to call its deploy function.

pale canopy
past garden
#

oh

#

yeah, I see the root of the issue

#

it's a pretty bad bug

#

good that you've found it

pale canopy
#

Ok yeah, when I change the storage type to something other than instance, the update works fine when deployed to network.

#

I think there's multiple issues here though. There's this issue with instance storage and updating which occurs on network. There's the original issue that in tests update doesn't work either, irrespective of storage type.

past garden
#

it's just a bug in instance storage

#

though for tests there may be some other issue

pale canopy
#

Yup, so when I use another storage type it is fixed.

#

Except in tests, it is still broken.

past garden
#

ok

#

I'll take a look at that as well

pale canopy
#

It seems like in tests that updates just never apply.

#

I understand the update shouldn't apply immediately because it has to take affect at the next ledger. But in tests we should probably have it apply (i.e. increment the ledger) after every top level invoke/frame is complete.

fossil delta
#

Just to pipe in with my observation, in the RPCiege challenge I am able to upgrade a deployed contract. In this case the upgraded contract has a function with the same name, just extra parameters. This is on futurenet

past garden
#

yeah, the bug has been there forever, yet just now we've got a combination of instance storage write+upgrade

pale canopy
#

The test issue I'm seeing might be different 🤔. I do see the ledger state changing when converting the ledger state to a snapshot.

past garden
#

do you upgrade a native contract to wasm?

pale canopy
#

My test is all wasms.

past garden
#

hmm

pale canopy
#

I have a test crate that tests the contracts in their wasm form only. No native test.

past garden
#

I'll look more then

pale canopy
#

Yeah in tests I'm getting a Error(WasmVm, UnexpectedType) when executing the upgraded contract, so it looks like the upgrade is working fine in tests when using another storage type.

#

I probably just have a logial bug in my contract.

#

I find the diagnostic events in tests very confusing in that the back trace includes every invoke in the test, rather than just the back trace for the last top-level invoke:


Event log (newest first):
   0: [Diagnostic Event] topics:[error, Error(WasmVm, UnexpectedType)], data:"escalating error to panic"
   1: [Diagnostic Event] topics:[error, Error(WasmVm, UnexpectedType)], data:["contract call failed", deploy, []]
   2: [Diagnostic Event] topics:[fn_call, Bytes(05c2f5cc07cc3ffbf926de0afbecd09ebdc3cfeb359717ba8ec5a54461529a9d), deploy], data:Void
   3: [Diagnostic Event] contract:05c2f5cc07cc3ffbf926de0afbecd09ebdc3cfeb359717ba8ec5a54461529a9d, topics:[fn_return, install], data:Void
   4: [System Event] contract:05c2f5cc07cc3ffbf926de0afbecd09ebdc3cfeb359717ba8ec5a54461529a9d, topics:[executable_update, [Wasm, Bytes(b3c5eaa6e2e8718af8bd3a87f173669c42977acb3a492f82b65a0a2056a4d24e)], [Wasm, Bytes(b844d3ceac7c11f926c5b26ce2f65189f365c198b035f04d9e305768301ba009)]], data:[]
   5: [Diagnostic Event] topics:[fn_call, Bytes(05c2f5cc07cc3ffbf926de0afbecd09ebdc3cfeb359717ba8ec5a54461529a9d), install], data:Void```
cc @jovial karma
past garden
#

that's because diagnostic events are not a backtrace...

#

I think it's possible to extract a backtrace from them though

pale canopy
#

Ok, the backtrace part of my message is a red herring.

past garden
#

(we would need to emit a diagnostic event for popping the stack frame though)

pale canopy
#

What I mean is each top-level invoke in a test is essentially its own tx, a new invoke into the system. So diagnostic logs shouldn't leak from one to the other.

past garden
#

ah, you mean at that level. yeah, we should flush them

#

FWIW I think we should flush everything - we do flush auth data, but nothing else

pale canopy
#

There's probably other things we should do like increment ledger number too.

past garden
#

like budget should be flushed as well

pale canopy
#

If someone needs to do testing as if it's inside a single contract call, they can wrap their calls with env.as_contract.

past garden
#

not sure for the ledger seq increment - you might want to simulate two txs in the same ledger

past garden
#

@pale canopy I'm trying your test with my fix and it passes just fine. is there some other scenario that doesn't pass? I'll send a PR with the fix in the meantime

pale canopy
#

Is that testing it against a deployed network? Or in a local test?

I couldn't get the test to pass.

past garden
#

local test

pale canopy
#

Haha. Just discovered why my test was't passing. Writing to temporary, reading from instance 🤦🏻‍♂️

#

👍🏻 Sg.

past garden
#

hmm, I think there is another issue, which is that we always prioritize running the native contract implementation for an id

#

so updating native to wasm will work from the ledger standpoint, but calls would still lead to the native implementation

pale canopy
#

Hmm. We had tests in the SDK that exercised that behavior I thought.

past garden
#

did we? maybe I'm misreading the code then...

pale canopy
#

It should be possible to replace wasm with native, and native with wasm.

past garden
#

I'll probably address this separately anyway

pale canopy
#

Looking for the tests now...

past garden
#

not replace, but update

pale canopy
#

Maybe I just talked about writing the test...

past garden
#

using the env fn

pale canopy
#

Oh.

#

We don't have tests for that.

past garden
#

register_test_.. should be covered indeed

#

hmm, there is some inherent ambiguity in native overrides

#

scenario A: you create a wasm contract using deployer host fns. then you register a native contract under the same id.
scenario B: you register a native contract. then you call update wasm host fn inside it
what should be the final value of contract executable in both scenarios? which implementation should we dispatch the calls to?

#

(FWIW we use a 'dummy' wasm executable for all the native contracts currently)

#

the issue is that I guess in scenario A you'd expect calls to be dispatched to native, while in B you'd expect calls to be dispatched to wasm. but that's not how things work now

pale canopy
#

If that's not how it works, that sounds like a bug.

#

It's reasonable for a user to expect the most recent update or registration to be the contract being executed.

past garden
#

yeah, so I think we should treat native contract registration in the same way as wasm update - it should reset executable to dummy value. then if we see the dummy executable we would dispatch to native implementation

#

also, given that the functionality of deployer host fns have been improved so much, I think we should consolidate the logic and leave only the native contract registration in host

#

ah, actually these aren't shared anyway, nvm

spark ruin
#

While on this thread, I was taking a look at this test implementation for deploying via wasm in soroban contracts https://github.com/stellar/soroban-examples/blob/f42ae737c349d1b0965560b1a65ca67cf695d04b/deployer/deployer/src/test.rs#L16

and wondering, what other ways can we reference a contract wasm apart from using the filesystem

GitHub

Example Soroban Contracts. Contribute to stellar/soroban-examples development by creating an account on GitHub.

#

example

  1. using a remote url
  2. using an already deployed contract wasm, by specifying it's hash or id
pale canopy
#

At the moment you must have it on the file system. You can get the contract wasm for any deployed contract by using the stellar contract fetch command.