@@ -30,6 +30,13 @@ static OLD_SOLC_RELEASES: LazyLock<Releases> = LazyLock::new(|| {
3030
3131const LINUX_AARCH64_MIN : Version = Version :: new ( 0 , 5 , 0 ) ;
3232
33+ // NOTE: Since version 0.8.31, Linux aarch64 releases are available: https://binaries.soliditylang.org/linux-arm64/list.json
34+ const LINUX_AARCH64_BINARIES : Version = Version :: new ( 0 , 8 , 31 ) ;
35+
36+ // NOTE: The official Solidity releases uses the platform name "linux-arm64"
37+ // instead of the "linux-aarch64" naming which is used by SVM.
38+ static LINUX_AARCH64_PLATFORM : & str = "linux-arm64" ;
39+
3340static LINUX_AARCH64_URL_PREFIX : & str = "https://raw.githubusercontent.com/nikitastupin/solc/2287d4326237172acf91ce42fd7ec18a67b7f512/linux/aarch64" ;
3441
3542static LINUX_AARCH64_RELEASES_URL : & str = "https://raw.githubusercontent.com/nikitastupin/solc/2287d4326237172acf91ce42fd7ec18a67b7f512/linux/aarch64/list.json" ;
@@ -120,6 +127,18 @@ impl Releases {
120127 versions. sort_unstable ( ) ;
121128 versions
122129 }
130+
131+ /// Retain versions matching a predicate.
132+ fn retain_versions ( & mut self , mut pred : impl FnMut ( & Version ) -> bool ) {
133+ self . builds . retain ( |build| pred ( & build. version ) ) ;
134+ self . releases . retain ( |version, _| pred ( version) ) ;
135+ }
136+
137+ /// Extends releases with another.
138+ fn extend ( & mut self , other : Self ) {
139+ self . builds . extend ( other. builds ) ;
140+ self . releases . extend ( other. releases ) ;
141+ }
123142}
124143
125144/// Build info contains the SHA256 checksum of a solc binary.
@@ -158,7 +177,22 @@ mod hex_string {
158177pub fn blocking_all_releases ( platform : Platform ) -> Result < Releases , SvmError > {
159178 match platform {
160179 Platform :: LinuxAarch64 => {
161- Ok ( reqwest:: blocking:: get ( LINUX_AARCH64_RELEASES_URL ) ?. json :: < Releases > ( ) ?)
180+ // Prior to version 0.8.31, releases for Linux arm64 builds was provided by the
181+ // `nikitastupin/solc` repository. From 0.8.31 (inclusive) and onwards, official
182+ // binary releases are provided by the Solidity project.
183+ let mut releases =
184+ reqwest:: blocking:: get ( LINUX_AARCH64_RELEASES_URL ) ?. json :: < Releases > ( ) ?;
185+ releases. retain_versions ( |v| * v < LINUX_AARCH64_BINARIES ) ;
186+ fix_build_prerelease ( & mut releases) ;
187+ let mut official = reqwest:: blocking:: get ( format ! (
188+ "{SOLC_RELEASES_URL}/{LINUX_AARCH64_PLATFORM}/list.json" ,
189+ ) ) ?
190+ . json :: < Releases > ( ) ?;
191+ // Filtering older releases isn't strinctly necessary here, but do it just in case
192+ // Solidity retroactively starts adding older release binaries for linux-aarch64.
193+ official. retain_versions ( |v| * v >= LINUX_AARCH64_BINARIES ) ;
194+ releases. extend ( official) ;
195+ Ok ( releases)
162196 }
163197 Platform :: MacOsAarch64 => {
164198 // The supported versions for both macos-amd64 and macos-aarch64 are the same.
@@ -170,23 +204,16 @@ pub fn blocking_all_releases(platform: Platform) -> Result<Releases, SvmError> {
170204 // require Rosetta support.
171205 //
172206 // Note: Since 0.8.24 universal macosx releases are available
173- let mut native =
174- reqwest:: blocking:: get ( MACOS_AARCH64_RELEASES_URL ) ?. json :: < Releases > ( ) ?;
207+ let native = reqwest:: blocking:: get ( MACOS_AARCH64_RELEASES_URL ) ?. json :: < Releases > ( ) ?;
175208 let mut releases = reqwest:: blocking:: get ( format ! (
176209 "{}/{}/list.json" ,
177210 SOLC_RELEASES_URL ,
178211 Platform :: MacOsAmd64 ,
179212 ) ) ?
180213 . json :: < Releases > ( ) ?;
181- releases. builds . retain ( |b| {
182- b. version < MACOS_AARCH64_NATIVE || b. version > UNIVERSAL_MACOS_BINARIES
183- } ) ;
184214 releases
185- . releases
186- . retain ( |v, _| * v < MACOS_AARCH64_NATIVE || * v > UNIVERSAL_MACOS_BINARIES ) ;
187- releases. builds . extend_from_slice ( & native. builds ) ;
188-
189- releases. releases . append ( & mut native. releases ) ;
215+ . retain_versions ( |v| * v < MACOS_AARCH64_NATIVE || * v > UNIVERSAL_MACOS_BINARIES ) ;
216+ releases. extend ( native) ;
190217 Ok ( releases)
191218 }
192219 Platform :: AndroidAarch64 => {
@@ -214,10 +241,28 @@ pub fn blocking_all_releases(platform: Platform) -> Result<Releases, SvmError> {
214241/// Fetch all releases available for the provided platform.
215242pub async fn all_releases ( platform : Platform ) -> Result < Releases , SvmError > {
216243 match platform {
217- Platform :: LinuxAarch64 => Ok ( get ( LINUX_AARCH64_RELEASES_URL )
244+ Platform :: LinuxAarch64 => {
245+ // Prior to version 0.8.31, releases for Linux arm64 builds was provided by the
246+ // `nikitastupin/solc` repository. From 0.8.31 (inclusive) and onwards, official
247+ // binary releases are provided by the Solidity project.
248+ let mut releases = get ( LINUX_AARCH64_RELEASES_URL )
249+ . await ?
250+ . json :: < Releases > ( )
251+ . await ?;
252+ releases. retain_versions ( |v| * v < LINUX_AARCH64_BINARIES ) ;
253+ fix_build_prerelease ( & mut releases) ;
254+ let mut official = get ( format ! (
255+ "{SOLC_RELEASES_URL}/{LINUX_AARCH64_PLATFORM}/list.json" ,
256+ ) )
218257 . await ?
219258 . json :: < Releases > ( )
220- . await ?) ,
259+ . await ?;
260+ // Filtering older releases isn't strinctly necessary here, but do it just in case
261+ // Solidity retroactively starts adding older release binaries for linux-aarch64.
262+ official. retain_versions ( |v| * v >= LINUX_AARCH64_BINARIES ) ;
263+ releases. extend ( official) ;
264+ Ok ( releases)
265+ }
221266 Platform :: MacOsAarch64 => {
222267 // The supported versions for both macos-amd64 and macos-aarch64 are the same.
223268 //
@@ -226,7 +271,7 @@ pub async fn all_releases(platform: Platform) -> Result<Releases, SvmError> {
226271 //
227272 // 2. For version <= 0.8.4 we fetch releases from https://binaries.soliditylang.org and
228273 // require Rosetta support.
229- let mut native = get ( MACOS_AARCH64_RELEASES_URL )
274+ let native = get ( MACOS_AARCH64_RELEASES_URL )
230275 . await ?
231276 . json :: < Releases > ( )
232277 . await ?;
@@ -238,15 +283,10 @@ pub async fn all_releases(platform: Platform) -> Result<Releases, SvmError> {
238283 . await ?
239284 . json :: < Releases > ( )
240285 . await ?;
241- releases. builds . retain ( |b| {
242- b. version < MACOS_AARCH64_NATIVE || b. version > UNIVERSAL_MACOS_BINARIES
243- } ) ;
244286 releases
245- . releases
246- . retain ( |v, _| * v < MACOS_AARCH64_NATIVE || * v > UNIVERSAL_MACOS_BINARIES ) ;
287+ . retain_versions ( |v| * v < MACOS_AARCH64_NATIVE || * v > UNIVERSAL_MACOS_BINARIES ) ;
247288
248- releases. builds . extend_from_slice ( & native. builds ) ;
249- releases. releases . append ( & mut native. releases ) ;
289+ releases. extend ( native) ;
250290 Ok ( releases)
251291 }
252292 Platform :: AndroidAarch64 => Ok ( get ( ANDROID_AARCH64_RELEASES_URL )
@@ -281,14 +321,27 @@ pub async fn all_releases(platform: Platform) -> Result<Releases, SvmError> {
281321fn unified_releases ( releases : Releases , platform : Platform ) -> Releases {
282322 if platform == Platform :: LinuxAmd64 {
283323 let mut all_releases = OLD_SOLC_RELEASES . clone ( ) ;
284- all_releases. builds . extend ( releases. builds ) ;
285- all_releases. releases . extend ( releases. releases ) ;
324+ all_releases. extend ( releases) ;
286325 all_releases
287326 } else {
288327 releases
289328 }
290329}
291330
331+ /// Fixes build pre-release info for certain release lists.
332+ ///
333+ /// In particular, the release list from the `nikitastupin/solc` repository does correctly label
334+ /// `prerelease` information in the build array, so populate it based on the `version`.
335+ fn fix_build_prerelease ( releases : & mut Releases ) {
336+ for build in & mut releases. builds {
337+ build. prerelease = if build. version . pre . is_empty ( ) {
338+ None
339+ } else {
340+ Some ( build. version . pre . as_str ( ) . to_owned ( ) )
341+ } ;
342+ }
343+ }
344+
292345/// Construct the URL to the Solc binary for the specified release version and target platform.
293346pub ( crate ) fn artifact_url (
294347 platform : Platform ,
@@ -305,7 +358,11 @@ pub(crate) fn artifact_url(
305358 }
306359
307360 if platform == Platform :: LinuxAarch64 {
308- if * version >= LINUX_AARCH64_MIN {
361+ if * version >= LINUX_AARCH64_BINARIES {
362+ return Ok ( Url :: parse ( & format ! (
363+ "{SOLC_RELEASES_URL}/{LINUX_AARCH64_PLATFORM}/{artifact}"
364+ ) ) ?) ;
365+ } else if * version >= LINUX_AARCH64_MIN {
309366 return Ok ( Url :: parse ( & format ! (
310367 "{LINUX_AARCH64_URL_PREFIX}/{artifact}"
311368 ) ) ?) ;
@@ -431,7 +488,33 @@ mod tests {
431488
432489 #[ tokio:: test]
433490 async fn test_all_releases_linux_aarch64 ( ) {
434- assert ! ( all_releases( Platform :: LinuxAarch64 ) . await . is_ok( ) ) ;
491+ let releases = all_releases ( Platform :: LinuxAarch64 )
492+ . await
493+ . expect ( "could not fetch releases for linux-aarch64" ) ;
494+ let thirdparty = LINUX_AARCH64_MIN ;
495+ let url1 = artifact_url (
496+ Platform :: LinuxAarch64 ,
497+ & thirdparty,
498+ releases. get_artifact ( & thirdparty) . unwrap ( ) ,
499+ )
500+ . expect ( "could not fetch artifact URL" ) ;
501+ let prerelease = Version :: parse ( "0.8.31-pre.1" ) . expect ( "failed to parse version" ) ;
502+ let url2 = artifact_url (
503+ Platform :: LinuxAarch64 ,
504+ & prerelease,
505+ releases. get_artifact ( & prerelease) . unwrap ( ) ,
506+ )
507+ . expect ( "could not fetch artifact URL" ) ;
508+ let official = LINUX_AARCH64_BINARIES ;
509+ let url3 = artifact_url (
510+ Platform :: LinuxAarch64 ,
511+ & official,
512+ releases. get_artifact ( & official) . unwrap ( ) ,
513+ )
514+ . expect ( "could not fetch artifact URL" ) ;
515+ assert ! ( url1. to_string( ) . contains( LINUX_AARCH64_URL_PREFIX ) ) ;
516+ assert ! ( url2. to_string( ) . contains( LINUX_AARCH64_URL_PREFIX ) ) ;
517+ assert ! ( url3. to_string( ) . contains( SOLC_RELEASES_URL ) ) ;
435518 }
436519
437520 #[ tokio:: test]
0 commit comments