Skip to content

Truncate linkerObject at the beginning, not end #3918

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

Closed
wants to merge 1 commit into from
Closed

Truncate linkerObject at the beginning, not end #3918

wants to merge 1 commit into from

Conversation

seanyoung
Copy link

@seanyoung seanyoung commented Apr 17, 2018

When a importing a library with a long path, the unresolved name in the bin file gets truncated at tail end, and contract name is lost. This makes it impossible to link against.

Before this PR:

[sean@hamalech yours]$ pwd
/home/sean/solidity/my/path/is/longer/than/yours
[sean@hamalech yours]$ cat bar.sol 

library bar {
	function number() returns (uint) {
		return 1;
	}
}
[sean@hamalech yours]$ cat foo.sol 

import "/home/sean/solidity/my/path/is/longer/than/yours/bar.sol";

contract foo {
	function func1() returns (uint)
	{
		return bar.number();
	}
}
[sean@hamalech yours]$ ~/git/solidity/build/solc/solc --bin -o . foo.sol 
Warning: This is a pre-release compiler version, please do not use it in production.
/home/sean/solidity/my/path/is/longer/than/yours/bar.sol:2:1: Warning: Source file does not specify required compiler version!
library bar {
^ (Relevant source part starts here and spans across multiple lines).
foo.sol:2:1: Warning: Source file does not specify required compiler version!
import "/home/sean/solidity/my/path/is/longer/than/yours/bar.sol";
^ (Relevant source part starts here and spans across multiple lines).
/home/sean/solidity/my/path/is/longer/than/yours/bar.sol:3:2: Warning: No visibility specified. Defaulting to "public". 
	function number() returns (uint) {
 ^ (Relevant source part starts here and spans across multiple lines).
foo.sol:5:2: Warning: No visibility specified. Defaulting to "public". 
	function func1() returns (uint)
 ^ (Relevant source part starts here and spans across multiple lines).
/home/sean/solidity/my/path/is/longer/than/yours/bar.sol:3:2: Warning: Function state mutability can be restricted to pure
	function number() returns (uint) {
 ^ (Relevant source part starts here and spans across multiple lines).
[sean@hamalech yours]$ cat foo.bin 
608060405234801561001057600080fd5b5061013f806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680637413515414610046575b600080fd5b34801561005257600080fd5b5061005b610071565b6040518082815260200191505060405180910390f35b600073__/home/sean/solidity/my/path/is/longe__638381f58a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156100d357600080fd5b505af41580156100e7573d6000803e3d6000fd5b505050506040513d60208110156100fd57600080fd5b81019080805190602001909291905050509050905600a165627a7a723058200dd3284d826f7d529da5e65ea2e7c789eeb00daa4b0c05b4c277ed84c0442dfd0029[sean@hamalech yours]$ 
[sean@hamalech yours]$  ~/git/solidity/build/solc/solc --link --libraries bar:0xE68EB21C15974808648B0C145E91C7C3BB10F292 < foo.bin
Reference "__/home/sean/solidity/my/path/is/longe__" in file "<stdin>" still unresolved.
608060405234801561001057600080fd5b5061013f806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680637413515414610046575b600080fd5b34801561005257600080fd5b5061005b610071565b6040518082815260200191505060405180910390f35b600073__/home/sean/solidity/my/path/is/longe__638381f58a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156100d357600080fd5b505af41580156100e7573d6000803e3d6000fd5b505050506040513d60208110156100fd57600080fd5b81019080805190602001909291905050509050905600a165627a7a723058200dd3284d826f7d529da5e65ea2e7c789eeb00daa4b0c05b4c277ed84c0442dfd0029

After this PR:

[sean@hamalech yours]$ pwd
/home/sean/solidity/my/path/is/longer/than/yours
[sean@hamalech yours]$ cat bar.sol

library bar {
	function number() returns (uint) {
		return 1;
	}
}
[sean@hamalech yours]$ cat foo.sol 
import "/home/sean/solidity/my/path/is/longer/than/yours/bar.sol";

contract foo {
	function func1() returns (uint)
	{
		return bar.number();
	}
}
[sean@hamalech yours]$ ~/git/solidity/build/solc/solc --bin -o . foo.sol 
Warning: This is a pre-release compiler version, please do not use it in production.
/home/sean/solidity/my/path/is/longer/than/yours/bar.sol:2:1: Warning: Source file does not specify required compiler version!
library bar {
^ (Relevant source part starts here and spans across multiple lines).
foo.sol:2:1: Warning: Source file does not specify required compiler version!
import "/home/sean/solidity/my/path/is/longer/than/yours/bar.sol";
^ (Relevant source part starts here and spans across multiple lines).
/home/sean/solidity/my/path/is/longer/than/yours/bar.sol:3:2: Warning: No visibility specified. Defaulting to "public". 
	function number() returns (uint) {
 ^ (Relevant source part starts here and spans across multiple lines).
foo.sol:5:2: Warning: No visibility specified. Defaulting to "public". 
	function func1() returns (uint)
 ^ (Relevant source part starts here and spans across multiple lines).
/home/sean/solidity/my/path/is/longer/than/yours/bar.sol:3:2: Warning: Function state mutability can be restricted to pure
	function number() returns (uint) {
 ^ (Relevant source part starts here and spans across multiple lines).
[sean@hamalech yours]$ cat foo.bin
608060405234801561001057600080fd5b5061013f806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680637413515414610046575b600080fd5b34801561005257600080fd5b5061005b610071565b6040518082815260200191505060405180910390f35b600073__ath/is/longer/than/yours/bar.sol:bar__638381f58a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156100d357600080fd5b505af41580156100e7573d6000803e3d6000fd5b505050506040513d60208110156100fd57600080fd5b81019080805190602001909291905050509050905600a165627a7a72305820bff2bc2b6f9cbf78dd880a28c9b24dd513053dc5dff6aca76b72e8da400ca4fb0029[sean@hamalech yours]$ 
[sean@hamalech yours]$  ~/git/solidity/build/solc/solc --link --libraries /home/sean/solidity/my/path/is/longer/than/yours/bar.sol:bar:0xE68EB21C15974808648B0C145E91C7C3BB10F292 < foo.bin
608060405234801561001057600080fd5b5061013f806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680637413515414610046575b600080fd5b34801561005257600080fd5b5061005b610071565b6040518082815260200191505060405180910390f35b600073e68eb21c15974808648b0c145e91c7c3bb10f292638381f58a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156100d357600080fd5b505af41580156100e7573d6000803e3d6000fd5b505050506040513d60208110156100fd57600080fd5b81019080805190602001909291905050509050905600a165627a7a72305820bff2bc2b6f9cbf78dd880a28c9b24dd513053dc5dff6aca76b72e8da400ca4fb0029

The format for a fully qualified library name is path:name, where name
is the simple library name. Before this change, we truncate fully
qualified names on at the end, which means we lose part of the library
name rather than the path.

If you have a large project with many libraries in different directories,
then the beginning of the library path is more likely to be similar than
then end (i.e. library name and filename). Thus, truncate the beginning
of the fully qualified library name rather than the beginning.

Also, if you specify absolute paths for your import statements then
the unresolved names not likely to be unique.
@seanyoung seanyoung changed the title Linking issues Truncate linkerObject at the beginning, not end Apr 17, 2018
@chriseth
Copy link
Contributor

Thank you for the pull request! In my opinion, this change is a breaking change and cannot be done before 0.5.0. I would actually rather remove the truncated library names than change their alignment.

@seanyoung
Copy link
Author

This merge would require ethereum/solc-js#213 if merged

@seanyoung
Copy link
Author

seanyoung commented Apr 17, 2018

@chriseth I agree, removing the truncation would be much nicer. I can see two options:

  1. Removing the 40 limit for unresolved addresses; this would that in a bin file with unresolved libraries the offsets are wrong. That might be worth it.
  2. Hash the contract name and/or filename. That might work but hashing is non-reversable, so it would make files less readable.

What do you think?

@axic
Copy link
Member

axic commented Apr 17, 2018

I would actually rather remove the truncated library names than change their alignment.

I think they are entirely deprecated because the new JSON format gives offsets properly.

For a proper big break, I'd consider to change each value to:

  • a unique identifier (index from 0) per compilation
  • the index within the linkReferences

This way the content is still parseable, but cannot be used without the standard JSON format, which is the aim.

@axic
Copy link
Member

axic commented Apr 17, 2018

@seanyoung a hash sounds nice too, but has to be less than 160 bits given the requirement of underscores on both sides. Otherwise the contract may be deployed with random "linked" addresses.

@axic axic closed this Apr 17, 2018
@axic axic reopened this Apr 17, 2018
@j-h-scheufen
Copy link

j-h-scheufen commented Apr 17, 2018

Allow me to comment as I worked with @seanyoung on this.
We realize that a better long-term solution is needed and this was an easy way to stay (somewhat) backwards-compatible with the pre 0.4.9 behavior of using only the library name as the unresolved reference. This PR guarantees that the library name is visible on the right-hand side of the reference. Otherwise, projects using imports from other directories have no chance of creating the linking instructions directly (without the additional json output, as was possible before, see also #1645). My assumption is that there are two types of projects:

  1. The ones that copy all contracts into the same directory before compiling
  2. The ones that use imports across directories and are forced to use json output

This change would be transparent to type 1.) projects (or any project where the import path fits into the 40 bytes). Type 2.) project would also not be affected by this change as they rely on json output.

We tried using solc --standard-json and parsing the linkReferences, but ran into issues since that particular mode of solc does not resolve local (same directory) imports, e.g. import "./Test.sol";. Is that a known issue?

We're currently using this patch on top of 0.4.21 to compile and link without resorting to standard-json output and we're interested in helping create a long-term solution that is more reliable. Do you think this ticket is a good place to discuss or is there a separate one that you're aware of?

@axic
Copy link
Member

axic commented Apr 17, 2018

The ones that use imports across directories and are forced to use json output

Please note that every other mode of operation is deprecated and will be removed in the future.

We tried using solc --standard-json and parsing the linkReferences, but ran into issues since that particular mode of solc does not resolve local (same directory) imports, e.g. import "./Test.sol";. Is that a known issue?

Not really. Please create issues whenever they are encountered to give us a chance fixing them 😉

We're currently using this patch on top of 0.4.21 to compile and link without resorting to standard-json output and we're interested in helping create a long-term solution that is more reliable.

Do you distribute that version? If so, what is the version number (do you append a marker to the version)? Otherwise it is quite hard for outsiders to validate your contracts.

Do you think this ticket is a good place to discuss or is there a separate one that you're aware of?

Usually we prefer having issues for discussions (because PRs are more transient discussion wise and a lot of people are only checking issues and not PRs), so if you think this will take longer to resolve, please open an issue. Actually, I think it will make much more sense discussing this in an issue, with more context and problems you've encountered. Can you please create one?

@chriseth
Copy link
Contributor

chriseth commented Aug 6, 2018

Closing because standard-json provides a better fix and this would be a breaking change that does not properly fix the underlying issue. Created a new issue for the local file resolution.

@chriseth chriseth closed this Aug 6, 2018
@chriseth chriseth mentioned this pull request Oct 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants