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

Borsh #75

Closed
wants to merge 8 commits into from
Closed

Borsh #75

wants to merge 8 commits into from

Conversation

volovyks
Copy link
Collaborator

@volovyks volovyks commented Jun 1, 2022

It is throwing errors for now. Trying to find the reason.

The difference between JSON and borsh serialization is 1 line of code + schema. It will be great to have this logic in NearContract in the future.

@gagdiez
Copy link
Collaborator

gagdiez commented Jun 3, 2022

Interesting, it behaves as if it was not finding the exports of borsh... could it be because of how the borsh.js was compiled/created?

@ailisp
Copy link
Member

ailisp commented Jun 7, 2022

@gagdiez is right. the problem is the rollup configuration, it can only import ES modules, we need either package borsh in that format or tweak the rollup config. Enable non ES module imports in rollup, is possible, but that is without tree-shaking, and resulting bytecode would be larger

@ailisp
Copy link
Member

ailisp commented Jun 7, 2022

I made an attempt to fix rollup configuration to use borsh, now import serialize/deserialize from borsh works. Now it fails for a different issue: borsh uses Buffer, but that's a nodejs API that quickjs doesn't have. We need either:

  • make a modifier verison of borsh that doesn't use Buffer
  • or find a pure JavaScript buffer implementation with only Uint8Array. Quickjs support Uint8Array

@gagdiez
Copy link
Collaborator

gagdiez commented Jun 7, 2022

Could we implement a Buffer object as a wrapper of uint8array and import it globally? Or use something like: https://github.com/feross/buffer

Edit: I used "browserify" on nodes_modules/borsh/lib/index.js and managed to make the contract compile. It gave an error with the Schema (StatusMessage missed in schema) so I changed the schema to:

const schema = new Map([[StatusMessage, { kind: 'struct', fields: [['records', { kind: 'map', key: 'string', value: 'string' }]]}]]);

Now I am getting a WebAssembly trap: An 'unreachable' opcode was executed.. Which I guess is the browserify magic failing.

@ailisp
Copy link
Member

ailisp commented Jun 8, 2022

@gagdiez Cool! A good step towards success! Let me further explore on your approach

@ailisp
Copy link
Member

ailisp commented Jun 13, 2022

I'm able to make it compile too, by using https://github.com/feross/buffer, update cli.js to config rollup, use more gas since compiled contracts become bigger.

And mutate the status-message/node_modules/borsh/lib/index.js, add this import:

var Buffer = __importDefault(require('buffer/')).Buffer

The borsh test now fail of this error:

Smart contract panicked: cannot read property \'alloc\' of undefined\\n    at BinaryWriter (build/status-message-borsh.js:6816)\\n    at serialize (build/status-message-borsh.js:7118)\\n    at serialize (build/status-message-borsh.js:7246)\\n    at NewClass (build/status-message-borsh.js:42)\\n    at init (build/status-message-borsh.js:7263)\\n

Looking at build/status-message-borsh.js, it correctly included https://github.com/feross/buffer, but it still doesn't work. When trying to import and log the buffer module directly:

import {Buffer} from 'buffer/index'
...
        near.panic(Buffer))

It prints:

"Smart contract panicked: function Buffer() {\\n    [native code]\\n}"

Which seems work. So I guess, import Buffer in borsh-js should also work, but I'm having trouble to modify and build from source: near/borsh-js#57

@ailisp
Copy link
Member

ailisp commented Jun 15, 2022

test-template is working locally, strange that it doesn't work on CI 🤔

@volovyks
Copy link
Collaborator Author

  • It is failing on my machine as well.
  • Borsh example tests work (we need to add it to CI after merging master).
  • Setup should be the same in all the examples. We can achieve this by merging the master to this branch since it has only one test project now. I have tried to do it, but it led to several other problems.

// commonjs(),
babel({ babelHelpers: 'bundled' })
babel({ babelHelpers: 'bundled' }),
commonjs()
Copy link
Collaborator Author

@volovyks volovyks Jun 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: Not sure why are we doing this change. Let's discuss it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commonjs is used for import non-es packages, if I didn't remember it wrong, import commonjs module doesn't work without it.

import { NearContract, NearBindgen, call, view, near } from 'near-sdk-js'
import { serialize, deserialize } from 'borsh';
import { panic } from '../../../src/api';
import { Buffer } from 'buffer/'
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not the best practice. Can we add it as a dependency?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, should do so

@@ -24,8 +24,8 @@ test.beforeEach(async t => {
// Deploy and init the counter JS contract
const counter = await root.createSubAccount('counter');
let contract_base64 = (await readFile('build/contract.base64')).toString();
await counter.call(jsvm, 'deploy_js_contract', Buffer.from(contract_base64, 'base64'), {attachedDeposit: '400000000000000000000000'});
await counter.call(jsvm, 'call_js_contract', encodeCall(counter.accountId, 'init', []), {attachedDeposit: '400000000000000000000000'});
await counter.call(jsvm, 'deploy_js_contract', Buffer.from(contract_base64, 'base64'), {attachedDeposit: '800000000000000000000000'});
Copy link
Collaborator Author

@volovyks volovyks Jun 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The contract is 37! times bigger now :)
I think it's better not to support Borsh at all. But I believe we will be able to find the solution.

Update: ok, this is because we are packaging all the borsh code to the contract. That is not cool :/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this is how commonjs module worse than esm, rollup cannot handle just importing the used functions. And you found it's even worse that it also packaging all borsh code :(

"test": "ava"
},
"author": "Near Inc <hello@nearprotocol.com>",
"license": "Apache-2.0",
"dependencies": {
"near-sdk-js": "file:../../"
"borsh": "https://github.com/near/borsh-js/tarball/import-buffer",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand how this branch is different and why are we using it here. Can we use fix-build branch instead? (or maybe master if we will merge it).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has a import {Buffer} from buffer/` in borsh.ts, and borsh.js built from that. Without this line it doesn't work.

"@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-commonjs": "^22.0.0",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change helps to fix status-message-collections, but I have no idea why :/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe some bug fixes happened in 22.0?

@ailisp
Copy link
Member

ailisp commented Jun 16, 2022

It is failing on my machine as well.

Perhaps due to commonjs increase template.js size (it depends on lodash). Ah i figure out why it work on my side - i didn't yarn before yarn build, the old node_modules work (why??)

Borsh example tests work (we need to add it to CI after merging master).

Good to hear. Yes.

Setup should be the same in all the examples. We can achieve this by merging the master to this branch since it has only one test project now. I have tried to do it, but it led to several other problems.

Got it. Is the problem only related to template and status-message-borsh?

@ailisp
Copy link
Member

ailisp commented Jun 17, 2022

Status summary: we made borsh work by a series of hacks in this PR. But enabling commonjs modules enlarge the contract size significantly. We plan to ship borsh also in esm format to resolve

@ailisp ailisp linked an issue Sep 23, 2022 that may be closed by this pull request
@ailisp
Copy link
Member

ailisp commented Sep 12, 2023

Closed as completed by #361

@ailisp ailisp closed this Sep 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

borsh support in near-sdk-js
3 participants