lib.rs 179 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144
  1. #![cfg_attr(
  2. not(feature = "agave-unstable-api"),
  3. deprecated(
  4. since = "3.1.0",
  5. note = "This crate has been marked for formal inclusion in the Agave Unstable API. From \
  6. v4.0.0 onward, the `agave-unstable-api` crate feature must be specified to \
  7. acknowledge use of an interface that may break without warning."
  8. )
  9. )]
  10. pub use self::{
  11. cpi::{SyscallInvokeSignedC, SyscallInvokeSignedRust},
  12. logging::{
  13. SyscallLog, SyscallLogBpfComputeUnits, SyscallLogData, SyscallLogPubkey, SyscallLogU64,
  14. },
  15. mem_ops::{SyscallMemcmp, SyscallMemcpy, SyscallMemmove, SyscallMemset},
  16. sysvar::{
  17. SyscallGetClockSysvar, SyscallGetEpochRewardsSysvar, SyscallGetEpochScheduleSysvar,
  18. SyscallGetFeesSysvar, SyscallGetLastRestartSlotSysvar, SyscallGetRentSysvar,
  19. SyscallGetSysvar,
  20. },
  21. };
  22. use solana_program_runtime::memory::translate_vm_slice;
  23. #[allow(deprecated)]
  24. use {
  25. crate::mem_ops::is_nonoverlapping,
  26. solana_big_mod_exp::{big_mod_exp, BigModExpParams},
  27. solana_blake3_hasher as blake3,
  28. solana_cpi::MAX_RETURN_DATA,
  29. solana_hash::Hash,
  30. solana_instruction::{error::InstructionError, AccountMeta, ProcessedSiblingInstruction},
  31. solana_keccak_hasher as keccak, solana_poseidon as poseidon,
  32. solana_program_entrypoint::{BPF_ALIGN_OF_U128, SUCCESS},
  33. solana_program_runtime::{
  34. cpi::CpiError,
  35. execution_budget::{SVMTransactionExecutionBudget, SVMTransactionExecutionCost},
  36. invoke_context::InvokeContext,
  37. memory::MemoryTranslationError,
  38. stable_log, translate_inner, translate_slice_inner, translate_type_inner,
  39. },
  40. solana_pubkey::{Pubkey, PubkeyError, MAX_SEEDS, MAX_SEED_LEN, PUBKEY_BYTES},
  41. solana_sbpf::{
  42. declare_builtin_function,
  43. memory_region::{AccessType, MemoryMapping},
  44. program::{BuiltinProgram, SBPFVersion},
  45. vm::Config,
  46. },
  47. solana_secp256k1_recover::{
  48. Secp256k1RecoverError, SECP256K1_PUBLIC_KEY_LENGTH, SECP256K1_SIGNATURE_LENGTH,
  49. },
  50. solana_sha256_hasher::Hasher,
  51. solana_svm_feature_set::SVMFeatureSet,
  52. solana_svm_log_collector::{ic_logger_msg, ic_msg},
  53. solana_svm_type_overrides::sync::Arc,
  54. solana_sysvar::SysvarSerialize,
  55. solana_transaction_context::vm_slice::VmSlice,
  56. std::{
  57. alloc::Layout,
  58. mem::{align_of, size_of},
  59. slice::from_raw_parts_mut,
  60. str::{from_utf8, Utf8Error},
  61. },
  62. thiserror::Error as ThisError,
  63. };
  64. mod cpi;
  65. mod logging;
  66. mod mem_ops;
  67. mod sysvar;
  68. /// Error definitions
  69. #[derive(Debug, ThisError, PartialEq, Eq)]
  70. pub enum SyscallError {
  71. #[error("{0}: {1:?}")]
  72. InvalidString(Utf8Error, Vec<u8>),
  73. #[error("SBF program panicked")]
  74. Abort,
  75. #[error("SBF program Panicked in {0} at {1}:{2}")]
  76. Panic(String, u64, u64),
  77. #[error("Cannot borrow invoke context")]
  78. InvokeContextBorrowFailed,
  79. #[error("Malformed signer seed: {0}: {1:?}")]
  80. MalformedSignerSeed(Utf8Error, Vec<u8>),
  81. #[error("Could not create program address with signer seeds: {0}")]
  82. BadSeeds(PubkeyError),
  83. #[error("Program {0} not supported by inner instructions")]
  84. ProgramNotSupported(Pubkey),
  85. #[error("Unaligned pointer")]
  86. UnalignedPointer,
  87. #[error("Too many signers")]
  88. TooManySigners,
  89. #[error("Instruction passed to inner instruction is too large ({0} > {1})")]
  90. InstructionTooLarge(usize, usize),
  91. #[error("Too many accounts passed to inner instruction")]
  92. TooManyAccounts,
  93. #[error("Overlapping copy")]
  94. CopyOverlapping,
  95. #[error("Return data too large ({0} > {1})")]
  96. ReturnDataTooLarge(u64, u64),
  97. #[error("Hashing too many sequences")]
  98. TooManySlices,
  99. #[error("InvalidLength")]
  100. InvalidLength,
  101. #[error("Invoked an instruction with data that is too large ({data_len} > {max_data_len})")]
  102. MaxInstructionDataLenExceeded { data_len: u64, max_data_len: u64 },
  103. #[error("Invoked an instruction with too many accounts ({num_accounts} > {max_accounts})")]
  104. MaxInstructionAccountsExceeded {
  105. num_accounts: u64,
  106. max_accounts: u64,
  107. },
  108. #[error(
  109. "Invoked an instruction with too many account info's ({num_account_infos} > \
  110. {max_account_infos})"
  111. )]
  112. MaxInstructionAccountInfosExceeded {
  113. num_account_infos: u64,
  114. max_account_infos: u64,
  115. },
  116. #[error("InvalidAttribute")]
  117. InvalidAttribute,
  118. #[error("Invalid pointer")]
  119. InvalidPointer,
  120. #[error("Arithmetic overflow")]
  121. ArithmeticOverflow,
  122. }
  123. impl From<MemoryTranslationError> for SyscallError {
  124. fn from(error: MemoryTranslationError) -> Self {
  125. match error {
  126. MemoryTranslationError::UnalignedPointer => SyscallError::UnalignedPointer,
  127. MemoryTranslationError::InvalidLength => SyscallError::InvalidLength,
  128. }
  129. }
  130. }
  131. impl From<CpiError> for SyscallError {
  132. fn from(error: CpiError) -> Self {
  133. match error {
  134. CpiError::InvalidPointer => SyscallError::InvalidPointer,
  135. CpiError::TooManySigners => SyscallError::TooManySigners,
  136. CpiError::BadSeeds(e) => SyscallError::BadSeeds(e),
  137. CpiError::InvalidLength => SyscallError::InvalidLength,
  138. CpiError::MaxInstructionAccountsExceeded {
  139. num_accounts,
  140. max_accounts,
  141. } => SyscallError::MaxInstructionAccountsExceeded {
  142. num_accounts,
  143. max_accounts,
  144. },
  145. CpiError::MaxInstructionDataLenExceeded {
  146. data_len,
  147. max_data_len,
  148. } => SyscallError::MaxInstructionDataLenExceeded {
  149. data_len,
  150. max_data_len,
  151. },
  152. CpiError::MaxInstructionAccountInfosExceeded {
  153. num_account_infos,
  154. max_account_infos,
  155. } => SyscallError::MaxInstructionAccountInfosExceeded {
  156. num_account_infos,
  157. max_account_infos,
  158. },
  159. CpiError::ProgramNotSupported(pubkey) => SyscallError::ProgramNotSupported(pubkey),
  160. }
  161. }
  162. }
  163. type Error = Box<dyn std::error::Error>;
  164. trait HasherImpl {
  165. const NAME: &'static str;
  166. type Output: AsRef<[u8]>;
  167. fn create_hasher() -> Self;
  168. fn hash(&mut self, val: &[u8]);
  169. fn result(self) -> Self::Output;
  170. fn get_base_cost(compute_cost: &SVMTransactionExecutionCost) -> u64;
  171. fn get_byte_cost(compute_cost: &SVMTransactionExecutionCost) -> u64;
  172. fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64;
  173. }
  174. struct Sha256Hasher(Hasher);
  175. struct Blake3Hasher(blake3::Hasher);
  176. struct Keccak256Hasher(keccak::Hasher);
  177. impl HasherImpl for Sha256Hasher {
  178. const NAME: &'static str = "Sha256";
  179. type Output = Hash;
  180. fn create_hasher() -> Self {
  181. Sha256Hasher(Hasher::default())
  182. }
  183. fn hash(&mut self, val: &[u8]) {
  184. self.0.hash(val);
  185. }
  186. fn result(self) -> Self::Output {
  187. self.0.result()
  188. }
  189. fn get_base_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
  190. compute_cost.sha256_base_cost
  191. }
  192. fn get_byte_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
  193. compute_cost.sha256_byte_cost
  194. }
  195. fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64 {
  196. compute_budget.sha256_max_slices
  197. }
  198. }
  199. impl HasherImpl for Blake3Hasher {
  200. const NAME: &'static str = "Blake3";
  201. type Output = blake3::Hash;
  202. fn create_hasher() -> Self {
  203. Blake3Hasher(blake3::Hasher::default())
  204. }
  205. fn hash(&mut self, val: &[u8]) {
  206. self.0.hash(val);
  207. }
  208. fn result(self) -> Self::Output {
  209. self.0.result()
  210. }
  211. fn get_base_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
  212. compute_cost.sha256_base_cost
  213. }
  214. fn get_byte_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
  215. compute_cost.sha256_byte_cost
  216. }
  217. fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64 {
  218. compute_budget.sha256_max_slices
  219. }
  220. }
  221. impl HasherImpl for Keccak256Hasher {
  222. const NAME: &'static str = "Keccak256";
  223. type Output = keccak::Hash;
  224. fn create_hasher() -> Self {
  225. Keccak256Hasher(keccak::Hasher::default())
  226. }
  227. fn hash(&mut self, val: &[u8]) {
  228. self.0.hash(val);
  229. }
  230. fn result(self) -> Self::Output {
  231. self.0.result()
  232. }
  233. fn get_base_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
  234. compute_cost.sha256_base_cost
  235. }
  236. fn get_byte_cost(compute_cost: &SVMTransactionExecutionCost) -> u64 {
  237. compute_cost.sha256_byte_cost
  238. }
  239. fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64 {
  240. compute_budget.sha256_max_slices
  241. }
  242. }
  243. fn consume_compute_meter(invoke_context: &InvokeContext, amount: u64) -> Result<(), Error> {
  244. invoke_context.consume_checked(amount)?;
  245. Ok(())
  246. }
  247. macro_rules! register_feature_gated_function {
  248. ($result:expr, $is_feature_active:expr, $name:expr, $call:expr $(,)?) => {
  249. if $is_feature_active {
  250. $result.register_function($name, $call)
  251. } else {
  252. Ok(())
  253. }
  254. };
  255. }
  256. pub fn create_program_runtime_environment_v1<'a, 'ix_data>(
  257. feature_set: &SVMFeatureSet,
  258. compute_budget: &SVMTransactionExecutionBudget,
  259. reject_deployment_of_broken_elfs: bool,
  260. debugging_features: bool,
  261. ) -> Result<BuiltinProgram<InvokeContext<'a, 'ix_data>>, Error> {
  262. let enable_alt_bn128_syscall = feature_set.enable_alt_bn128_syscall;
  263. let enable_alt_bn128_compression_syscall = feature_set.enable_alt_bn128_compression_syscall;
  264. let enable_big_mod_exp_syscall = feature_set.enable_big_mod_exp_syscall;
  265. let blake3_syscall_enabled = feature_set.blake3_syscall_enabled;
  266. let curve25519_syscall_enabled = feature_set.curve25519_syscall_enabled;
  267. let disable_fees_sysvar = feature_set.disable_fees_sysvar;
  268. let disable_deploy_of_alloc_free_syscall =
  269. reject_deployment_of_broken_elfs && feature_set.disable_deploy_of_alloc_free_syscall;
  270. let last_restart_slot_syscall_enabled = feature_set.last_restart_slot_sysvar;
  271. let enable_poseidon_syscall = feature_set.enable_poseidon_syscall;
  272. let remaining_compute_units_syscall_enabled =
  273. feature_set.remaining_compute_units_syscall_enabled;
  274. let get_sysvar_syscall_enabled = feature_set.get_sysvar_syscall_enabled;
  275. let enable_get_epoch_stake_syscall = feature_set.enable_get_epoch_stake_syscall;
  276. let min_sbpf_version =
  277. if !feature_set.disable_sbpf_v0_execution || feature_set.reenable_sbpf_v0_execution {
  278. SBPFVersion::V0
  279. } else {
  280. SBPFVersion::V3
  281. };
  282. let max_sbpf_version = if feature_set.enable_sbpf_v3_deployment_and_execution {
  283. SBPFVersion::V3
  284. } else if feature_set.enable_sbpf_v2_deployment_and_execution {
  285. SBPFVersion::V2
  286. } else if feature_set.enable_sbpf_v1_deployment_and_execution {
  287. SBPFVersion::V1
  288. } else {
  289. SBPFVersion::V0
  290. };
  291. debug_assert!(min_sbpf_version <= max_sbpf_version);
  292. let config = Config {
  293. max_call_depth: compute_budget.max_call_depth,
  294. stack_frame_size: compute_budget.stack_frame_size,
  295. enable_address_translation: true,
  296. enable_stack_frame_gaps: true,
  297. instruction_meter_checkpoint_distance: 10000,
  298. enable_instruction_meter: true,
  299. enable_register_tracing: debugging_features,
  300. enable_symbol_and_section_labels: debugging_features,
  301. reject_broken_elfs: reject_deployment_of_broken_elfs,
  302. noop_instruction_rate: 256,
  303. sanitize_user_provided_values: true,
  304. enabled_sbpf_versions: min_sbpf_version..=max_sbpf_version,
  305. optimize_rodata: false,
  306. aligned_memory_mapping: !feature_set.stricter_abi_and_runtime_constraints,
  307. // Warning, do not use `Config::default()` so that configuration here is explicit.
  308. };
  309. let mut result = BuiltinProgram::new_loader(config);
  310. // Abort
  311. result.register_function("abort", SyscallAbort::vm)?;
  312. // Panic
  313. result.register_function("sol_panic_", SyscallPanic::vm)?;
  314. // Logging
  315. result.register_function("sol_log_", SyscallLog::vm)?;
  316. result.register_function("sol_log_64_", SyscallLogU64::vm)?;
  317. result.register_function("sol_log_pubkey", SyscallLogPubkey::vm)?;
  318. result.register_function("sol_log_compute_units_", SyscallLogBpfComputeUnits::vm)?;
  319. // Program defined addresses (PDA)
  320. result.register_function(
  321. "sol_create_program_address",
  322. SyscallCreateProgramAddress::vm,
  323. )?;
  324. result.register_function(
  325. "sol_try_find_program_address",
  326. SyscallTryFindProgramAddress::vm,
  327. )?;
  328. // Sha256
  329. result.register_function("sol_sha256", SyscallHash::vm::<Sha256Hasher>)?;
  330. // Keccak256
  331. result.register_function("sol_keccak256", SyscallHash::vm::<Keccak256Hasher>)?;
  332. // Secp256k1 Recover
  333. result.register_function("sol_secp256k1_recover", SyscallSecp256k1Recover::vm)?;
  334. // Blake3
  335. register_feature_gated_function!(
  336. result,
  337. blake3_syscall_enabled,
  338. "sol_blake3",
  339. SyscallHash::vm::<Blake3Hasher>,
  340. )?;
  341. // Elliptic Curve Operations
  342. register_feature_gated_function!(
  343. result,
  344. curve25519_syscall_enabled,
  345. "sol_curve_validate_point",
  346. SyscallCurvePointValidation::vm,
  347. )?;
  348. register_feature_gated_function!(
  349. result,
  350. curve25519_syscall_enabled,
  351. "sol_curve_group_op",
  352. SyscallCurveGroupOps::vm,
  353. )?;
  354. register_feature_gated_function!(
  355. result,
  356. curve25519_syscall_enabled,
  357. "sol_curve_multiscalar_mul",
  358. SyscallCurveMultiscalarMultiplication::vm,
  359. )?;
  360. // Sysvars
  361. result.register_function("sol_get_clock_sysvar", SyscallGetClockSysvar::vm)?;
  362. result.register_function(
  363. "sol_get_epoch_schedule_sysvar",
  364. SyscallGetEpochScheduleSysvar::vm,
  365. )?;
  366. register_feature_gated_function!(
  367. result,
  368. !disable_fees_sysvar,
  369. "sol_get_fees_sysvar",
  370. SyscallGetFeesSysvar::vm,
  371. )?;
  372. result.register_function("sol_get_rent_sysvar", SyscallGetRentSysvar::vm)?;
  373. register_feature_gated_function!(
  374. result,
  375. last_restart_slot_syscall_enabled,
  376. "sol_get_last_restart_slot",
  377. SyscallGetLastRestartSlotSysvar::vm,
  378. )?;
  379. result.register_function(
  380. "sol_get_epoch_rewards_sysvar",
  381. SyscallGetEpochRewardsSysvar::vm,
  382. )?;
  383. // Memory ops
  384. result.register_function("sol_memcpy_", SyscallMemcpy::vm)?;
  385. result.register_function("sol_memmove_", SyscallMemmove::vm)?;
  386. result.register_function("sol_memset_", SyscallMemset::vm)?;
  387. result.register_function("sol_memcmp_", SyscallMemcmp::vm)?;
  388. // Processed sibling instructions
  389. result.register_function(
  390. "sol_get_processed_sibling_instruction",
  391. SyscallGetProcessedSiblingInstruction::vm,
  392. )?;
  393. // Stack height
  394. result.register_function("sol_get_stack_height", SyscallGetStackHeight::vm)?;
  395. // Return data
  396. result.register_function("sol_set_return_data", SyscallSetReturnData::vm)?;
  397. result.register_function("sol_get_return_data", SyscallGetReturnData::vm)?;
  398. // Cross-program invocation
  399. result.register_function("sol_invoke_signed_c", SyscallInvokeSignedC::vm)?;
  400. result.register_function("sol_invoke_signed_rust", SyscallInvokeSignedRust::vm)?;
  401. // Memory allocator
  402. register_feature_gated_function!(
  403. result,
  404. !disable_deploy_of_alloc_free_syscall,
  405. "sol_alloc_free_",
  406. SyscallAllocFree::vm,
  407. )?;
  408. // Alt_bn128
  409. register_feature_gated_function!(
  410. result,
  411. enable_alt_bn128_syscall,
  412. "sol_alt_bn128_group_op",
  413. SyscallAltBn128::vm,
  414. )?;
  415. // Big_mod_exp
  416. register_feature_gated_function!(
  417. result,
  418. enable_big_mod_exp_syscall,
  419. "sol_big_mod_exp",
  420. SyscallBigModExp::vm,
  421. )?;
  422. // Poseidon
  423. register_feature_gated_function!(
  424. result,
  425. enable_poseidon_syscall,
  426. "sol_poseidon",
  427. SyscallPoseidon::vm,
  428. )?;
  429. // Accessing remaining compute units
  430. register_feature_gated_function!(
  431. result,
  432. remaining_compute_units_syscall_enabled,
  433. "sol_remaining_compute_units",
  434. SyscallRemainingComputeUnits::vm
  435. )?;
  436. // Alt_bn128_compression
  437. register_feature_gated_function!(
  438. result,
  439. enable_alt_bn128_compression_syscall,
  440. "sol_alt_bn128_compression",
  441. SyscallAltBn128Compression::vm,
  442. )?;
  443. // Sysvar getter
  444. register_feature_gated_function!(
  445. result,
  446. get_sysvar_syscall_enabled,
  447. "sol_get_sysvar",
  448. SyscallGetSysvar::vm,
  449. )?;
  450. // Get Epoch Stake
  451. register_feature_gated_function!(
  452. result,
  453. enable_get_epoch_stake_syscall,
  454. "sol_get_epoch_stake",
  455. SyscallGetEpochStake::vm,
  456. )?;
  457. // Log data
  458. result.register_function("sol_log_data", SyscallLogData::vm)?;
  459. Ok(result)
  460. }
  461. pub fn create_program_runtime_environment_v2<'a, 'ix_data>(
  462. compute_budget: &SVMTransactionExecutionBudget,
  463. debugging_features: bool,
  464. ) -> BuiltinProgram<InvokeContext<'a, 'ix_data>> {
  465. let config = Config {
  466. max_call_depth: compute_budget.max_call_depth,
  467. stack_frame_size: compute_budget.stack_frame_size,
  468. enable_address_translation: true, // To be deactivated once we have BTF inference and verification
  469. enable_stack_frame_gaps: false,
  470. instruction_meter_checkpoint_distance: 10000,
  471. enable_instruction_meter: true,
  472. enable_register_tracing: debugging_features,
  473. enable_symbol_and_section_labels: debugging_features,
  474. reject_broken_elfs: true,
  475. noop_instruction_rate: 256,
  476. sanitize_user_provided_values: true,
  477. enabled_sbpf_versions: SBPFVersion::Reserved..=SBPFVersion::Reserved,
  478. optimize_rodata: true,
  479. aligned_memory_mapping: true,
  480. // Warning, do not use `Config::default()` so that configuration here is explicit.
  481. };
  482. BuiltinProgram::new_loader(config)
  483. }
  484. fn translate_type<'a, T>(
  485. memory_mapping: &'a MemoryMapping,
  486. vm_addr: u64,
  487. check_aligned: bool,
  488. ) -> Result<&'a T, Error> {
  489. translate_type_inner!(memory_mapping, AccessType::Load, vm_addr, T, check_aligned)
  490. .map(|value| &*value)
  491. }
  492. fn translate_slice<'a, T>(
  493. memory_mapping: &'a MemoryMapping,
  494. vm_addr: u64,
  495. len: u64,
  496. check_aligned: bool,
  497. ) -> Result<&'a [T], Error> {
  498. translate_slice_inner!(
  499. memory_mapping,
  500. AccessType::Load,
  501. vm_addr,
  502. len,
  503. T,
  504. check_aligned,
  505. )
  506. .map(|value| &*value)
  507. }
  508. /// Take a virtual pointer to a string (points to SBF VM memory space), translate it
  509. /// pass it to a user-defined work function
  510. fn translate_string_and_do(
  511. memory_mapping: &MemoryMapping,
  512. addr: u64,
  513. len: u64,
  514. check_aligned: bool,
  515. work: &mut dyn FnMut(&str) -> Result<u64, Error>,
  516. ) -> Result<u64, Error> {
  517. let buf = translate_slice::<u8>(memory_mapping, addr, len, check_aligned)?;
  518. match from_utf8(buf) {
  519. Ok(message) => work(message),
  520. Err(err) => Err(SyscallError::InvalidString(err, buf.to_vec()).into()),
  521. }
  522. }
  523. // Do not use this directly
  524. fn translate_type_mut<'a, T>(
  525. memory_mapping: &'a MemoryMapping,
  526. vm_addr: u64,
  527. check_aligned: bool,
  528. ) -> Result<&'a mut T, Error> {
  529. translate_type_inner!(memory_mapping, AccessType::Store, vm_addr, T, check_aligned)
  530. }
  531. // Do not use this directly
  532. fn translate_slice_mut<'a, T>(
  533. memory_mapping: &'a MemoryMapping,
  534. vm_addr: u64,
  535. len: u64,
  536. check_aligned: bool,
  537. ) -> Result<&'a mut [T], Error> {
  538. translate_slice_inner!(
  539. memory_mapping,
  540. AccessType::Store,
  541. vm_addr,
  542. len,
  543. T,
  544. check_aligned,
  545. )
  546. }
  547. fn touch_type_mut<T>(memory_mapping: &mut MemoryMapping, vm_addr: u64) -> Result<(), Error> {
  548. translate_inner!(
  549. memory_mapping,
  550. map_with_access_violation_handler,
  551. AccessType::Store,
  552. vm_addr,
  553. size_of::<T>() as u64,
  554. )
  555. .map(|_| ())
  556. }
  557. fn touch_slice_mut<T>(
  558. memory_mapping: &mut MemoryMapping,
  559. vm_addr: u64,
  560. element_count: u64,
  561. ) -> Result<(), Error> {
  562. if element_count == 0 {
  563. return Ok(());
  564. }
  565. translate_inner!(
  566. memory_mapping,
  567. map_with_access_violation_handler,
  568. AccessType::Store,
  569. vm_addr,
  570. element_count.saturating_mul(size_of::<T>() as u64),
  571. )
  572. .map(|_| ())
  573. }
  574. // No other translated references can be live when calling this.
  575. // Meaning it should generally be at the beginning or end of a syscall and
  576. // it should only be called once with all translations passed in one call.
  577. #[macro_export]
  578. macro_rules! translate_mut {
  579. (internal, $memory_mapping:expr, &mut [$T:ty], $vm_addr_and_element_count:expr) => {
  580. touch_slice_mut::<$T>(
  581. $memory_mapping,
  582. $vm_addr_and_element_count.0,
  583. $vm_addr_and_element_count.1,
  584. )?
  585. };
  586. (internal, $memory_mapping:expr, &mut $T:ty, $vm_addr:expr) => {
  587. touch_type_mut::<$T>(
  588. $memory_mapping,
  589. $vm_addr,
  590. )?
  591. };
  592. (internal, $memory_mapping:expr, $check_aligned:expr, &mut [$T:ty], $vm_addr_and_element_count:expr) => {{
  593. let slice = translate_slice_mut::<$T>(
  594. $memory_mapping,
  595. $vm_addr_and_element_count.0,
  596. $vm_addr_and_element_count.1,
  597. $check_aligned,
  598. )?;
  599. let host_addr = slice.as_ptr() as usize;
  600. (slice, host_addr, std::mem::size_of::<$T>().saturating_mul($vm_addr_and_element_count.1 as usize))
  601. }};
  602. (internal, $memory_mapping:expr, $check_aligned:expr, &mut $T:ty, $vm_addr:expr) => {{
  603. let reference = translate_type_mut::<$T>(
  604. $memory_mapping,
  605. $vm_addr,
  606. $check_aligned,
  607. )?;
  608. let host_addr = reference as *const _ as usize;
  609. (reference, host_addr, std::mem::size_of::<$T>())
  610. }};
  611. ($memory_mapping:expr, $check_aligned:expr, $(let $binding:ident : &mut $T:tt = map($vm_addr:expr $(, $element_count:expr)?) $try:tt;)+) => {
  612. // This ensures that all the parameters are collected first so that if they depend on previous translations
  613. $(let $binding = ($vm_addr $(, $element_count)?);)+
  614. // they are not invalidated by the following translations here:
  615. $(translate_mut!(internal, $memory_mapping, &mut $T, $binding);)+
  616. $(let $binding = translate_mut!(internal, $memory_mapping, $check_aligned, &mut $T, $binding);)+
  617. let host_ranges = [
  618. $(($binding.1, $binding.2),)+
  619. ];
  620. for (index, range_a) in host_ranges.get(..host_ranges.len().saturating_sub(1)).unwrap().iter().enumerate() {
  621. for range_b in host_ranges.get(index.saturating_add(1)..).unwrap().iter() {
  622. if !is_nonoverlapping(range_a.0, range_a.1, range_b.0, range_b.1) {
  623. return Err(SyscallError::CopyOverlapping.into());
  624. }
  625. }
  626. }
  627. $(let $binding = $binding.0;)+
  628. };
  629. }
  630. declare_builtin_function!(
  631. /// Abort syscall functions, called when the SBF program calls `abort()`
  632. /// LLVM will insert calls to `abort()` if it detects an untenable situation,
  633. /// `abort()` is not intended to be called explicitly by the program.
  634. /// Causes the SBF program to be halted immediately
  635. SyscallAbort,
  636. fn rust(
  637. _invoke_context: &mut InvokeContext,
  638. _arg1: u64,
  639. _arg2: u64,
  640. _arg3: u64,
  641. _arg4: u64,
  642. _arg5: u64,
  643. _memory_mapping: &mut MemoryMapping,
  644. ) -> Result<u64, Error> {
  645. Err(SyscallError::Abort.into())
  646. }
  647. );
  648. declare_builtin_function!(
  649. /// Panic syscall function, called when the SBF program calls 'sol_panic_()`
  650. /// Causes the SBF program to be halted immediately
  651. SyscallPanic,
  652. fn rust(
  653. invoke_context: &mut InvokeContext,
  654. file: u64,
  655. len: u64,
  656. line: u64,
  657. column: u64,
  658. _arg5: u64,
  659. memory_mapping: &mut MemoryMapping,
  660. ) -> Result<u64, Error> {
  661. consume_compute_meter(invoke_context, len)?;
  662. translate_string_and_do(
  663. memory_mapping,
  664. file,
  665. len,
  666. invoke_context.get_check_aligned(),
  667. &mut |string: &str| Err(SyscallError::Panic(string.to_string(), line, column).into()),
  668. )
  669. }
  670. );
  671. declare_builtin_function!(
  672. /// Dynamic memory allocation syscall called when the SBF program calls
  673. /// `sol_alloc_free_()`. The allocator is expected to allocate/free
  674. /// from/to a given chunk of memory and enforce size restrictions. The
  675. /// memory chunk is given to the allocator during allocator creation and
  676. /// information about that memory (start address and size) is passed
  677. /// to the VM to use for enforcement.
  678. SyscallAllocFree,
  679. fn rust(
  680. invoke_context: &mut InvokeContext,
  681. size: u64,
  682. free_addr: u64,
  683. _arg3: u64,
  684. _arg4: u64,
  685. _arg5: u64,
  686. _memory_mapping: &mut MemoryMapping,
  687. ) -> Result<u64, Error> {
  688. let align = if invoke_context.get_check_aligned() {
  689. BPF_ALIGN_OF_U128
  690. } else {
  691. align_of::<u8>()
  692. };
  693. let Ok(layout) = Layout::from_size_align(size as usize, align) else {
  694. return Ok(0);
  695. };
  696. let allocator = &mut invoke_context.get_syscall_context_mut()?.allocator;
  697. if free_addr == 0 {
  698. match allocator.alloc(layout) {
  699. Ok(addr) => Ok(addr),
  700. Err(_) => Ok(0),
  701. }
  702. } else {
  703. // Unimplemented
  704. Ok(0)
  705. }
  706. }
  707. );
  708. fn translate_and_check_program_address_inputs<'a>(
  709. seeds_addr: u64,
  710. seeds_len: u64,
  711. program_id_addr: u64,
  712. memory_mapping: &'a mut MemoryMapping,
  713. check_aligned: bool,
  714. ) -> Result<(Vec<&'a [u8]>, &'a Pubkey), Error> {
  715. let untranslated_seeds =
  716. translate_slice::<VmSlice<u8>>(memory_mapping, seeds_addr, seeds_len, check_aligned)?;
  717. if untranslated_seeds.len() > MAX_SEEDS {
  718. return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into());
  719. }
  720. let seeds = untranslated_seeds
  721. .iter()
  722. .map(|untranslated_seed| {
  723. if untranslated_seed.len() > MAX_SEED_LEN as u64 {
  724. return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into());
  725. }
  726. translate_vm_slice(untranslated_seed, memory_mapping, check_aligned)
  727. })
  728. .collect::<Result<Vec<_>, Error>>()?;
  729. let program_id = translate_type::<Pubkey>(memory_mapping, program_id_addr, check_aligned)?;
  730. Ok((seeds, program_id))
  731. }
  732. declare_builtin_function!(
  733. /// Create a program address
  734. SyscallCreateProgramAddress,
  735. fn rust(
  736. invoke_context: &mut InvokeContext,
  737. seeds_addr: u64,
  738. seeds_len: u64,
  739. program_id_addr: u64,
  740. address_addr: u64,
  741. _arg5: u64,
  742. memory_mapping: &mut MemoryMapping,
  743. ) -> Result<u64, Error> {
  744. let cost = invoke_context
  745. .get_execution_cost()
  746. .create_program_address_units;
  747. consume_compute_meter(invoke_context, cost)?;
  748. let (seeds, program_id) = translate_and_check_program_address_inputs(
  749. seeds_addr,
  750. seeds_len,
  751. program_id_addr,
  752. memory_mapping,
  753. invoke_context.get_check_aligned(),
  754. )?;
  755. let Ok(new_address) = Pubkey::create_program_address(&seeds, program_id) else {
  756. return Ok(1);
  757. };
  758. translate_mut!(
  759. memory_mapping,
  760. invoke_context.get_check_aligned(),
  761. let address: &mut [u8] = map(address_addr, std::mem::size_of::<Pubkey>() as u64)?;
  762. );
  763. address.copy_from_slice(new_address.as_ref());
  764. Ok(0)
  765. }
  766. );
  767. declare_builtin_function!(
  768. /// Create a program address
  769. SyscallTryFindProgramAddress,
  770. fn rust(
  771. invoke_context: &mut InvokeContext,
  772. seeds_addr: u64,
  773. seeds_len: u64,
  774. program_id_addr: u64,
  775. address_addr: u64,
  776. bump_seed_addr: u64,
  777. memory_mapping: &mut MemoryMapping,
  778. ) -> Result<u64, Error> {
  779. let cost = invoke_context
  780. .get_execution_cost()
  781. .create_program_address_units;
  782. consume_compute_meter(invoke_context, cost)?;
  783. let (seeds, program_id) = translate_and_check_program_address_inputs(
  784. seeds_addr,
  785. seeds_len,
  786. program_id_addr,
  787. memory_mapping,
  788. invoke_context.get_check_aligned(),
  789. )?;
  790. let mut bump_seed = [u8::MAX];
  791. for _ in 0..u8::MAX {
  792. {
  793. let mut seeds_with_bump = seeds.to_vec();
  794. seeds_with_bump.push(&bump_seed);
  795. if let Ok(new_address) =
  796. Pubkey::create_program_address(&seeds_with_bump, program_id)
  797. {
  798. translate_mut!(
  799. memory_mapping,
  800. invoke_context.get_check_aligned(),
  801. let bump_seed_ref: &mut u8 = map(bump_seed_addr)?;
  802. let address: &mut [u8] = map(address_addr, std::mem::size_of::<Pubkey>() as u64)?;
  803. );
  804. *bump_seed_ref = bump_seed[0];
  805. address.copy_from_slice(new_address.as_ref());
  806. return Ok(0);
  807. }
  808. }
  809. bump_seed[0] = bump_seed[0].saturating_sub(1);
  810. consume_compute_meter(invoke_context, cost)?;
  811. }
  812. Ok(1)
  813. }
  814. );
  815. declare_builtin_function!(
  816. /// secp256k1_recover
  817. SyscallSecp256k1Recover,
  818. fn rust(
  819. invoke_context: &mut InvokeContext,
  820. hash_addr: u64,
  821. recovery_id_val: u64,
  822. signature_addr: u64,
  823. result_addr: u64,
  824. _arg5: u64,
  825. memory_mapping: &mut MemoryMapping,
  826. ) -> Result<u64, Error> {
  827. let cost = invoke_context.get_execution_cost().secp256k1_recover_cost;
  828. consume_compute_meter(invoke_context, cost)?;
  829. translate_mut!(
  830. memory_mapping,
  831. invoke_context.get_check_aligned(),
  832. let secp256k1_recover_result: &mut [u8] = map(result_addr, SECP256K1_PUBLIC_KEY_LENGTH as u64)?;
  833. );
  834. let hash = translate_slice::<u8>(
  835. memory_mapping,
  836. hash_addr,
  837. keccak::HASH_BYTES as u64,
  838. invoke_context.get_check_aligned(),
  839. )?;
  840. let signature = translate_slice::<u8>(
  841. memory_mapping,
  842. signature_addr,
  843. SECP256K1_SIGNATURE_LENGTH as u64,
  844. invoke_context.get_check_aligned(),
  845. )?;
  846. let Ok(message) = libsecp256k1::Message::parse_slice(hash) else {
  847. return Ok(Secp256k1RecoverError::InvalidHash.into());
  848. };
  849. let Ok(adjusted_recover_id_val) = recovery_id_val.try_into() else {
  850. return Ok(Secp256k1RecoverError::InvalidRecoveryId.into());
  851. };
  852. let Ok(recovery_id) = libsecp256k1::RecoveryId::parse(adjusted_recover_id_val) else {
  853. return Ok(Secp256k1RecoverError::InvalidRecoveryId.into());
  854. };
  855. let Ok(signature) = libsecp256k1::Signature::parse_standard_slice(signature) else {
  856. return Ok(Secp256k1RecoverError::InvalidSignature.into());
  857. };
  858. let public_key = match libsecp256k1::recover(&message, &signature, &recovery_id) {
  859. Ok(key) => key.serialize(),
  860. Err(_) => {
  861. return Ok(Secp256k1RecoverError::InvalidSignature.into());
  862. }
  863. };
  864. secp256k1_recover_result.copy_from_slice(&public_key[1..65]);
  865. Ok(SUCCESS)
  866. }
  867. );
  868. declare_builtin_function!(
  869. // Elliptic Curve Point Validation
  870. //
  871. // Currently, only curve25519 Edwards and Ristretto representations are supported
  872. SyscallCurvePointValidation,
  873. fn rust(
  874. invoke_context: &mut InvokeContext,
  875. curve_id: u64,
  876. point_addr: u64,
  877. _arg3: u64,
  878. _arg4: u64,
  879. _arg5: u64,
  880. memory_mapping: &mut MemoryMapping,
  881. ) -> Result<u64, Error> {
  882. use solana_curve25519::{curve_syscall_traits::*, edwards, ristretto};
  883. match curve_id {
  884. CURVE25519_EDWARDS => {
  885. let cost = invoke_context
  886. .get_execution_cost()
  887. .curve25519_edwards_validate_point_cost;
  888. consume_compute_meter(invoke_context, cost)?;
  889. let point = translate_type::<edwards::PodEdwardsPoint>(
  890. memory_mapping,
  891. point_addr,
  892. invoke_context.get_check_aligned(),
  893. )?;
  894. if edwards::validate_edwards(point) {
  895. Ok(0)
  896. } else {
  897. Ok(1)
  898. }
  899. }
  900. CURVE25519_RISTRETTO => {
  901. let cost = invoke_context
  902. .get_execution_cost()
  903. .curve25519_ristretto_validate_point_cost;
  904. consume_compute_meter(invoke_context, cost)?;
  905. let point = translate_type::<ristretto::PodRistrettoPoint>(
  906. memory_mapping,
  907. point_addr,
  908. invoke_context.get_check_aligned(),
  909. )?;
  910. if ristretto::validate_ristretto(point) {
  911. Ok(0)
  912. } else {
  913. Ok(1)
  914. }
  915. }
  916. _ => {
  917. if invoke_context.get_feature_set().abort_on_invalid_curve {
  918. Err(SyscallError::InvalidAttribute.into())
  919. } else {
  920. Ok(1)
  921. }
  922. }
  923. }
  924. }
  925. );
  926. declare_builtin_function!(
  927. // Elliptic Curve Group Operations
  928. //
  929. // Currently, only curve25519 Edwards and Ristretto representations are supported
  930. SyscallCurveGroupOps,
  931. fn rust(
  932. invoke_context: &mut InvokeContext,
  933. curve_id: u64,
  934. group_op: u64,
  935. left_input_addr: u64,
  936. right_input_addr: u64,
  937. result_point_addr: u64,
  938. memory_mapping: &mut MemoryMapping,
  939. ) -> Result<u64, Error> {
  940. use solana_curve25519::{
  941. curve_syscall_traits::*,
  942. edwards::{self, PodEdwardsPoint},
  943. ristretto::{self, PodRistrettoPoint},
  944. scalar,
  945. };
  946. match curve_id {
  947. CURVE25519_EDWARDS => match group_op {
  948. ADD => {
  949. let cost = invoke_context
  950. .get_execution_cost()
  951. .curve25519_edwards_add_cost;
  952. consume_compute_meter(invoke_context, cost)?;
  953. let left_point = translate_type::<PodEdwardsPoint>(
  954. memory_mapping,
  955. left_input_addr,
  956. invoke_context.get_check_aligned(),
  957. )?;
  958. let right_point = translate_type::<PodEdwardsPoint>(
  959. memory_mapping,
  960. right_input_addr,
  961. invoke_context.get_check_aligned(),
  962. )?;
  963. if let Some(result_point) = edwards::add_edwards(left_point, right_point) {
  964. translate_mut!(
  965. memory_mapping,
  966. invoke_context.get_check_aligned(),
  967. let result_point_ref_mut: &mut PodEdwardsPoint = map(result_point_addr)?;
  968. );
  969. *result_point_ref_mut = result_point;
  970. Ok(0)
  971. } else {
  972. Ok(1)
  973. }
  974. }
  975. SUB => {
  976. let cost = invoke_context
  977. .get_execution_cost()
  978. .curve25519_edwards_subtract_cost;
  979. consume_compute_meter(invoke_context, cost)?;
  980. let left_point = translate_type::<PodEdwardsPoint>(
  981. memory_mapping,
  982. left_input_addr,
  983. invoke_context.get_check_aligned(),
  984. )?;
  985. let right_point = translate_type::<PodEdwardsPoint>(
  986. memory_mapping,
  987. right_input_addr,
  988. invoke_context.get_check_aligned(),
  989. )?;
  990. if let Some(result_point) = edwards::subtract_edwards(left_point, right_point) {
  991. translate_mut!(
  992. memory_mapping,
  993. invoke_context.get_check_aligned(),
  994. let result_point_ref_mut: &mut PodEdwardsPoint = map(result_point_addr)?;
  995. );
  996. *result_point_ref_mut = result_point;
  997. Ok(0)
  998. } else {
  999. Ok(1)
  1000. }
  1001. }
  1002. MUL => {
  1003. let cost = invoke_context
  1004. .get_execution_cost()
  1005. .curve25519_edwards_multiply_cost;
  1006. consume_compute_meter(invoke_context, cost)?;
  1007. let scalar = translate_type::<scalar::PodScalar>(
  1008. memory_mapping,
  1009. left_input_addr,
  1010. invoke_context.get_check_aligned(),
  1011. )?;
  1012. let input_point = translate_type::<PodEdwardsPoint>(
  1013. memory_mapping,
  1014. right_input_addr,
  1015. invoke_context.get_check_aligned(),
  1016. )?;
  1017. if let Some(result_point) = edwards::multiply_edwards(scalar, input_point) {
  1018. translate_mut!(
  1019. memory_mapping,
  1020. invoke_context.get_check_aligned(),
  1021. let result_point_ref_mut: &mut PodEdwardsPoint = map(result_point_addr)?;
  1022. );
  1023. *result_point_ref_mut = result_point;
  1024. Ok(0)
  1025. } else {
  1026. Ok(1)
  1027. }
  1028. }
  1029. _ => {
  1030. if invoke_context.get_feature_set().abort_on_invalid_curve {
  1031. Err(SyscallError::InvalidAttribute.into())
  1032. } else {
  1033. Ok(1)
  1034. }
  1035. }
  1036. },
  1037. CURVE25519_RISTRETTO => match group_op {
  1038. ADD => {
  1039. let cost = invoke_context
  1040. .get_execution_cost()
  1041. .curve25519_ristretto_add_cost;
  1042. consume_compute_meter(invoke_context, cost)?;
  1043. let left_point = translate_type::<PodRistrettoPoint>(
  1044. memory_mapping,
  1045. left_input_addr,
  1046. invoke_context.get_check_aligned(),
  1047. )?;
  1048. let right_point = translate_type::<PodRistrettoPoint>(
  1049. memory_mapping,
  1050. right_input_addr,
  1051. invoke_context.get_check_aligned(),
  1052. )?;
  1053. if let Some(result_point) = ristretto::add_ristretto(left_point, right_point) {
  1054. translate_mut!(
  1055. memory_mapping,
  1056. invoke_context.get_check_aligned(),
  1057. let result_point_ref_mut: &mut PodRistrettoPoint = map(result_point_addr)?;
  1058. );
  1059. *result_point_ref_mut = result_point;
  1060. Ok(0)
  1061. } else {
  1062. Ok(1)
  1063. }
  1064. }
  1065. SUB => {
  1066. let cost = invoke_context
  1067. .get_execution_cost()
  1068. .curve25519_ristretto_subtract_cost;
  1069. consume_compute_meter(invoke_context, cost)?;
  1070. let left_point = translate_type::<PodRistrettoPoint>(
  1071. memory_mapping,
  1072. left_input_addr,
  1073. invoke_context.get_check_aligned(),
  1074. )?;
  1075. let right_point = translate_type::<PodRistrettoPoint>(
  1076. memory_mapping,
  1077. right_input_addr,
  1078. invoke_context.get_check_aligned(),
  1079. )?;
  1080. if let Some(result_point) =
  1081. ristretto::subtract_ristretto(left_point, right_point)
  1082. {
  1083. translate_mut!(
  1084. memory_mapping,
  1085. invoke_context.get_check_aligned(),
  1086. let result_point_ref_mut: &mut PodRistrettoPoint = map(result_point_addr)?;
  1087. );
  1088. *result_point_ref_mut = result_point;
  1089. Ok(0)
  1090. } else {
  1091. Ok(1)
  1092. }
  1093. }
  1094. MUL => {
  1095. let cost = invoke_context
  1096. .get_execution_cost()
  1097. .curve25519_ristretto_multiply_cost;
  1098. consume_compute_meter(invoke_context, cost)?;
  1099. let scalar = translate_type::<scalar::PodScalar>(
  1100. memory_mapping,
  1101. left_input_addr,
  1102. invoke_context.get_check_aligned(),
  1103. )?;
  1104. let input_point = translate_type::<PodRistrettoPoint>(
  1105. memory_mapping,
  1106. right_input_addr,
  1107. invoke_context.get_check_aligned(),
  1108. )?;
  1109. if let Some(result_point) = ristretto::multiply_ristretto(scalar, input_point) {
  1110. translate_mut!(
  1111. memory_mapping,
  1112. invoke_context.get_check_aligned(),
  1113. let result_point_ref_mut: &mut PodRistrettoPoint = map(result_point_addr)?;
  1114. );
  1115. *result_point_ref_mut = result_point;
  1116. Ok(0)
  1117. } else {
  1118. Ok(1)
  1119. }
  1120. }
  1121. _ => {
  1122. if invoke_context.get_feature_set().abort_on_invalid_curve {
  1123. Err(SyscallError::InvalidAttribute.into())
  1124. } else {
  1125. Ok(1)
  1126. }
  1127. }
  1128. },
  1129. _ => {
  1130. if invoke_context.get_feature_set().abort_on_invalid_curve {
  1131. Err(SyscallError::InvalidAttribute.into())
  1132. } else {
  1133. Ok(1)
  1134. }
  1135. }
  1136. }
  1137. }
  1138. );
  1139. declare_builtin_function!(
  1140. // Elliptic Curve Multiscalar Multiplication
  1141. //
  1142. // Currently, only curve25519 Edwards and Ristretto representations are supported
  1143. SyscallCurveMultiscalarMultiplication,
  1144. fn rust(
  1145. invoke_context: &mut InvokeContext,
  1146. curve_id: u64,
  1147. scalars_addr: u64,
  1148. points_addr: u64,
  1149. points_len: u64,
  1150. result_point_addr: u64,
  1151. memory_mapping: &mut MemoryMapping,
  1152. ) -> Result<u64, Error> {
  1153. use solana_curve25519::{
  1154. curve_syscall_traits::*,
  1155. edwards::{self, PodEdwardsPoint},
  1156. ristretto::{self, PodRistrettoPoint},
  1157. scalar,
  1158. };
  1159. if points_len > 512 {
  1160. return Err(Box::new(SyscallError::InvalidLength));
  1161. }
  1162. match curve_id {
  1163. CURVE25519_EDWARDS => {
  1164. let cost = invoke_context
  1165. .get_execution_cost()
  1166. .curve25519_edwards_msm_base_cost
  1167. .saturating_add(
  1168. invoke_context
  1169. .get_execution_cost()
  1170. .curve25519_edwards_msm_incremental_cost
  1171. .saturating_mul(points_len.saturating_sub(1)),
  1172. );
  1173. consume_compute_meter(invoke_context, cost)?;
  1174. let scalars = translate_slice::<scalar::PodScalar>(
  1175. memory_mapping,
  1176. scalars_addr,
  1177. points_len,
  1178. invoke_context.get_check_aligned(),
  1179. )?;
  1180. let points = translate_slice::<PodEdwardsPoint>(
  1181. memory_mapping,
  1182. points_addr,
  1183. points_len,
  1184. invoke_context.get_check_aligned(),
  1185. )?;
  1186. if let Some(result_point) = edwards::multiscalar_multiply_edwards(scalars, points) {
  1187. translate_mut!(
  1188. memory_mapping,
  1189. invoke_context.get_check_aligned(),
  1190. let result_point_ref_mut: &mut PodEdwardsPoint = map(result_point_addr)?;
  1191. );
  1192. *result_point_ref_mut = result_point;
  1193. Ok(0)
  1194. } else {
  1195. Ok(1)
  1196. }
  1197. }
  1198. CURVE25519_RISTRETTO => {
  1199. let cost = invoke_context
  1200. .get_execution_cost()
  1201. .curve25519_ristretto_msm_base_cost
  1202. .saturating_add(
  1203. invoke_context
  1204. .get_execution_cost()
  1205. .curve25519_ristretto_msm_incremental_cost
  1206. .saturating_mul(points_len.saturating_sub(1)),
  1207. );
  1208. consume_compute_meter(invoke_context, cost)?;
  1209. let scalars = translate_slice::<scalar::PodScalar>(
  1210. memory_mapping,
  1211. scalars_addr,
  1212. points_len,
  1213. invoke_context.get_check_aligned(),
  1214. )?;
  1215. let points = translate_slice::<PodRistrettoPoint>(
  1216. memory_mapping,
  1217. points_addr,
  1218. points_len,
  1219. invoke_context.get_check_aligned(),
  1220. )?;
  1221. if let Some(result_point) =
  1222. ristretto::multiscalar_multiply_ristretto(scalars, points)
  1223. {
  1224. translate_mut!(
  1225. memory_mapping,
  1226. invoke_context.get_check_aligned(),
  1227. let result_point_ref_mut: &mut PodRistrettoPoint = map(result_point_addr)?;
  1228. );
  1229. *result_point_ref_mut = result_point;
  1230. Ok(0)
  1231. } else {
  1232. Ok(1)
  1233. }
  1234. }
  1235. _ => {
  1236. if invoke_context.get_feature_set().abort_on_invalid_curve {
  1237. Err(SyscallError::InvalidAttribute.into())
  1238. } else {
  1239. Ok(1)
  1240. }
  1241. }
  1242. }
  1243. }
  1244. );
  1245. declare_builtin_function!(
  1246. /// Set return data
  1247. SyscallSetReturnData,
  1248. fn rust(
  1249. invoke_context: &mut InvokeContext,
  1250. addr: u64,
  1251. len: u64,
  1252. _arg3: u64,
  1253. _arg4: u64,
  1254. _arg5: u64,
  1255. memory_mapping: &mut MemoryMapping,
  1256. ) -> Result<u64, Error> {
  1257. let execution_cost = invoke_context.get_execution_cost();
  1258. let cost = len
  1259. .checked_div(execution_cost.cpi_bytes_per_unit)
  1260. .unwrap_or(u64::MAX)
  1261. .saturating_add(execution_cost.syscall_base_cost);
  1262. consume_compute_meter(invoke_context, cost)?;
  1263. if len > MAX_RETURN_DATA as u64 {
  1264. return Err(SyscallError::ReturnDataTooLarge(len, MAX_RETURN_DATA as u64).into());
  1265. }
  1266. let return_data = if len == 0 {
  1267. Vec::new()
  1268. } else {
  1269. translate_slice::<u8>(
  1270. memory_mapping,
  1271. addr,
  1272. len,
  1273. invoke_context.get_check_aligned(),
  1274. )?
  1275. .to_vec()
  1276. };
  1277. let transaction_context = &mut invoke_context.transaction_context;
  1278. let program_id = *transaction_context
  1279. .get_current_instruction_context()
  1280. .and_then(|instruction_context| {
  1281. instruction_context.get_program_key()
  1282. })?;
  1283. transaction_context.set_return_data(program_id, return_data)?;
  1284. Ok(0)
  1285. }
  1286. );
  1287. declare_builtin_function!(
  1288. /// Get return data
  1289. SyscallGetReturnData,
  1290. fn rust(
  1291. invoke_context: &mut InvokeContext,
  1292. return_data_addr: u64,
  1293. length: u64,
  1294. program_id_addr: u64,
  1295. _arg4: u64,
  1296. _arg5: u64,
  1297. memory_mapping: &mut MemoryMapping,
  1298. ) -> Result<u64, Error> {
  1299. let execution_cost = invoke_context.get_execution_cost();
  1300. consume_compute_meter(invoke_context, execution_cost.syscall_base_cost)?;
  1301. let (program_id, return_data) = invoke_context.transaction_context.get_return_data();
  1302. let length = length.min(return_data.len() as u64);
  1303. if length != 0 {
  1304. let cost = length
  1305. .saturating_add(size_of::<Pubkey>() as u64)
  1306. .checked_div(execution_cost.cpi_bytes_per_unit)
  1307. .unwrap_or(u64::MAX);
  1308. consume_compute_meter(invoke_context, cost)?;
  1309. translate_mut!(
  1310. memory_mapping,
  1311. invoke_context.get_check_aligned(),
  1312. let return_data_result: &mut [u8] = map(return_data_addr, length)?;
  1313. let program_id_result: &mut Pubkey = map(program_id_addr)?;
  1314. );
  1315. let to_slice = return_data_result;
  1316. let from_slice = return_data
  1317. .get(..length as usize)
  1318. .ok_or(SyscallError::InvokeContextBorrowFailed)?;
  1319. if to_slice.len() != from_slice.len() {
  1320. return Err(SyscallError::InvalidLength.into());
  1321. }
  1322. to_slice.copy_from_slice(from_slice);
  1323. *program_id_result = *program_id;
  1324. }
  1325. // Return the actual length, rather the length returned
  1326. Ok(return_data.len() as u64)
  1327. }
  1328. );
  1329. declare_builtin_function!(
  1330. /// Get a processed sigling instruction
  1331. SyscallGetProcessedSiblingInstruction,
  1332. fn rust(
  1333. invoke_context: &mut InvokeContext,
  1334. index: u64,
  1335. meta_addr: u64,
  1336. program_id_addr: u64,
  1337. data_addr: u64,
  1338. accounts_addr: u64,
  1339. memory_mapping: &mut MemoryMapping,
  1340. ) -> Result<u64, Error> {
  1341. let execution_cost = invoke_context.get_execution_cost();
  1342. consume_compute_meter(invoke_context, execution_cost.syscall_base_cost)?;
  1343. // Reverse iterate through the instruction trace,
  1344. // ignoring anything except instructions on the same level
  1345. let stack_height = invoke_context.get_stack_height();
  1346. let instruction_trace_length = invoke_context
  1347. .transaction_context
  1348. .get_instruction_trace_length();
  1349. let mut reverse_index_at_stack_height = 0;
  1350. let mut found_instruction_context = None;
  1351. for index_in_trace in (0..instruction_trace_length).rev() {
  1352. let instruction_context = invoke_context
  1353. .transaction_context
  1354. .get_instruction_context_at_index_in_trace(index_in_trace)?;
  1355. if instruction_context.get_stack_height() < stack_height {
  1356. break;
  1357. }
  1358. if instruction_context.get_stack_height() == stack_height {
  1359. if index.saturating_add(1) == reverse_index_at_stack_height {
  1360. found_instruction_context = Some(instruction_context);
  1361. break;
  1362. }
  1363. reverse_index_at_stack_height = reverse_index_at_stack_height.saturating_add(1);
  1364. }
  1365. }
  1366. if let Some(instruction_context) = found_instruction_context {
  1367. translate_mut!(
  1368. memory_mapping,
  1369. invoke_context.get_check_aligned(),
  1370. let result_header: &mut ProcessedSiblingInstruction = map(meta_addr)?;
  1371. );
  1372. if result_header.data_len == (instruction_context.get_instruction_data().len() as u64)
  1373. && result_header.accounts_len
  1374. == (instruction_context.get_number_of_instruction_accounts() as u64)
  1375. {
  1376. translate_mut!(
  1377. memory_mapping,
  1378. invoke_context.get_check_aligned(),
  1379. let program_id: &mut Pubkey = map(program_id_addr)?;
  1380. let data: &mut [u8] = map(data_addr, result_header.data_len)?;
  1381. let accounts: &mut [AccountMeta] = map(accounts_addr, result_header.accounts_len)?;
  1382. let result_header: &mut ProcessedSiblingInstruction = map(meta_addr)?;
  1383. );
  1384. // Marks result_header used. It had to be in translate_mut!() for the overlap checks.
  1385. let _ = result_header;
  1386. *program_id = *instruction_context
  1387. .get_program_key()?;
  1388. data.clone_from_slice(instruction_context.get_instruction_data());
  1389. let account_metas = (0..instruction_context.get_number_of_instruction_accounts())
  1390. .map(|instruction_account_index| {
  1391. Ok(AccountMeta {
  1392. pubkey: *instruction_context.get_key_of_instruction_account(instruction_account_index)?,
  1393. is_signer: instruction_context
  1394. .is_instruction_account_signer(instruction_account_index)?,
  1395. is_writable: instruction_context
  1396. .is_instruction_account_writable(instruction_account_index)?,
  1397. })
  1398. })
  1399. .collect::<Result<Vec<_>, InstructionError>>()?;
  1400. accounts.clone_from_slice(account_metas.as_slice());
  1401. } else {
  1402. result_header.data_len = instruction_context.get_instruction_data().len() as u64;
  1403. result_header.accounts_len =
  1404. instruction_context.get_number_of_instruction_accounts() as u64;
  1405. }
  1406. return Ok(true as u64);
  1407. }
  1408. Ok(false as u64)
  1409. }
  1410. );
  1411. declare_builtin_function!(
  1412. /// Get current call stack height
  1413. SyscallGetStackHeight,
  1414. fn rust(
  1415. invoke_context: &mut InvokeContext,
  1416. _arg1: u64,
  1417. _arg2: u64,
  1418. _arg3: u64,
  1419. _arg4: u64,
  1420. _arg5: u64,
  1421. _memory_mapping: &mut MemoryMapping,
  1422. ) -> Result<u64, Error> {
  1423. let execution_cost = invoke_context.get_execution_cost();
  1424. consume_compute_meter(invoke_context, execution_cost.syscall_base_cost)?;
  1425. Ok(invoke_context.get_stack_height() as u64)
  1426. }
  1427. );
  1428. declare_builtin_function!(
  1429. /// alt_bn128 group operations
  1430. SyscallAltBn128,
  1431. fn rust(
  1432. invoke_context: &mut InvokeContext,
  1433. group_op: u64,
  1434. input_addr: u64,
  1435. input_size: u64,
  1436. result_addr: u64,
  1437. _arg5: u64,
  1438. memory_mapping: &mut MemoryMapping,
  1439. ) -> Result<u64, Error> {
  1440. use solana_bn254::versioned::{
  1441. alt_bn128_versioned_g1_addition, alt_bn128_versioned_g1_multiplication,
  1442. alt_bn128_versioned_pairing, Endianness, VersionedG1Addition,
  1443. VersionedG1Multiplication, VersionedPairing, ALT_BN128_ADDITION_OUTPUT_SIZE,
  1444. ALT_BN128_G1_ADD_BE, ALT_BN128_G1_MUL_BE, ALT_BN128_MULTIPLICATION_OUTPUT_SIZE,
  1445. ALT_BN128_PAIRING_BE, ALT_BN128_PAIRING_ELEMENT_SIZE,
  1446. ALT_BN128_PAIRING_OUTPUT_SIZE,
  1447. };
  1448. let execution_cost = invoke_context.get_execution_cost();
  1449. let (cost, output): (u64, usize) = match group_op {
  1450. ALT_BN128_G1_ADD_BE => (
  1451. execution_cost.alt_bn128_addition_cost,
  1452. ALT_BN128_ADDITION_OUTPUT_SIZE,
  1453. ),
  1454. ALT_BN128_G1_MUL_BE => (
  1455. execution_cost.alt_bn128_multiplication_cost,
  1456. ALT_BN128_MULTIPLICATION_OUTPUT_SIZE,
  1457. ),
  1458. ALT_BN128_PAIRING_BE => {
  1459. let ele_len = input_size
  1460. .checked_div(ALT_BN128_PAIRING_ELEMENT_SIZE as u64)
  1461. .expect("div by non-zero constant");
  1462. let cost = execution_cost
  1463. .alt_bn128_pairing_one_pair_cost_first
  1464. .saturating_add(
  1465. execution_cost
  1466. .alt_bn128_pairing_one_pair_cost_other
  1467. .saturating_mul(ele_len.saturating_sub(1)),
  1468. )
  1469. .saturating_add(execution_cost.sha256_base_cost)
  1470. .saturating_add(input_size)
  1471. .saturating_add(ALT_BN128_PAIRING_OUTPUT_SIZE as u64);
  1472. (cost, ALT_BN128_PAIRING_OUTPUT_SIZE)
  1473. }
  1474. _ => {
  1475. return Err(SyscallError::InvalidAttribute.into());
  1476. }
  1477. };
  1478. consume_compute_meter(invoke_context, cost)?;
  1479. translate_mut!(
  1480. memory_mapping,
  1481. invoke_context.get_check_aligned(),
  1482. let call_result: &mut [u8] = map(result_addr, output as u64)?;
  1483. );
  1484. let input = translate_slice::<u8>(
  1485. memory_mapping,
  1486. input_addr,
  1487. input_size,
  1488. invoke_context.get_check_aligned(),
  1489. )?;
  1490. let result_point = match group_op {
  1491. ALT_BN128_G1_ADD_BE => {
  1492. alt_bn128_versioned_g1_addition(VersionedG1Addition::V0, input, Endianness::BE)
  1493. }
  1494. ALT_BN128_G1_MUL_BE => {
  1495. alt_bn128_versioned_g1_multiplication(
  1496. VersionedG1Multiplication::V1,
  1497. input,
  1498. Endianness::BE
  1499. )
  1500. }
  1501. ALT_BN128_PAIRING_BE => {
  1502. alt_bn128_versioned_pairing(VersionedPairing::V0, input, Endianness::BE)
  1503. }
  1504. _ => {
  1505. return Err(SyscallError::InvalidAttribute.into());
  1506. }
  1507. };
  1508. match result_point {
  1509. Ok(point) => {
  1510. call_result.copy_from_slice(&point);
  1511. Ok(SUCCESS)
  1512. }
  1513. Err(_) => {
  1514. Ok(1)
  1515. }
  1516. }
  1517. }
  1518. );
  1519. declare_builtin_function!(
  1520. /// Big integer modular exponentiation
  1521. SyscallBigModExp,
  1522. fn rust(
  1523. invoke_context: &mut InvokeContext,
  1524. params: u64,
  1525. return_value: u64,
  1526. _arg3: u64,
  1527. _arg4: u64,
  1528. _arg5: u64,
  1529. memory_mapping: &mut MemoryMapping,
  1530. ) -> Result<u64, Error> {
  1531. let params = &translate_slice::<BigModExpParams>(
  1532. memory_mapping,
  1533. params,
  1534. 1,
  1535. invoke_context.get_check_aligned(),
  1536. )?
  1537. .first()
  1538. .ok_or(SyscallError::InvalidLength)?;
  1539. if params.base_len > 512 || params.exponent_len > 512 || params.modulus_len > 512 {
  1540. return Err(Box::new(SyscallError::InvalidLength));
  1541. }
  1542. let input_len: u64 = std::cmp::max(params.base_len, params.exponent_len);
  1543. let input_len: u64 = std::cmp::max(input_len, params.modulus_len);
  1544. let execution_cost = invoke_context.get_execution_cost();
  1545. // the compute units are calculated by the quadratic equation `0.5 input_len^2 + 190`
  1546. consume_compute_meter(
  1547. invoke_context,
  1548. execution_cost.syscall_base_cost.saturating_add(
  1549. input_len
  1550. .saturating_mul(input_len)
  1551. .checked_div(execution_cost.big_modular_exponentiation_cost_divisor)
  1552. .unwrap_or(u64::MAX)
  1553. .saturating_add(execution_cost.big_modular_exponentiation_base_cost),
  1554. ),
  1555. )?;
  1556. let base = translate_slice::<u8>(
  1557. memory_mapping,
  1558. params.base as *const _ as u64,
  1559. params.base_len,
  1560. invoke_context.get_check_aligned(),
  1561. )?;
  1562. let exponent = translate_slice::<u8>(
  1563. memory_mapping,
  1564. params.exponent as *const _ as u64,
  1565. params.exponent_len,
  1566. invoke_context.get_check_aligned(),
  1567. )?;
  1568. let modulus = translate_slice::<u8>(
  1569. memory_mapping,
  1570. params.modulus as *const _ as u64,
  1571. params.modulus_len,
  1572. invoke_context.get_check_aligned(),
  1573. )?;
  1574. let value = big_mod_exp(base, exponent, modulus);
  1575. translate_mut!(
  1576. memory_mapping,
  1577. invoke_context.get_check_aligned(),
  1578. let return_value_ref_mut: &mut [u8] = map(return_value, params.modulus_len)?;
  1579. );
  1580. return_value_ref_mut.copy_from_slice(value.as_slice());
  1581. Ok(0)
  1582. }
  1583. );
  1584. declare_builtin_function!(
  1585. // Poseidon
  1586. SyscallPoseidon,
  1587. fn rust(
  1588. invoke_context: &mut InvokeContext,
  1589. parameters: u64,
  1590. endianness: u64,
  1591. vals_addr: u64,
  1592. vals_len: u64,
  1593. result_addr: u64,
  1594. memory_mapping: &mut MemoryMapping,
  1595. ) -> Result<u64, Error> {
  1596. let parameters: poseidon::Parameters = parameters.try_into()?;
  1597. let endianness: poseidon::Endianness = endianness.try_into()?;
  1598. if vals_len > 12 {
  1599. ic_msg!(
  1600. invoke_context,
  1601. "Poseidon hashing {} sequences is not supported",
  1602. vals_len,
  1603. );
  1604. return Err(SyscallError::InvalidLength.into());
  1605. }
  1606. let execution_cost = invoke_context.get_execution_cost();
  1607. let Some(cost) = execution_cost.poseidon_cost(vals_len) else {
  1608. ic_msg!(
  1609. invoke_context,
  1610. "Overflow while calculating the compute cost"
  1611. );
  1612. return Err(SyscallError::ArithmeticOverflow.into());
  1613. };
  1614. consume_compute_meter(invoke_context, cost.to_owned())?;
  1615. translate_mut!(
  1616. memory_mapping,
  1617. invoke_context.get_check_aligned(),
  1618. let hash_result: &mut [u8] = map(result_addr, poseidon::HASH_BYTES as u64)?;
  1619. );
  1620. let inputs = translate_slice::<VmSlice<u8>>(
  1621. memory_mapping,
  1622. vals_addr,
  1623. vals_len,
  1624. invoke_context.get_check_aligned(),
  1625. )?;
  1626. let inputs = inputs
  1627. .iter()
  1628. .map(|input| {
  1629. translate_vm_slice(input, memory_mapping, invoke_context.get_check_aligned())
  1630. })
  1631. .collect::<Result<Vec<_>, Error>>()?;
  1632. let result = if invoke_context.get_feature_set().poseidon_enforce_padding {
  1633. poseidon::hashv(parameters, endianness, inputs.as_slice())
  1634. } else {
  1635. poseidon::legacy::hashv(parameters, endianness, inputs.as_slice())
  1636. };
  1637. let Ok(hash) = result else {
  1638. return Ok(1);
  1639. };
  1640. hash_result.copy_from_slice(&hash.to_bytes());
  1641. Ok(SUCCESS)
  1642. }
  1643. );
  1644. declare_builtin_function!(
  1645. /// Read remaining compute units
  1646. SyscallRemainingComputeUnits,
  1647. fn rust(
  1648. invoke_context: &mut InvokeContext,
  1649. _arg1: u64,
  1650. _arg2: u64,
  1651. _arg3: u64,
  1652. _arg4: u64,
  1653. _arg5: u64,
  1654. _memory_mapping: &mut MemoryMapping,
  1655. ) -> Result<u64, Error> {
  1656. let execution_cost = invoke_context.get_execution_cost();
  1657. consume_compute_meter(invoke_context, execution_cost.syscall_base_cost)?;
  1658. use solana_sbpf::vm::ContextObject;
  1659. Ok(invoke_context.get_remaining())
  1660. }
  1661. );
  1662. declare_builtin_function!(
  1663. /// alt_bn128 g1 and g2 compression and decompression
  1664. SyscallAltBn128Compression,
  1665. fn rust(
  1666. invoke_context: &mut InvokeContext,
  1667. op: u64,
  1668. input_addr: u64,
  1669. input_size: u64,
  1670. result_addr: u64,
  1671. _arg5: u64,
  1672. memory_mapping: &mut MemoryMapping,
  1673. ) -> Result<u64, Error> {
  1674. use solana_bn254::{
  1675. prelude::{ALT_BN128_G1_POINT_SIZE, ALT_BN128_G2_POINT_SIZE},
  1676. compression::prelude::{
  1677. alt_bn128_g1_compress, alt_bn128_g1_decompress, alt_bn128_g2_compress,
  1678. alt_bn128_g2_decompress, ALT_BN128_G1_COMPRESS_BE, ALT_BN128_G1_DECOMPRESS_BE,
  1679. ALT_BN128_G2_COMPRESS_BE, ALT_BN128_G2_DECOMPRESS_BE, ALT_BN128_G1_COMPRESSED_POINT_SIZE,
  1680. ALT_BN128_G2_COMPRESSED_POINT_SIZE,
  1681. }
  1682. };
  1683. let execution_cost = invoke_context.get_execution_cost();
  1684. let base_cost = execution_cost.syscall_base_cost;
  1685. let (cost, output): (u64, usize) = match op {
  1686. ALT_BN128_G1_COMPRESS_BE => (
  1687. base_cost.saturating_add(execution_cost.alt_bn128_g1_compress),
  1688. ALT_BN128_G1_COMPRESSED_POINT_SIZE,
  1689. ),
  1690. ALT_BN128_G1_DECOMPRESS_BE => {
  1691. (base_cost.saturating_add(execution_cost.alt_bn128_g1_decompress), ALT_BN128_G1_POINT_SIZE)
  1692. }
  1693. ALT_BN128_G2_COMPRESS_BE => (
  1694. base_cost.saturating_add(execution_cost.alt_bn128_g2_compress),
  1695. ALT_BN128_G2_COMPRESSED_POINT_SIZE,
  1696. ),
  1697. ALT_BN128_G2_DECOMPRESS_BE => {
  1698. (base_cost.saturating_add(execution_cost.alt_bn128_g2_decompress), ALT_BN128_G2_POINT_SIZE)
  1699. }
  1700. _ => {
  1701. return Err(SyscallError::InvalidAttribute.into());
  1702. }
  1703. };
  1704. consume_compute_meter(invoke_context, cost)?;
  1705. translate_mut!(
  1706. memory_mapping,
  1707. invoke_context.get_check_aligned(),
  1708. let call_result: &mut [u8] = map(result_addr, output as u64)?;
  1709. );
  1710. let input = translate_slice::<u8>(
  1711. memory_mapping,
  1712. input_addr,
  1713. input_size,
  1714. invoke_context.get_check_aligned(),
  1715. )?;
  1716. match op {
  1717. ALT_BN128_G1_COMPRESS_BE => {
  1718. let Ok(result_point) = alt_bn128_g1_compress(input) else {
  1719. return Ok(1);
  1720. };
  1721. call_result.copy_from_slice(&result_point);
  1722. }
  1723. ALT_BN128_G1_DECOMPRESS_BE => {
  1724. let Ok(result_point) = alt_bn128_g1_decompress(input) else {
  1725. return Ok(1);
  1726. };
  1727. call_result.copy_from_slice(&result_point);
  1728. }
  1729. ALT_BN128_G2_COMPRESS_BE => {
  1730. let Ok(result_point) = alt_bn128_g2_compress(input) else {
  1731. return Ok(1);
  1732. };
  1733. call_result.copy_from_slice(&result_point);
  1734. }
  1735. ALT_BN128_G2_DECOMPRESS_BE => {
  1736. let Ok(result_point) = alt_bn128_g2_decompress(input) else {
  1737. return Ok(1);
  1738. };
  1739. call_result.copy_from_slice(&result_point);
  1740. }
  1741. _ => return Err(SyscallError::InvalidAttribute.into()),
  1742. }
  1743. Ok(SUCCESS)
  1744. }
  1745. );
  1746. declare_builtin_function!(
  1747. // Generic Hashing Syscall
  1748. SyscallHash<H: HasherImpl>,
  1749. fn rust(
  1750. invoke_context: &mut InvokeContext,
  1751. vals_addr: u64,
  1752. vals_len: u64,
  1753. result_addr: u64,
  1754. _arg4: u64,
  1755. _arg5: u64,
  1756. memory_mapping: &mut MemoryMapping,
  1757. ) -> Result<u64, Error> {
  1758. let compute_budget = invoke_context.get_compute_budget();
  1759. let compute_cost = invoke_context.get_execution_cost();
  1760. let hash_base_cost = H::get_base_cost(compute_cost);
  1761. let hash_byte_cost = H::get_byte_cost(compute_cost);
  1762. let hash_max_slices = H::get_max_slices(compute_budget);
  1763. if hash_max_slices < vals_len {
  1764. ic_msg!(
  1765. invoke_context,
  1766. "{} Hashing {} sequences in one syscall is over the limit {}",
  1767. H::NAME,
  1768. vals_len,
  1769. hash_max_slices,
  1770. );
  1771. return Err(SyscallError::TooManySlices.into());
  1772. }
  1773. consume_compute_meter(invoke_context, hash_base_cost)?;
  1774. translate_mut!(
  1775. memory_mapping,
  1776. invoke_context.get_check_aligned(),
  1777. let hash_result: &mut [u8] = map(result_addr, std::mem::size_of::<H::Output>() as u64)?;
  1778. );
  1779. let mut hasher = H::create_hasher();
  1780. if vals_len > 0 {
  1781. let vals = translate_slice::<VmSlice<u8>>(
  1782. memory_mapping,
  1783. vals_addr,
  1784. vals_len,
  1785. invoke_context.get_check_aligned(),
  1786. )?;
  1787. for val in vals.iter() {
  1788. let bytes = translate_vm_slice(val, memory_mapping, invoke_context.get_check_aligned())?;
  1789. let cost = compute_cost.mem_op_base_cost.max(
  1790. hash_byte_cost.saturating_mul(
  1791. val.len()
  1792. .checked_div(2)
  1793. .expect("div by non-zero literal"),
  1794. ),
  1795. );
  1796. consume_compute_meter(invoke_context, cost)?;
  1797. hasher.hash(bytes);
  1798. }
  1799. }
  1800. hash_result.copy_from_slice(hasher.result().as_ref());
  1801. Ok(0)
  1802. }
  1803. );
  1804. declare_builtin_function!(
  1805. // Get Epoch Stake Syscall
  1806. SyscallGetEpochStake,
  1807. fn rust(
  1808. invoke_context: &mut InvokeContext,
  1809. var_addr: u64,
  1810. _arg2: u64,
  1811. _arg3: u64,
  1812. _arg4: u64,
  1813. _arg5: u64,
  1814. memory_mapping: &mut MemoryMapping,
  1815. ) -> Result<u64, Error> {
  1816. let compute_cost = invoke_context.get_execution_cost();
  1817. if var_addr == 0 {
  1818. // As specified by SIMD-0133: If `var_addr` is a null pointer:
  1819. //
  1820. // Compute units:
  1821. //
  1822. // ```
  1823. // syscall_base
  1824. // ```
  1825. let compute_units = compute_cost.syscall_base_cost;
  1826. consume_compute_meter(invoke_context, compute_units)?;
  1827. //
  1828. // Control flow:
  1829. //
  1830. // - The syscall aborts the virtual machine if:
  1831. // - Compute budget is exceeded.
  1832. // - Otherwise, the syscall returns a `u64` integer representing the total active
  1833. // stake on the cluster for the current epoch.
  1834. Ok(invoke_context.get_epoch_stake())
  1835. } else {
  1836. // As specified by SIMD-0133: If `var_addr` is _not_ a null pointer:
  1837. //
  1838. // Compute units:
  1839. //
  1840. // ```
  1841. // syscall_base + floor(PUBKEY_BYTES/cpi_bytes_per_unit) + mem_op_base
  1842. // ```
  1843. let compute_units = compute_cost
  1844. .syscall_base_cost
  1845. .saturating_add(
  1846. (PUBKEY_BYTES as u64)
  1847. .checked_div(compute_cost.cpi_bytes_per_unit)
  1848. .unwrap_or(u64::MAX),
  1849. )
  1850. .saturating_add(compute_cost.mem_op_base_cost);
  1851. consume_compute_meter(invoke_context, compute_units)?;
  1852. //
  1853. // Control flow:
  1854. //
  1855. // - The syscall aborts the virtual machine if:
  1856. // - Not all bytes in VM memory range `[vote_addr, vote_addr + 32)` are
  1857. // readable.
  1858. // - Compute budget is exceeded.
  1859. // - Otherwise, the syscall returns a `u64` integer representing the total active
  1860. // stake delegated to the vote account at the provided address.
  1861. // If the provided vote address corresponds to an account that is not a vote
  1862. // account or does not exist, the syscall will return `0` for active stake.
  1863. let check_aligned = invoke_context.get_check_aligned();
  1864. let vote_address = translate_type::<Pubkey>(memory_mapping, var_addr, check_aligned)?;
  1865. Ok(invoke_context.get_epoch_stake_for_vote_account(vote_address))
  1866. }
  1867. }
  1868. );
  1869. #[cfg(test)]
  1870. #[allow(clippy::arithmetic_side_effects)]
  1871. #[allow(clippy::indexing_slicing)]
  1872. mod tests {
  1873. #[allow(deprecated)]
  1874. use solana_sysvar::fees::Fees;
  1875. use {
  1876. super::*,
  1877. assert_matches::assert_matches,
  1878. core::slice,
  1879. solana_account::{create_account_shared_data_for_test, AccountSharedData},
  1880. solana_account_info::AccountInfo,
  1881. solana_clock::Clock,
  1882. solana_epoch_rewards::EpochRewards,
  1883. solana_epoch_schedule::EpochSchedule,
  1884. solana_fee_calculator::FeeCalculator,
  1885. solana_hash::HASH_BYTES,
  1886. solana_instruction::Instruction,
  1887. solana_last_restart_slot::LastRestartSlot,
  1888. solana_program::program::check_type_assumptions,
  1889. solana_program_runtime::{
  1890. execution_budget::MAX_HEAP_FRAME_BYTES,
  1891. invoke_context::{BpfAllocator, InvokeContext, SyscallContext},
  1892. memory::address_is_aligned,
  1893. with_mock_invoke_context,
  1894. },
  1895. solana_sbpf::{
  1896. aligned_memory::AlignedMemory,
  1897. ebpf::{self, HOST_ALIGN},
  1898. error::EbpfError,
  1899. memory_region::{MemoryMapping, MemoryRegion},
  1900. program::SBPFVersion,
  1901. vm::Config,
  1902. },
  1903. solana_sdk_ids::{
  1904. bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, native_loader, sysvar,
  1905. },
  1906. solana_sha256_hasher::hashv,
  1907. solana_slot_hashes::{self as slot_hashes, SlotHashes},
  1908. solana_stable_layout::stable_instruction::StableInstruction,
  1909. solana_stake_interface::stake_history::{self, StakeHistory, StakeHistoryEntry},
  1910. solana_sysvar_id::SysvarId,
  1911. solana_transaction_context::{IndexOfAccount, InstructionAccount},
  1912. std::{
  1913. hash::{DefaultHasher, Hash, Hasher},
  1914. mem,
  1915. str::FromStr,
  1916. },
  1917. test_case::test_case,
  1918. };
  1919. macro_rules! assert_access_violation {
  1920. ($result:expr, $va:expr, $len:expr) => {
  1921. match $result.unwrap_err().downcast_ref::<EbpfError>().unwrap() {
  1922. EbpfError::AccessViolation(_, va, len, _) if $va == *va && $len == *len => {}
  1923. EbpfError::StackAccessViolation(_, va, len, _) if $va == *va && $len == *len => {}
  1924. _ => panic!(),
  1925. }
  1926. };
  1927. }
  1928. macro_rules! prepare_mockup {
  1929. ($invoke_context:ident,
  1930. $program_key:ident,
  1931. $loader_key:expr $(,)?) => {
  1932. let $program_key = Pubkey::new_unique();
  1933. let transaction_accounts = vec![
  1934. (
  1935. $loader_key,
  1936. AccountSharedData::new(0, 0, &native_loader::id()),
  1937. ),
  1938. ($program_key, AccountSharedData::new(0, 0, &$loader_key)),
  1939. ];
  1940. with_mock_invoke_context!($invoke_context, transaction_context, transaction_accounts);
  1941. $invoke_context
  1942. .transaction_context
  1943. .configure_next_instruction_for_tests(1, vec![], vec![])
  1944. .unwrap();
  1945. $invoke_context.push().unwrap();
  1946. };
  1947. }
  1948. #[allow(dead_code)]
  1949. struct MockSlice {
  1950. vm_addr: u64,
  1951. len: usize,
  1952. }
  1953. #[test]
  1954. fn test_translate() {
  1955. const START: u64 = 0x100000000;
  1956. const LENGTH: u64 = 1000;
  1957. let data = vec![0u8; LENGTH as usize];
  1958. let addr = data.as_ptr() as u64;
  1959. let config = Config::default();
  1960. let memory_mapping = MemoryMapping::new(
  1961. vec![MemoryRegion::new_readonly(&data, START)],
  1962. &config,
  1963. SBPFVersion::V3,
  1964. )
  1965. .unwrap();
  1966. let cases = vec![
  1967. (true, START, 0, addr),
  1968. (true, START, 1, addr),
  1969. (true, START, LENGTH, addr),
  1970. (true, START + 1, LENGTH - 1, addr + 1),
  1971. (false, START + 1, LENGTH, 0),
  1972. (true, START + LENGTH - 1, 1, addr + LENGTH - 1),
  1973. (true, START + LENGTH, 0, addr + LENGTH),
  1974. (false, START + LENGTH, 1, 0),
  1975. (false, START, LENGTH + 1, 0),
  1976. (false, 0, 0, 0),
  1977. (false, 0, 1, 0),
  1978. (false, START - 1, 0, 0),
  1979. (false, START - 1, 1, 0),
  1980. (true, START + LENGTH / 2, LENGTH / 2, addr + LENGTH / 2),
  1981. ];
  1982. for (ok, start, length, value) in cases {
  1983. if ok {
  1984. assert_eq!(
  1985. translate_inner!(&memory_mapping, map, AccessType::Load, start, length)
  1986. .unwrap(),
  1987. value
  1988. )
  1989. } else {
  1990. assert!(
  1991. translate_inner!(&memory_mapping, map, AccessType::Load, start, length)
  1992. .is_err()
  1993. )
  1994. }
  1995. }
  1996. }
  1997. #[test]
  1998. fn test_translate_type() {
  1999. let config = Config::default();
  2000. // Pubkey
  2001. let pubkey = solana_pubkey::new_rand();
  2002. let memory_mapping = MemoryMapping::new(
  2003. vec![MemoryRegion::new_readonly(bytes_of(&pubkey), 0x100000000)],
  2004. &config,
  2005. SBPFVersion::V3,
  2006. )
  2007. .unwrap();
  2008. let translated_pubkey =
  2009. translate_type::<Pubkey>(&memory_mapping, 0x100000000, true).unwrap();
  2010. assert_eq!(pubkey, *translated_pubkey);
  2011. // Instruction
  2012. let instruction = Instruction::new_with_bincode(
  2013. solana_pubkey::new_rand(),
  2014. &"foobar",
  2015. vec![AccountMeta::new(solana_pubkey::new_rand(), false)],
  2016. );
  2017. let instruction = StableInstruction::from(instruction);
  2018. let memory_region = MemoryRegion::new_readonly(bytes_of(&instruction), 0x100000000);
  2019. let memory_mapping =
  2020. MemoryMapping::new(vec![memory_region], &config, SBPFVersion::V3).unwrap();
  2021. let translated_instruction =
  2022. translate_type::<StableInstruction>(&memory_mapping, 0x100000000, true).unwrap();
  2023. assert_eq!(instruction, *translated_instruction);
  2024. let memory_region = MemoryRegion::new_readonly(&bytes_of(&instruction)[..1], 0x100000000);
  2025. let memory_mapping =
  2026. MemoryMapping::new(vec![memory_region], &config, SBPFVersion::V3).unwrap();
  2027. assert!(translate_type::<Instruction>(&memory_mapping, 0x100000000, true).is_err());
  2028. }
  2029. #[test]
  2030. fn test_translate_slice() {
  2031. let config = Config::default();
  2032. // zero len
  2033. let good_data = vec![1u8, 2, 3, 4, 5];
  2034. let data: Vec<u8> = vec![];
  2035. assert_eq!(std::ptr::dangling::<u8>(), data.as_ptr());
  2036. let memory_mapping = MemoryMapping::new(
  2037. vec![MemoryRegion::new_readonly(&good_data, 0x100000000)],
  2038. &config,
  2039. SBPFVersion::V3,
  2040. )
  2041. .unwrap();
  2042. let translated_data =
  2043. translate_slice::<u8>(&memory_mapping, data.as_ptr() as u64, 0, true).unwrap();
  2044. assert_eq!(data, translated_data);
  2045. assert_eq!(0, translated_data.len());
  2046. // u8
  2047. let mut data = vec![1u8, 2, 3, 4, 5];
  2048. let memory_mapping = MemoryMapping::new(
  2049. vec![MemoryRegion::new_readonly(&data, 0x100000000)],
  2050. &config,
  2051. SBPFVersion::V3,
  2052. )
  2053. .unwrap();
  2054. let translated_data =
  2055. translate_slice::<u8>(&memory_mapping, 0x100000000, data.len() as u64, true).unwrap();
  2056. assert_eq!(data, translated_data);
  2057. *data.first_mut().unwrap() = 10;
  2058. assert_eq!(data, translated_data);
  2059. assert!(
  2060. translate_slice::<u8>(&memory_mapping, data.as_ptr() as u64, u64::MAX, true).is_err()
  2061. );
  2062. assert!(
  2063. translate_slice::<u8>(&memory_mapping, 0x100000000 - 1, data.len() as u64, true,)
  2064. .is_err()
  2065. );
  2066. // u64
  2067. let mut data = vec![1u64, 2, 3, 4, 5];
  2068. let memory_mapping = MemoryMapping::new(
  2069. vec![MemoryRegion::new_readonly(
  2070. bytes_of_slice(&data),
  2071. 0x100000000,
  2072. )],
  2073. &config,
  2074. SBPFVersion::V3,
  2075. )
  2076. .unwrap();
  2077. let translated_data =
  2078. translate_slice::<u64>(&memory_mapping, 0x100000000, data.len() as u64, true).unwrap();
  2079. assert_eq!(data, translated_data);
  2080. *data.first_mut().unwrap() = 10;
  2081. assert_eq!(data, translated_data);
  2082. assert!(translate_slice::<u64>(&memory_mapping, 0x100000000, u64::MAX, true).is_err());
  2083. // Pubkeys
  2084. let mut data = vec![solana_pubkey::new_rand(); 5];
  2085. let memory_mapping = MemoryMapping::new(
  2086. vec![MemoryRegion::new_readonly(
  2087. unsafe {
  2088. slice::from_raw_parts(data.as_ptr() as *const u8, mem::size_of::<Pubkey>() * 5)
  2089. },
  2090. 0x100000000,
  2091. )],
  2092. &config,
  2093. SBPFVersion::V3,
  2094. )
  2095. .unwrap();
  2096. let translated_data =
  2097. translate_slice::<Pubkey>(&memory_mapping, 0x100000000, data.len() as u64, true)
  2098. .unwrap();
  2099. assert_eq!(data, translated_data);
  2100. *data.first_mut().unwrap() = solana_pubkey::new_rand(); // Both should point to same place
  2101. assert_eq!(data, translated_data);
  2102. }
  2103. #[test]
  2104. fn test_translate_string_and_do() {
  2105. let string = "Gaggablaghblagh!";
  2106. let config = Config::default();
  2107. let memory_mapping = MemoryMapping::new(
  2108. vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
  2109. &config,
  2110. SBPFVersion::V3,
  2111. )
  2112. .unwrap();
  2113. assert_eq!(
  2114. 42,
  2115. translate_string_and_do(
  2116. &memory_mapping,
  2117. 0x100000000,
  2118. string.len() as u64,
  2119. true,
  2120. &mut |string: &str| {
  2121. assert_eq!(string, "Gaggablaghblagh!");
  2122. Ok(42)
  2123. }
  2124. )
  2125. .unwrap()
  2126. );
  2127. }
  2128. #[test]
  2129. #[should_panic(expected = "Abort")]
  2130. fn test_syscall_abort() {
  2131. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  2132. let config = Config::default();
  2133. let mut memory_mapping = MemoryMapping::new(vec![], &config, SBPFVersion::V3).unwrap();
  2134. let result = SyscallAbort::rust(&mut invoke_context, 0, 0, 0, 0, 0, &mut memory_mapping);
  2135. result.unwrap();
  2136. }
  2137. #[test]
  2138. #[should_panic(expected = "Panic(\"Gaggablaghblagh!\", 42, 84)")]
  2139. fn test_syscall_sol_panic() {
  2140. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  2141. let string = "Gaggablaghblagh!";
  2142. let config = Config::default();
  2143. let mut memory_mapping = MemoryMapping::new(
  2144. vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
  2145. &config,
  2146. SBPFVersion::V3,
  2147. )
  2148. .unwrap();
  2149. invoke_context.mock_set_remaining(string.len() as u64 - 1);
  2150. let result = SyscallPanic::rust(
  2151. &mut invoke_context,
  2152. 0x100000000,
  2153. string.len() as u64,
  2154. 42,
  2155. 84,
  2156. 0,
  2157. &mut memory_mapping,
  2158. );
  2159. assert_matches!(
  2160. result,
  2161. Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
  2162. );
  2163. invoke_context.mock_set_remaining(string.len() as u64);
  2164. let result = SyscallPanic::rust(
  2165. &mut invoke_context,
  2166. 0x100000000,
  2167. string.len() as u64,
  2168. 42,
  2169. 84,
  2170. 0,
  2171. &mut memory_mapping,
  2172. );
  2173. result.unwrap();
  2174. }
  2175. #[test]
  2176. fn test_syscall_sol_log() {
  2177. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  2178. let string = "Gaggablaghblagh!";
  2179. let config = Config::default();
  2180. let mut memory_mapping = MemoryMapping::new(
  2181. vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
  2182. &config,
  2183. SBPFVersion::V3,
  2184. )
  2185. .unwrap();
  2186. invoke_context.mock_set_remaining(400 - 1);
  2187. let result = SyscallLog::rust(
  2188. &mut invoke_context,
  2189. 0x100000001, // AccessViolation
  2190. string.len() as u64,
  2191. 0,
  2192. 0,
  2193. 0,
  2194. &mut memory_mapping,
  2195. );
  2196. assert_access_violation!(result, 0x100000001, string.len() as u64);
  2197. let result = SyscallLog::rust(
  2198. &mut invoke_context,
  2199. 0x100000000,
  2200. string.len() as u64 * 2, // AccessViolation
  2201. 0,
  2202. 0,
  2203. 0,
  2204. &mut memory_mapping,
  2205. );
  2206. assert_access_violation!(result, 0x100000000, string.len() as u64 * 2);
  2207. let result = SyscallLog::rust(
  2208. &mut invoke_context,
  2209. 0x100000000,
  2210. string.len() as u64,
  2211. 0,
  2212. 0,
  2213. 0,
  2214. &mut memory_mapping,
  2215. );
  2216. result.unwrap();
  2217. let result = SyscallLog::rust(
  2218. &mut invoke_context,
  2219. 0x100000000,
  2220. string.len() as u64,
  2221. 0,
  2222. 0,
  2223. 0,
  2224. &mut memory_mapping,
  2225. );
  2226. assert_matches!(
  2227. result,
  2228. Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
  2229. );
  2230. assert_eq!(
  2231. invoke_context
  2232. .get_log_collector()
  2233. .unwrap()
  2234. .borrow()
  2235. .get_recorded_content(),
  2236. &["Program log: Gaggablaghblagh!".to_string()]
  2237. );
  2238. }
  2239. #[test]
  2240. fn test_syscall_sol_log_u64() {
  2241. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  2242. let cost = invoke_context.get_execution_cost().log_64_units;
  2243. invoke_context.mock_set_remaining(cost);
  2244. let config = Config::default();
  2245. let mut memory_mapping = MemoryMapping::new(vec![], &config, SBPFVersion::V3).unwrap();
  2246. let result = SyscallLogU64::rust(&mut invoke_context, 1, 2, 3, 4, 5, &mut memory_mapping);
  2247. result.unwrap();
  2248. assert_eq!(
  2249. invoke_context
  2250. .get_log_collector()
  2251. .unwrap()
  2252. .borrow()
  2253. .get_recorded_content(),
  2254. &["Program log: 0x1, 0x2, 0x3, 0x4, 0x5".to_string()]
  2255. );
  2256. }
  2257. #[test]
  2258. fn test_syscall_sol_pubkey() {
  2259. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  2260. let cost = invoke_context.get_execution_cost().log_pubkey_units;
  2261. let pubkey = Pubkey::from_str("MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN").unwrap();
  2262. let config = Config::default();
  2263. let mut memory_mapping = MemoryMapping::new(
  2264. vec![MemoryRegion::new_readonly(bytes_of(&pubkey), 0x100000000)],
  2265. &config,
  2266. SBPFVersion::V3,
  2267. )
  2268. .unwrap();
  2269. let result = SyscallLogPubkey::rust(
  2270. &mut invoke_context,
  2271. 0x100000001, // AccessViolation
  2272. 32,
  2273. 0,
  2274. 0,
  2275. 0,
  2276. &mut memory_mapping,
  2277. );
  2278. assert_access_violation!(result, 0x100000001, 32);
  2279. invoke_context.mock_set_remaining(1);
  2280. let result =
  2281. SyscallLogPubkey::rust(&mut invoke_context, 100, 32, 0, 0, 0, &mut memory_mapping);
  2282. assert_matches!(
  2283. result,
  2284. Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
  2285. );
  2286. invoke_context.mock_set_remaining(cost);
  2287. let result = SyscallLogPubkey::rust(
  2288. &mut invoke_context,
  2289. 0x100000000,
  2290. 0,
  2291. 0,
  2292. 0,
  2293. 0,
  2294. &mut memory_mapping,
  2295. );
  2296. result.unwrap();
  2297. assert_eq!(
  2298. invoke_context
  2299. .get_log_collector()
  2300. .unwrap()
  2301. .borrow()
  2302. .get_recorded_content(),
  2303. &["Program log: MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN".to_string()]
  2304. );
  2305. }
  2306. macro_rules! setup_alloc_test {
  2307. ($invoke_context:ident, $memory_mapping:ident, $heap:ident) => {
  2308. prepare_mockup!($invoke_context, program_id, bpf_loader::id());
  2309. $invoke_context
  2310. .set_syscall_context(SyscallContext {
  2311. allocator: BpfAllocator::new(solana_program_entrypoint::HEAP_LENGTH as u64),
  2312. accounts_metadata: Vec::new(),
  2313. })
  2314. .unwrap();
  2315. let config = Config {
  2316. aligned_memory_mapping: false,
  2317. ..Config::default()
  2318. };
  2319. let mut $heap =
  2320. AlignedMemory::<{ HOST_ALIGN }>::zero_filled(MAX_HEAP_FRAME_BYTES as usize);
  2321. let regions = vec![MemoryRegion::new_writable(
  2322. $heap.as_slice_mut(),
  2323. ebpf::MM_HEAP_START,
  2324. )];
  2325. let mut $memory_mapping =
  2326. MemoryMapping::new(regions, &config, SBPFVersion::V3).unwrap();
  2327. };
  2328. }
  2329. #[test]
  2330. fn test_syscall_sol_alloc_free() {
  2331. // large alloc
  2332. {
  2333. setup_alloc_test!(invoke_context, memory_mapping, heap);
  2334. let result = SyscallAllocFree::rust(
  2335. &mut invoke_context,
  2336. solana_program_entrypoint::HEAP_LENGTH as u64,
  2337. 0,
  2338. 0,
  2339. 0,
  2340. 0,
  2341. &mut memory_mapping,
  2342. );
  2343. assert_ne!(result.unwrap(), 0);
  2344. let result = SyscallAllocFree::rust(
  2345. &mut invoke_context,
  2346. solana_program_entrypoint::HEAP_LENGTH as u64,
  2347. 0,
  2348. 0,
  2349. 0,
  2350. 0,
  2351. &mut memory_mapping,
  2352. );
  2353. assert_eq!(result.unwrap(), 0);
  2354. let result = SyscallAllocFree::rust(
  2355. &mut invoke_context,
  2356. u64::MAX,
  2357. 0,
  2358. 0,
  2359. 0,
  2360. 0,
  2361. &mut memory_mapping,
  2362. );
  2363. assert_eq!(result.unwrap(), 0);
  2364. }
  2365. // many small unaligned allocs
  2366. {
  2367. setup_alloc_test!(invoke_context, memory_mapping, heap);
  2368. for _ in 0..100 {
  2369. let result =
  2370. SyscallAllocFree::rust(&mut invoke_context, 1, 0, 0, 0, 0, &mut memory_mapping);
  2371. assert_ne!(result.unwrap(), 0);
  2372. }
  2373. let result = SyscallAllocFree::rust(
  2374. &mut invoke_context,
  2375. solana_program_entrypoint::HEAP_LENGTH as u64,
  2376. 0,
  2377. 0,
  2378. 0,
  2379. 0,
  2380. &mut memory_mapping,
  2381. );
  2382. assert_eq!(result.unwrap(), 0);
  2383. }
  2384. // many small aligned allocs
  2385. {
  2386. setup_alloc_test!(invoke_context, memory_mapping, heap);
  2387. for _ in 0..12 {
  2388. let result =
  2389. SyscallAllocFree::rust(&mut invoke_context, 1, 0, 0, 0, 0, &mut memory_mapping);
  2390. assert_ne!(result.unwrap(), 0);
  2391. }
  2392. let result = SyscallAllocFree::rust(
  2393. &mut invoke_context,
  2394. solana_program_entrypoint::HEAP_LENGTH as u64,
  2395. 0,
  2396. 0,
  2397. 0,
  2398. 0,
  2399. &mut memory_mapping,
  2400. );
  2401. assert_eq!(result.unwrap(), 0);
  2402. }
  2403. // aligned allocs
  2404. fn aligned<T>() {
  2405. setup_alloc_test!(invoke_context, memory_mapping, heap);
  2406. let result = SyscallAllocFree::rust(
  2407. &mut invoke_context,
  2408. size_of::<T>() as u64,
  2409. 0,
  2410. 0,
  2411. 0,
  2412. 0,
  2413. &mut memory_mapping,
  2414. );
  2415. let address = result.unwrap();
  2416. assert_ne!(address, 0);
  2417. assert!(address_is_aligned::<T>(address));
  2418. }
  2419. aligned::<u8>();
  2420. aligned::<u16>();
  2421. aligned::<u32>();
  2422. aligned::<u64>();
  2423. aligned::<u128>();
  2424. }
  2425. #[test]
  2426. fn test_syscall_sha256() {
  2427. let config = Config::default();
  2428. prepare_mockup!(invoke_context, program_id, bpf_loader_deprecated::id());
  2429. let bytes1 = "Gaggablaghblagh!";
  2430. let bytes2 = "flurbos";
  2431. let mock_slice1 = MockSlice {
  2432. vm_addr: 0x300000000,
  2433. len: bytes1.len(),
  2434. };
  2435. let mock_slice2 = MockSlice {
  2436. vm_addr: 0x400000000,
  2437. len: bytes2.len(),
  2438. };
  2439. let bytes_to_hash = [mock_slice1, mock_slice2];
  2440. let mut hash_result = [0; HASH_BYTES];
  2441. let ro_len = bytes_to_hash.len() as u64;
  2442. let ro_va = 0x100000000;
  2443. let rw_va = 0x200000000;
  2444. let mut memory_mapping = MemoryMapping::new(
  2445. vec![
  2446. MemoryRegion::new_readonly(bytes_of_slice(&bytes_to_hash), ro_va),
  2447. MemoryRegion::new_writable(bytes_of_slice_mut(&mut hash_result), rw_va),
  2448. MemoryRegion::new_readonly(bytes1.as_bytes(), bytes_to_hash[0].vm_addr),
  2449. MemoryRegion::new_readonly(bytes2.as_bytes(), bytes_to_hash[1].vm_addr),
  2450. ],
  2451. &config,
  2452. SBPFVersion::V3,
  2453. )
  2454. .unwrap();
  2455. invoke_context.mock_set_remaining(
  2456. (invoke_context.get_execution_cost().sha256_base_cost
  2457. + invoke_context.get_execution_cost().mem_op_base_cost.max(
  2458. invoke_context
  2459. .get_execution_cost()
  2460. .sha256_byte_cost
  2461. .saturating_mul((bytes1.len() + bytes2.len()) as u64 / 2),
  2462. ))
  2463. * 4,
  2464. );
  2465. let result = SyscallHash::rust::<Sha256Hasher>(
  2466. &mut invoke_context,
  2467. ro_va,
  2468. ro_len,
  2469. rw_va,
  2470. 0,
  2471. 0,
  2472. &mut memory_mapping,
  2473. );
  2474. result.unwrap();
  2475. let hash_local = hashv(&[bytes1.as_ref(), bytes2.as_ref()]).to_bytes();
  2476. assert_eq!(hash_result, hash_local);
  2477. let result = SyscallHash::rust::<Sha256Hasher>(
  2478. &mut invoke_context,
  2479. ro_va - 1, // AccessViolation
  2480. ro_len,
  2481. rw_va,
  2482. 0,
  2483. 0,
  2484. &mut memory_mapping,
  2485. );
  2486. assert_access_violation!(result, ro_va - 1, 32);
  2487. let result = SyscallHash::rust::<Sha256Hasher>(
  2488. &mut invoke_context,
  2489. ro_va,
  2490. ro_len + 1, // AccessViolation
  2491. rw_va,
  2492. 0,
  2493. 0,
  2494. &mut memory_mapping,
  2495. );
  2496. assert_access_violation!(result, ro_va, 48);
  2497. let result = SyscallHash::rust::<Sha256Hasher>(
  2498. &mut invoke_context,
  2499. ro_va,
  2500. ro_len,
  2501. rw_va - 1, // AccessViolation
  2502. 0,
  2503. 0,
  2504. &mut memory_mapping,
  2505. );
  2506. assert_access_violation!(result, rw_va - 1, HASH_BYTES as u64);
  2507. let result = SyscallHash::rust::<Sha256Hasher>(
  2508. &mut invoke_context,
  2509. ro_va,
  2510. ro_len,
  2511. rw_va,
  2512. 0,
  2513. 0,
  2514. &mut memory_mapping,
  2515. );
  2516. assert_matches!(
  2517. result,
  2518. Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
  2519. );
  2520. }
  2521. #[test]
  2522. fn test_syscall_edwards_curve_point_validation() {
  2523. use solana_curve25519::curve_syscall_traits::CURVE25519_EDWARDS;
  2524. let config = Config::default();
  2525. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  2526. let valid_bytes: [u8; 32] = [
  2527. 201, 179, 241, 122, 180, 185, 239, 50, 183, 52, 221, 0, 153, 195, 43, 18, 22, 38, 187,
  2528. 206, 179, 192, 210, 58, 53, 45, 150, 98, 89, 17, 158, 11,
  2529. ];
  2530. let valid_bytes_va = 0x100000000;
  2531. let invalid_bytes: [u8; 32] = [
  2532. 120, 140, 152, 233, 41, 227, 203, 27, 87, 115, 25, 251, 219, 5, 84, 148, 117, 38, 84,
  2533. 60, 87, 144, 161, 146, 42, 34, 91, 155, 158, 189, 121, 79,
  2534. ];
  2535. let invalid_bytes_va = 0x200000000;
  2536. let mut memory_mapping = MemoryMapping::new(
  2537. vec![
  2538. MemoryRegion::new_readonly(&valid_bytes, valid_bytes_va),
  2539. MemoryRegion::new_readonly(&invalid_bytes, invalid_bytes_va),
  2540. ],
  2541. &config,
  2542. SBPFVersion::V3,
  2543. )
  2544. .unwrap();
  2545. invoke_context.mock_set_remaining(
  2546. (invoke_context
  2547. .get_execution_cost()
  2548. .curve25519_edwards_validate_point_cost)
  2549. * 2,
  2550. );
  2551. let result = SyscallCurvePointValidation::rust(
  2552. &mut invoke_context,
  2553. CURVE25519_EDWARDS,
  2554. valid_bytes_va,
  2555. 0,
  2556. 0,
  2557. 0,
  2558. &mut memory_mapping,
  2559. );
  2560. assert_eq!(0, result.unwrap());
  2561. let result = SyscallCurvePointValidation::rust(
  2562. &mut invoke_context,
  2563. CURVE25519_EDWARDS,
  2564. invalid_bytes_va,
  2565. 0,
  2566. 0,
  2567. 0,
  2568. &mut memory_mapping,
  2569. );
  2570. assert_eq!(1, result.unwrap());
  2571. let result = SyscallCurvePointValidation::rust(
  2572. &mut invoke_context,
  2573. CURVE25519_EDWARDS,
  2574. valid_bytes_va,
  2575. 0,
  2576. 0,
  2577. 0,
  2578. &mut memory_mapping,
  2579. );
  2580. assert_matches!(
  2581. result,
  2582. Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
  2583. );
  2584. }
  2585. #[test]
  2586. fn test_syscall_ristretto_curve_point_validation() {
  2587. use solana_curve25519::curve_syscall_traits::CURVE25519_RISTRETTO;
  2588. let config = Config::default();
  2589. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  2590. let valid_bytes: [u8; 32] = [
  2591. 226, 242, 174, 10, 106, 188, 78, 113, 168, 132, 169, 97, 197, 0, 81, 95, 88, 227, 11,
  2592. 106, 165, 130, 221, 141, 182, 166, 89, 69, 224, 141, 45, 118,
  2593. ];
  2594. let valid_bytes_va = 0x100000000;
  2595. let invalid_bytes: [u8; 32] = [
  2596. 120, 140, 152, 233, 41, 227, 203, 27, 87, 115, 25, 251, 219, 5, 84, 148, 117, 38, 84,
  2597. 60, 87, 144, 161, 146, 42, 34, 91, 155, 158, 189, 121, 79,
  2598. ];
  2599. let invalid_bytes_va = 0x200000000;
  2600. let mut memory_mapping = MemoryMapping::new(
  2601. vec![
  2602. MemoryRegion::new_readonly(&valid_bytes, valid_bytes_va),
  2603. MemoryRegion::new_readonly(&invalid_bytes, invalid_bytes_va),
  2604. ],
  2605. &config,
  2606. SBPFVersion::V3,
  2607. )
  2608. .unwrap();
  2609. invoke_context.mock_set_remaining(
  2610. (invoke_context
  2611. .get_execution_cost()
  2612. .curve25519_ristretto_validate_point_cost)
  2613. * 2,
  2614. );
  2615. let result = SyscallCurvePointValidation::rust(
  2616. &mut invoke_context,
  2617. CURVE25519_RISTRETTO,
  2618. valid_bytes_va,
  2619. 0,
  2620. 0,
  2621. 0,
  2622. &mut memory_mapping,
  2623. );
  2624. assert_eq!(0, result.unwrap());
  2625. let result = SyscallCurvePointValidation::rust(
  2626. &mut invoke_context,
  2627. CURVE25519_RISTRETTO,
  2628. invalid_bytes_va,
  2629. 0,
  2630. 0,
  2631. 0,
  2632. &mut memory_mapping,
  2633. );
  2634. assert_eq!(1, result.unwrap());
  2635. let result = SyscallCurvePointValidation::rust(
  2636. &mut invoke_context,
  2637. CURVE25519_RISTRETTO,
  2638. valid_bytes_va,
  2639. 0,
  2640. 0,
  2641. 0,
  2642. &mut memory_mapping,
  2643. );
  2644. assert_matches!(
  2645. result,
  2646. Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
  2647. );
  2648. }
  2649. #[test]
  2650. fn test_syscall_edwards_curve_group_ops() {
  2651. use solana_curve25519::curve_syscall_traits::{ADD, CURVE25519_EDWARDS, MUL, SUB};
  2652. let config = Config::default();
  2653. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  2654. let left_point: [u8; 32] = [
  2655. 33, 124, 71, 170, 117, 69, 151, 247, 59, 12, 95, 125, 133, 166, 64, 5, 2, 27, 90, 27,
  2656. 200, 167, 59, 164, 52, 54, 52, 200, 29, 13, 34, 213,
  2657. ];
  2658. let left_point_va = 0x100000000;
  2659. let right_point: [u8; 32] = [
  2660. 70, 222, 137, 221, 253, 204, 71, 51, 78, 8, 124, 1, 67, 200, 102, 225, 122, 228, 111,
  2661. 183, 129, 14, 131, 210, 212, 95, 109, 246, 55, 10, 159, 91,
  2662. ];
  2663. let right_point_va = 0x200000000;
  2664. let scalar: [u8; 32] = [
  2665. 254, 198, 23, 138, 67, 243, 184, 110, 236, 115, 236, 205, 205, 215, 79, 114, 45, 250,
  2666. 78, 137, 3, 107, 136, 237, 49, 126, 117, 223, 37, 191, 88, 6,
  2667. ];
  2668. let scalar_va = 0x300000000;
  2669. let invalid_point: [u8; 32] = [
  2670. 120, 140, 152, 233, 41, 227, 203, 27, 87, 115, 25, 251, 219, 5, 84, 148, 117, 38, 84,
  2671. 60, 87, 144, 161, 146, 42, 34, 91, 155, 158, 189, 121, 79,
  2672. ];
  2673. let invalid_point_va = 0x400000000;
  2674. let mut result_point: [u8; 32] = [0; 32];
  2675. let result_point_va = 0x500000000;
  2676. let mut memory_mapping = MemoryMapping::new(
  2677. vec![
  2678. MemoryRegion::new_readonly(bytes_of_slice(&left_point), left_point_va),
  2679. MemoryRegion::new_readonly(bytes_of_slice(&right_point), right_point_va),
  2680. MemoryRegion::new_readonly(bytes_of_slice(&scalar), scalar_va),
  2681. MemoryRegion::new_readonly(bytes_of_slice(&invalid_point), invalid_point_va),
  2682. MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
  2683. ],
  2684. &config,
  2685. SBPFVersion::V3,
  2686. )
  2687. .unwrap();
  2688. invoke_context.mock_set_remaining(
  2689. (invoke_context
  2690. .get_execution_cost()
  2691. .curve25519_edwards_add_cost
  2692. + invoke_context
  2693. .get_execution_cost()
  2694. .curve25519_edwards_subtract_cost
  2695. + invoke_context
  2696. .get_execution_cost()
  2697. .curve25519_edwards_multiply_cost)
  2698. * 2,
  2699. );
  2700. let result = SyscallCurveGroupOps::rust(
  2701. &mut invoke_context,
  2702. CURVE25519_EDWARDS,
  2703. ADD,
  2704. left_point_va,
  2705. right_point_va,
  2706. result_point_va,
  2707. &mut memory_mapping,
  2708. );
  2709. assert_eq!(0, result.unwrap());
  2710. let expected_sum = [
  2711. 7, 251, 187, 86, 186, 232, 57, 242, 193, 236, 49, 200, 90, 29, 254, 82, 46, 80, 83, 70,
  2712. 244, 153, 23, 156, 2, 138, 207, 51, 165, 38, 200, 85,
  2713. ];
  2714. assert_eq!(expected_sum, result_point);
  2715. let result = SyscallCurveGroupOps::rust(
  2716. &mut invoke_context,
  2717. CURVE25519_EDWARDS,
  2718. ADD,
  2719. invalid_point_va,
  2720. right_point_va,
  2721. result_point_va,
  2722. &mut memory_mapping,
  2723. );
  2724. assert_eq!(1, result.unwrap());
  2725. let result = SyscallCurveGroupOps::rust(
  2726. &mut invoke_context,
  2727. CURVE25519_EDWARDS,
  2728. SUB,
  2729. left_point_va,
  2730. right_point_va,
  2731. result_point_va,
  2732. &mut memory_mapping,
  2733. );
  2734. assert_eq!(0, result.unwrap());
  2735. let expected_difference = [
  2736. 60, 87, 90, 68, 232, 25, 7, 172, 247, 120, 158, 104, 52, 127, 94, 244, 5, 79, 253, 15,
  2737. 48, 69, 82, 134, 155, 70, 188, 81, 108, 95, 212, 9,
  2738. ];
  2739. assert_eq!(expected_difference, result_point);
  2740. let result = SyscallCurveGroupOps::rust(
  2741. &mut invoke_context,
  2742. CURVE25519_EDWARDS,
  2743. SUB,
  2744. invalid_point_va,
  2745. right_point_va,
  2746. result_point_va,
  2747. &mut memory_mapping,
  2748. );
  2749. assert_eq!(1, result.unwrap());
  2750. let result = SyscallCurveGroupOps::rust(
  2751. &mut invoke_context,
  2752. CURVE25519_EDWARDS,
  2753. MUL,
  2754. scalar_va,
  2755. right_point_va,
  2756. result_point_va,
  2757. &mut memory_mapping,
  2758. );
  2759. result.unwrap();
  2760. let expected_product = [
  2761. 64, 150, 40, 55, 80, 49, 217, 209, 105, 229, 181, 65, 241, 68, 2, 106, 220, 234, 211,
  2762. 71, 159, 76, 156, 114, 242, 68, 147, 31, 243, 211, 191, 124,
  2763. ];
  2764. assert_eq!(expected_product, result_point);
  2765. let result = SyscallCurveGroupOps::rust(
  2766. &mut invoke_context,
  2767. CURVE25519_EDWARDS,
  2768. MUL,
  2769. scalar_va,
  2770. invalid_point_va,
  2771. result_point_va,
  2772. &mut memory_mapping,
  2773. );
  2774. assert_eq!(1, result.unwrap());
  2775. let result = SyscallCurveGroupOps::rust(
  2776. &mut invoke_context,
  2777. CURVE25519_EDWARDS,
  2778. MUL,
  2779. scalar_va,
  2780. invalid_point_va,
  2781. result_point_va,
  2782. &mut memory_mapping,
  2783. );
  2784. assert_matches!(
  2785. result,
  2786. Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
  2787. );
  2788. }
  2789. #[test]
  2790. fn test_syscall_ristretto_curve_group_ops() {
  2791. use solana_curve25519::curve_syscall_traits::{ADD, CURVE25519_RISTRETTO, MUL, SUB};
  2792. let config = Config::default();
  2793. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  2794. let left_point: [u8; 32] = [
  2795. 208, 165, 125, 204, 2, 100, 218, 17, 170, 194, 23, 9, 102, 156, 134, 136, 217, 190, 98,
  2796. 34, 183, 194, 228, 153, 92, 11, 108, 103, 28, 57, 88, 15,
  2797. ];
  2798. let left_point_va = 0x100000000;
  2799. let right_point: [u8; 32] = [
  2800. 208, 241, 72, 163, 73, 53, 32, 174, 54, 194, 71, 8, 70, 181, 244, 199, 93, 147, 99,
  2801. 231, 162, 127, 25, 40, 39, 19, 140, 132, 112, 212, 145, 108,
  2802. ];
  2803. let right_point_va = 0x200000000;
  2804. let scalar: [u8; 32] = [
  2805. 254, 198, 23, 138, 67, 243, 184, 110, 236, 115, 236, 205, 205, 215, 79, 114, 45, 250,
  2806. 78, 137, 3, 107, 136, 237, 49, 126, 117, 223, 37, 191, 88, 6,
  2807. ];
  2808. let scalar_va = 0x300000000;
  2809. let invalid_point: [u8; 32] = [
  2810. 120, 140, 152, 233, 41, 227, 203, 27, 87, 115, 25, 251, 219, 5, 84, 148, 117, 38, 84,
  2811. 60, 87, 144, 161, 146, 42, 34, 91, 155, 158, 189, 121, 79,
  2812. ];
  2813. let invalid_point_va = 0x400000000;
  2814. let mut result_point: [u8; 32] = [0; 32];
  2815. let result_point_va = 0x500000000;
  2816. let mut memory_mapping = MemoryMapping::new(
  2817. vec![
  2818. MemoryRegion::new_readonly(bytes_of_slice(&left_point), left_point_va),
  2819. MemoryRegion::new_readonly(bytes_of_slice(&right_point), right_point_va),
  2820. MemoryRegion::new_readonly(bytes_of_slice(&scalar), scalar_va),
  2821. MemoryRegion::new_readonly(bytes_of_slice(&invalid_point), invalid_point_va),
  2822. MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
  2823. ],
  2824. &config,
  2825. SBPFVersion::V3,
  2826. )
  2827. .unwrap();
  2828. invoke_context.mock_set_remaining(
  2829. (invoke_context
  2830. .get_execution_cost()
  2831. .curve25519_ristretto_add_cost
  2832. + invoke_context
  2833. .get_execution_cost()
  2834. .curve25519_ristretto_subtract_cost
  2835. + invoke_context
  2836. .get_execution_cost()
  2837. .curve25519_ristretto_multiply_cost)
  2838. * 2,
  2839. );
  2840. let result = SyscallCurveGroupOps::rust(
  2841. &mut invoke_context,
  2842. CURVE25519_RISTRETTO,
  2843. ADD,
  2844. left_point_va,
  2845. right_point_va,
  2846. result_point_va,
  2847. &mut memory_mapping,
  2848. );
  2849. assert_eq!(0, result.unwrap());
  2850. let expected_sum = [
  2851. 78, 173, 9, 241, 180, 224, 31, 107, 176, 210, 144, 240, 118, 73, 70, 191, 128, 119,
  2852. 141, 113, 125, 215, 161, 71, 49, 176, 87, 38, 180, 177, 39, 78,
  2853. ];
  2854. assert_eq!(expected_sum, result_point);
  2855. let result = SyscallCurveGroupOps::rust(
  2856. &mut invoke_context,
  2857. CURVE25519_RISTRETTO,
  2858. ADD,
  2859. invalid_point_va,
  2860. right_point_va,
  2861. result_point_va,
  2862. &mut memory_mapping,
  2863. );
  2864. assert_eq!(1, result.unwrap());
  2865. let result = SyscallCurveGroupOps::rust(
  2866. &mut invoke_context,
  2867. CURVE25519_RISTRETTO,
  2868. SUB,
  2869. left_point_va,
  2870. right_point_va,
  2871. result_point_va,
  2872. &mut memory_mapping,
  2873. );
  2874. assert_eq!(0, result.unwrap());
  2875. let expected_difference = [
  2876. 150, 72, 222, 61, 148, 79, 96, 130, 151, 176, 29, 217, 231, 211, 0, 215, 76, 86, 212,
  2877. 146, 110, 128, 24, 151, 187, 144, 108, 233, 221, 208, 157, 52,
  2878. ];
  2879. assert_eq!(expected_difference, result_point);
  2880. let result = SyscallCurveGroupOps::rust(
  2881. &mut invoke_context,
  2882. CURVE25519_RISTRETTO,
  2883. SUB,
  2884. invalid_point_va,
  2885. right_point_va,
  2886. result_point_va,
  2887. &mut memory_mapping,
  2888. );
  2889. assert_eq!(1, result.unwrap());
  2890. let result = SyscallCurveGroupOps::rust(
  2891. &mut invoke_context,
  2892. CURVE25519_RISTRETTO,
  2893. MUL,
  2894. scalar_va,
  2895. right_point_va,
  2896. result_point_va,
  2897. &mut memory_mapping,
  2898. );
  2899. result.unwrap();
  2900. let expected_product = [
  2901. 4, 16, 46, 2, 53, 151, 201, 133, 117, 149, 232, 164, 119, 109, 136, 20, 153, 24, 124,
  2902. 21, 101, 124, 80, 19, 119, 100, 77, 108, 65, 187, 228, 5,
  2903. ];
  2904. assert_eq!(expected_product, result_point);
  2905. let result = SyscallCurveGroupOps::rust(
  2906. &mut invoke_context,
  2907. CURVE25519_RISTRETTO,
  2908. MUL,
  2909. scalar_va,
  2910. invalid_point_va,
  2911. result_point_va,
  2912. &mut memory_mapping,
  2913. );
  2914. assert_eq!(1, result.unwrap());
  2915. let result = SyscallCurveGroupOps::rust(
  2916. &mut invoke_context,
  2917. CURVE25519_RISTRETTO,
  2918. MUL,
  2919. scalar_va,
  2920. invalid_point_va,
  2921. result_point_va,
  2922. &mut memory_mapping,
  2923. );
  2924. assert_matches!(
  2925. result,
  2926. Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
  2927. );
  2928. }
  2929. #[test]
  2930. fn test_syscall_multiscalar_multiplication() {
  2931. use solana_curve25519::curve_syscall_traits::{CURVE25519_EDWARDS, CURVE25519_RISTRETTO};
  2932. let config = Config::default();
  2933. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  2934. let scalar_a: [u8; 32] = [
  2935. 254, 198, 23, 138, 67, 243, 184, 110, 236, 115, 236, 205, 205, 215, 79, 114, 45, 250,
  2936. 78, 137, 3, 107, 136, 237, 49, 126, 117, 223, 37, 191, 88, 6,
  2937. ];
  2938. let scalar_b: [u8; 32] = [
  2939. 254, 198, 23, 138, 67, 243, 184, 110, 236, 115, 236, 205, 205, 215, 79, 114, 45, 250,
  2940. 78, 137, 3, 107, 136, 237, 49, 126, 117, 223, 37, 191, 88, 6,
  2941. ];
  2942. let scalars = [scalar_a, scalar_b];
  2943. let scalars_va = 0x100000000;
  2944. let edwards_point_x: [u8; 32] = [
  2945. 252, 31, 230, 46, 173, 95, 144, 148, 158, 157, 63, 10, 8, 68, 58, 176, 142, 192, 168,
  2946. 53, 61, 105, 194, 166, 43, 56, 246, 236, 28, 146, 114, 133,
  2947. ];
  2948. let edwards_point_y: [u8; 32] = [
  2949. 10, 111, 8, 236, 97, 189, 124, 69, 89, 176, 222, 39, 199, 253, 111, 11, 248, 186, 128,
  2950. 90, 120, 128, 248, 210, 232, 183, 93, 104, 111, 150, 7, 241,
  2951. ];
  2952. let edwards_points = [edwards_point_x, edwards_point_y];
  2953. let edwards_points_va = 0x200000000;
  2954. let ristretto_point_x: [u8; 32] = [
  2955. 130, 35, 97, 25, 18, 199, 33, 239, 85, 143, 119, 111, 49, 51, 224, 40, 167, 185, 240,
  2956. 179, 25, 194, 213, 41, 14, 155, 104, 18, 181, 197, 15, 112,
  2957. ];
  2958. let ristretto_point_y: [u8; 32] = [
  2959. 152, 156, 155, 197, 152, 232, 92, 206, 219, 159, 193, 134, 121, 128, 139, 36, 56, 191,
  2960. 51, 143, 72, 204, 87, 76, 110, 124, 101, 96, 238, 158, 42, 108,
  2961. ];
  2962. let ristretto_points = [ristretto_point_x, ristretto_point_y];
  2963. let ristretto_points_va = 0x300000000;
  2964. let mut result_point: [u8; 32] = [0; 32];
  2965. let result_point_va = 0x400000000;
  2966. let mut memory_mapping = MemoryMapping::new(
  2967. vec![
  2968. MemoryRegion::new_readonly(bytes_of_slice(&scalars), scalars_va),
  2969. MemoryRegion::new_readonly(bytes_of_slice(&edwards_points), edwards_points_va),
  2970. MemoryRegion::new_readonly(bytes_of_slice(&ristretto_points), ristretto_points_va),
  2971. MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
  2972. ],
  2973. &config,
  2974. SBPFVersion::V3,
  2975. )
  2976. .unwrap();
  2977. invoke_context.mock_set_remaining(
  2978. invoke_context
  2979. .get_execution_cost()
  2980. .curve25519_edwards_msm_base_cost
  2981. + invoke_context
  2982. .get_execution_cost()
  2983. .curve25519_edwards_msm_incremental_cost
  2984. + invoke_context
  2985. .get_execution_cost()
  2986. .curve25519_ristretto_msm_base_cost
  2987. + invoke_context
  2988. .get_execution_cost()
  2989. .curve25519_ristretto_msm_incremental_cost,
  2990. );
  2991. let result = SyscallCurveMultiscalarMultiplication::rust(
  2992. &mut invoke_context,
  2993. CURVE25519_EDWARDS,
  2994. scalars_va,
  2995. edwards_points_va,
  2996. 2,
  2997. result_point_va,
  2998. &mut memory_mapping,
  2999. );
  3000. assert_eq!(0, result.unwrap());
  3001. let expected_product = [
  3002. 30, 174, 168, 34, 160, 70, 63, 166, 236, 18, 74, 144, 185, 222, 208, 243, 5, 54, 223,
  3003. 172, 185, 75, 244, 26, 70, 18, 248, 46, 207, 184, 235, 60,
  3004. ];
  3005. assert_eq!(expected_product, result_point);
  3006. let result = SyscallCurveMultiscalarMultiplication::rust(
  3007. &mut invoke_context,
  3008. CURVE25519_RISTRETTO,
  3009. scalars_va,
  3010. ristretto_points_va,
  3011. 2,
  3012. result_point_va,
  3013. &mut memory_mapping,
  3014. );
  3015. assert_eq!(0, result.unwrap());
  3016. let expected_product = [
  3017. 78, 120, 86, 111, 152, 64, 146, 84, 14, 236, 77, 147, 237, 190, 251, 241, 136, 167, 21,
  3018. 94, 84, 118, 92, 140, 120, 81, 30, 246, 173, 140, 195, 86,
  3019. ];
  3020. assert_eq!(expected_product, result_point);
  3021. }
  3022. #[test]
  3023. fn test_syscall_multiscalar_multiplication_maximum_length_exceeded() {
  3024. use solana_curve25519::curve_syscall_traits::{CURVE25519_EDWARDS, CURVE25519_RISTRETTO};
  3025. let config = Config::default();
  3026. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  3027. let scalar: [u8; 32] = [
  3028. 254, 198, 23, 138, 67, 243, 184, 110, 236, 115, 236, 205, 205, 215, 79, 114, 45, 250,
  3029. 78, 137, 3, 107, 136, 237, 49, 126, 117, 223, 37, 191, 88, 6,
  3030. ];
  3031. let scalars = [scalar; 513];
  3032. let scalars_va = 0x100000000;
  3033. let edwards_point: [u8; 32] = [
  3034. 252, 31, 230, 46, 173, 95, 144, 148, 158, 157, 63, 10, 8, 68, 58, 176, 142, 192, 168,
  3035. 53, 61, 105, 194, 166, 43, 56, 246, 236, 28, 146, 114, 133,
  3036. ];
  3037. let edwards_points = [edwards_point; 513];
  3038. let edwards_points_va = 0x200000000;
  3039. let ristretto_point: [u8; 32] = [
  3040. 130, 35, 97, 25, 18, 199, 33, 239, 85, 143, 119, 111, 49, 51, 224, 40, 167, 185, 240,
  3041. 179, 25, 194, 213, 41, 14, 155, 104, 18, 181, 197, 15, 112,
  3042. ];
  3043. let ristretto_points = [ristretto_point; 513];
  3044. let ristretto_points_va = 0x300000000;
  3045. let mut result_point: [u8; 32] = [0; 32];
  3046. let result_point_va = 0x400000000;
  3047. let mut memory_mapping = MemoryMapping::new(
  3048. vec![
  3049. MemoryRegion::new_readonly(bytes_of_slice(&scalars), scalars_va),
  3050. MemoryRegion::new_readonly(bytes_of_slice(&edwards_points), edwards_points_va),
  3051. MemoryRegion::new_readonly(bytes_of_slice(&ristretto_points), ristretto_points_va),
  3052. MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
  3053. ],
  3054. &config,
  3055. SBPFVersion::V3,
  3056. )
  3057. .unwrap();
  3058. // test Edwards
  3059. invoke_context.mock_set_remaining(500_000);
  3060. let result = SyscallCurveMultiscalarMultiplication::rust(
  3061. &mut invoke_context,
  3062. CURVE25519_EDWARDS,
  3063. scalars_va,
  3064. edwards_points_va,
  3065. 512, // below maximum vector length
  3066. result_point_va,
  3067. &mut memory_mapping,
  3068. );
  3069. assert_eq!(0, result.unwrap());
  3070. let expected_product = [
  3071. 20, 146, 226, 37, 22, 61, 86, 249, 208, 40, 38, 11, 126, 101, 10, 82, 81, 77, 88, 209,
  3072. 15, 76, 82, 251, 180, 133, 84, 243, 162, 0, 11, 145,
  3073. ];
  3074. assert_eq!(expected_product, result_point);
  3075. invoke_context.mock_set_remaining(500_000);
  3076. let result = SyscallCurveMultiscalarMultiplication::rust(
  3077. &mut invoke_context,
  3078. CURVE25519_EDWARDS,
  3079. scalars_va,
  3080. edwards_points_va,
  3081. 513, // above maximum vector length
  3082. result_point_va,
  3083. &mut memory_mapping,
  3084. )
  3085. .unwrap_err()
  3086. .downcast::<SyscallError>()
  3087. .unwrap();
  3088. assert_eq!(*result, SyscallError::InvalidLength);
  3089. // test Ristretto
  3090. invoke_context.mock_set_remaining(500_000);
  3091. let result = SyscallCurveMultiscalarMultiplication::rust(
  3092. &mut invoke_context,
  3093. CURVE25519_RISTRETTO,
  3094. scalars_va,
  3095. ristretto_points_va,
  3096. 512, // below maximum vector length
  3097. result_point_va,
  3098. &mut memory_mapping,
  3099. );
  3100. assert_eq!(0, result.unwrap());
  3101. let expected_product = [
  3102. 146, 224, 127, 193, 252, 64, 196, 181, 246, 104, 27, 116, 183, 52, 200, 239, 2, 108,
  3103. 21, 27, 97, 44, 95, 65, 26, 218, 223, 39, 197, 132, 51, 49,
  3104. ];
  3105. assert_eq!(expected_product, result_point);
  3106. invoke_context.mock_set_remaining(500_000);
  3107. let result = SyscallCurveMultiscalarMultiplication::rust(
  3108. &mut invoke_context,
  3109. CURVE25519_RISTRETTO,
  3110. scalars_va,
  3111. ristretto_points_va,
  3112. 513, // above maximum vector length
  3113. result_point_va,
  3114. &mut memory_mapping,
  3115. )
  3116. .unwrap_err()
  3117. .downcast::<SyscallError>()
  3118. .unwrap();
  3119. assert_eq!(*result, SyscallError::InvalidLength);
  3120. }
  3121. fn create_filled_type<T: Default>(zero_init: bool) -> T {
  3122. let mut val = T::default();
  3123. let p = &mut val as *mut _ as *mut u8;
  3124. for i in 0..(size_of::<T>() as isize) {
  3125. unsafe {
  3126. *p.offset(i) = if zero_init { 0 } else { i as u8 };
  3127. }
  3128. }
  3129. val
  3130. }
  3131. fn are_bytes_equal<T>(first: &T, second: &T) -> bool {
  3132. let p_first = first as *const _ as *const u8;
  3133. let p_second = second as *const _ as *const u8;
  3134. for i in 0..(size_of::<T>() as isize) {
  3135. unsafe {
  3136. if *p_first.offset(i) != *p_second.offset(i) {
  3137. return false;
  3138. }
  3139. }
  3140. }
  3141. true
  3142. }
  3143. #[test]
  3144. #[allow(deprecated)]
  3145. fn test_syscall_get_sysvar() {
  3146. let config = Config::default();
  3147. let mut src_clock = create_filled_type::<Clock>(false);
  3148. src_clock.slot = 1;
  3149. src_clock.epoch_start_timestamp = 2;
  3150. src_clock.epoch = 3;
  3151. src_clock.leader_schedule_epoch = 4;
  3152. src_clock.unix_timestamp = 5;
  3153. let mut src_epochschedule = create_filled_type::<EpochSchedule>(false);
  3154. src_epochschedule.slots_per_epoch = 1;
  3155. src_epochschedule.leader_schedule_slot_offset = 2;
  3156. src_epochschedule.warmup = false;
  3157. src_epochschedule.first_normal_epoch = 3;
  3158. src_epochschedule.first_normal_slot = 4;
  3159. let mut src_fees = create_filled_type::<Fees>(false);
  3160. src_fees.fee_calculator = FeeCalculator {
  3161. lamports_per_signature: 1,
  3162. };
  3163. let mut src_rent = create_filled_type::<Rent>(false);
  3164. src_rent.lamports_per_byte_year = 1;
  3165. src_rent.exemption_threshold = 2.0;
  3166. src_rent.burn_percent = 3;
  3167. let mut src_rewards = create_filled_type::<EpochRewards>(false);
  3168. src_rewards.distribution_starting_block_height = 42;
  3169. src_rewards.num_partitions = 2;
  3170. src_rewards.parent_blockhash = Hash::new_from_array([3; 32]);
  3171. src_rewards.total_points = 4;
  3172. src_rewards.total_rewards = 100;
  3173. src_rewards.distributed_rewards = 10;
  3174. src_rewards.active = true;
  3175. let mut src_restart = create_filled_type::<LastRestartSlot>(false);
  3176. src_restart.last_restart_slot = 1;
  3177. let transaction_accounts = vec![
  3178. (
  3179. sysvar::clock::id(),
  3180. create_account_shared_data_for_test(&src_clock),
  3181. ),
  3182. (
  3183. sysvar::epoch_schedule::id(),
  3184. create_account_shared_data_for_test(&src_epochschedule),
  3185. ),
  3186. (
  3187. sysvar::fees::id(),
  3188. create_account_shared_data_for_test(&src_fees),
  3189. ),
  3190. (
  3191. sysvar::rent::id(),
  3192. create_account_shared_data_for_test(&src_rent),
  3193. ),
  3194. (
  3195. sysvar::epoch_rewards::id(),
  3196. create_account_shared_data_for_test(&src_rewards),
  3197. ),
  3198. (
  3199. sysvar::last_restart_slot::id(),
  3200. create_account_shared_data_for_test(&src_restart),
  3201. ),
  3202. ];
  3203. with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
  3204. // Test clock sysvar
  3205. {
  3206. let mut got_clock_obj = Clock::default();
  3207. let got_clock_obj_va = 0x100000000;
  3208. let mut got_clock_buf = vec![0; Clock::size_of()];
  3209. let got_clock_buf_va = 0x200000000;
  3210. let clock_id_va = 0x300000000;
  3211. let clock_id = Clock::id().to_bytes();
  3212. let mut memory_mapping = MemoryMapping::new(
  3213. vec![
  3214. MemoryRegion::new_writable(bytes_of_mut(&mut got_clock_obj), got_clock_obj_va),
  3215. MemoryRegion::new_writable(&mut got_clock_buf, got_clock_buf_va),
  3216. MemoryRegion::new_readonly(&clock_id, clock_id_va),
  3217. ],
  3218. &config,
  3219. SBPFVersion::V3,
  3220. )
  3221. .unwrap();
  3222. let result = SyscallGetClockSysvar::rust(
  3223. &mut invoke_context,
  3224. got_clock_obj_va,
  3225. 0,
  3226. 0,
  3227. 0,
  3228. 0,
  3229. &mut memory_mapping,
  3230. );
  3231. assert_eq!(result.unwrap(), 0);
  3232. assert_eq!(got_clock_obj, src_clock);
  3233. let mut clean_clock = create_filled_type::<Clock>(true);
  3234. clean_clock.slot = src_clock.slot;
  3235. clean_clock.epoch_start_timestamp = src_clock.epoch_start_timestamp;
  3236. clean_clock.epoch = src_clock.epoch;
  3237. clean_clock.leader_schedule_epoch = src_clock.leader_schedule_epoch;
  3238. clean_clock.unix_timestamp = src_clock.unix_timestamp;
  3239. assert!(are_bytes_equal(&got_clock_obj, &clean_clock));
  3240. let result = SyscallGetSysvar::rust(
  3241. &mut invoke_context,
  3242. clock_id_va,
  3243. got_clock_buf_va,
  3244. 0,
  3245. Clock::size_of() as u64,
  3246. 0,
  3247. &mut memory_mapping,
  3248. );
  3249. assert_eq!(result.unwrap(), 0);
  3250. let clock_from_buf = bincode::deserialize::<Clock>(&got_clock_buf).unwrap();
  3251. assert_eq!(clock_from_buf, src_clock);
  3252. assert!(are_bytes_equal(&clock_from_buf, &clean_clock));
  3253. }
  3254. // Test epoch_schedule sysvar
  3255. {
  3256. let mut got_epochschedule_obj = EpochSchedule::default();
  3257. let got_epochschedule_obj_va = 0x100000000;
  3258. let mut got_epochschedule_buf = vec![0; EpochSchedule::size_of()];
  3259. let got_epochschedule_buf_va = 0x200000000;
  3260. let epochschedule_id_va = 0x300000000;
  3261. let epochschedule_id = EpochSchedule::id().to_bytes();
  3262. let mut memory_mapping = MemoryMapping::new(
  3263. vec![
  3264. MemoryRegion::new_writable(
  3265. bytes_of_mut(&mut got_epochschedule_obj),
  3266. got_epochschedule_obj_va,
  3267. ),
  3268. MemoryRegion::new_writable(
  3269. &mut got_epochschedule_buf,
  3270. got_epochschedule_buf_va,
  3271. ),
  3272. MemoryRegion::new_readonly(&epochschedule_id, epochschedule_id_va),
  3273. ],
  3274. &config,
  3275. SBPFVersion::V3,
  3276. )
  3277. .unwrap();
  3278. let result = SyscallGetEpochScheduleSysvar::rust(
  3279. &mut invoke_context,
  3280. got_epochschedule_obj_va,
  3281. 0,
  3282. 0,
  3283. 0,
  3284. 0,
  3285. &mut memory_mapping,
  3286. );
  3287. assert_eq!(result.unwrap(), 0);
  3288. assert_eq!(got_epochschedule_obj, src_epochschedule);
  3289. let mut clean_epochschedule = create_filled_type::<EpochSchedule>(true);
  3290. clean_epochschedule.slots_per_epoch = src_epochschedule.slots_per_epoch;
  3291. clean_epochschedule.leader_schedule_slot_offset =
  3292. src_epochschedule.leader_schedule_slot_offset;
  3293. clean_epochschedule.warmup = src_epochschedule.warmup;
  3294. clean_epochschedule.first_normal_epoch = src_epochschedule.first_normal_epoch;
  3295. clean_epochschedule.first_normal_slot = src_epochschedule.first_normal_slot;
  3296. assert!(are_bytes_equal(
  3297. &got_epochschedule_obj,
  3298. &clean_epochschedule
  3299. ));
  3300. let result = SyscallGetSysvar::rust(
  3301. &mut invoke_context,
  3302. epochschedule_id_va,
  3303. got_epochschedule_buf_va,
  3304. 0,
  3305. EpochSchedule::size_of() as u64,
  3306. 0,
  3307. &mut memory_mapping,
  3308. );
  3309. assert_eq!(result.unwrap(), 0);
  3310. let epochschedule_from_buf =
  3311. bincode::deserialize::<EpochSchedule>(&got_epochschedule_buf).unwrap();
  3312. assert_eq!(epochschedule_from_buf, src_epochschedule);
  3313. // clone is to zero the alignment padding
  3314. assert!(are_bytes_equal(
  3315. &epochschedule_from_buf.clone(),
  3316. &clean_epochschedule
  3317. ));
  3318. }
  3319. // Test fees sysvar
  3320. {
  3321. let mut got_fees = Fees::default();
  3322. let got_fees_va = 0x100000000;
  3323. let mut memory_mapping = MemoryMapping::new(
  3324. vec![MemoryRegion::new_writable(
  3325. bytes_of_mut(&mut got_fees),
  3326. got_fees_va,
  3327. )],
  3328. &config,
  3329. SBPFVersion::V3,
  3330. )
  3331. .unwrap();
  3332. let result = SyscallGetFeesSysvar::rust(
  3333. &mut invoke_context,
  3334. got_fees_va,
  3335. 0,
  3336. 0,
  3337. 0,
  3338. 0,
  3339. &mut memory_mapping,
  3340. );
  3341. assert_eq!(result.unwrap(), 0);
  3342. assert_eq!(got_fees, src_fees);
  3343. let mut clean_fees = create_filled_type::<Fees>(true);
  3344. clean_fees.fee_calculator = src_fees.fee_calculator;
  3345. assert!(are_bytes_equal(&got_fees, &clean_fees));
  3346. // fees sysvar is not accessible via sol_get_sysvar so nothing further to test
  3347. }
  3348. // Test rent sysvar
  3349. {
  3350. let mut got_rent_obj = create_filled_type::<Rent>(true);
  3351. let got_rent_obj_va = 0x100000000;
  3352. let mut got_rent_buf = vec![0; Rent::size_of()];
  3353. let got_rent_buf_va = 0x200000000;
  3354. let rent_id_va = 0x300000000;
  3355. let rent_id = Rent::id().to_bytes();
  3356. let mut memory_mapping = MemoryMapping::new(
  3357. vec![
  3358. MemoryRegion::new_writable(bytes_of_mut(&mut got_rent_obj), got_rent_obj_va),
  3359. MemoryRegion::new_writable(&mut got_rent_buf, got_rent_buf_va),
  3360. MemoryRegion::new_readonly(&rent_id, rent_id_va),
  3361. ],
  3362. &config,
  3363. SBPFVersion::V3,
  3364. )
  3365. .unwrap();
  3366. let result = SyscallGetRentSysvar::rust(
  3367. &mut invoke_context,
  3368. got_rent_obj_va,
  3369. 0,
  3370. 0,
  3371. 0,
  3372. 0,
  3373. &mut memory_mapping,
  3374. );
  3375. assert_eq!(result.unwrap(), 0);
  3376. assert_eq!(got_rent_obj, src_rent);
  3377. let mut clean_rent = create_filled_type::<Rent>(true);
  3378. clean_rent.lamports_per_byte_year = src_rent.lamports_per_byte_year;
  3379. clean_rent.exemption_threshold = src_rent.exemption_threshold;
  3380. clean_rent.burn_percent = src_rent.burn_percent;
  3381. assert!(are_bytes_equal(&got_rent_obj, &clean_rent));
  3382. let result = SyscallGetSysvar::rust(
  3383. &mut invoke_context,
  3384. rent_id_va,
  3385. got_rent_buf_va,
  3386. 0,
  3387. Rent::size_of() as u64,
  3388. 0,
  3389. &mut memory_mapping,
  3390. );
  3391. assert_eq!(result.unwrap(), 0);
  3392. let rent_from_buf = bincode::deserialize::<Rent>(&got_rent_buf).unwrap();
  3393. assert_eq!(rent_from_buf, src_rent);
  3394. // clone is to zero the alignment padding
  3395. assert!(are_bytes_equal(&rent_from_buf.clone(), &clean_rent));
  3396. }
  3397. // Test epoch rewards sysvar
  3398. {
  3399. let mut got_rewards_obj = create_filled_type::<EpochRewards>(true);
  3400. let got_rewards_obj_va = 0x100000000;
  3401. let mut got_rewards_buf = vec![0; EpochRewards::size_of()];
  3402. let got_rewards_buf_va = 0x200000000;
  3403. let rewards_id_va = 0x300000000;
  3404. let rewards_id = EpochRewards::id().to_bytes();
  3405. let mut memory_mapping = MemoryMapping::new(
  3406. vec![
  3407. MemoryRegion::new_writable(
  3408. bytes_of_mut(&mut got_rewards_obj),
  3409. got_rewards_obj_va,
  3410. ),
  3411. MemoryRegion::new_writable(&mut got_rewards_buf, got_rewards_buf_va),
  3412. MemoryRegion::new_readonly(&rewards_id, rewards_id_va),
  3413. ],
  3414. &config,
  3415. SBPFVersion::V3,
  3416. )
  3417. .unwrap();
  3418. let result = SyscallGetEpochRewardsSysvar::rust(
  3419. &mut invoke_context,
  3420. got_rewards_obj_va,
  3421. 0,
  3422. 0,
  3423. 0,
  3424. 0,
  3425. &mut memory_mapping,
  3426. );
  3427. assert_eq!(result.unwrap(), 0);
  3428. assert_eq!(got_rewards_obj, src_rewards);
  3429. let mut clean_rewards = create_filled_type::<EpochRewards>(true);
  3430. clean_rewards.distribution_starting_block_height =
  3431. src_rewards.distribution_starting_block_height;
  3432. clean_rewards.num_partitions = src_rewards.num_partitions;
  3433. clean_rewards.parent_blockhash = src_rewards.parent_blockhash;
  3434. clean_rewards.total_points = src_rewards.total_points;
  3435. clean_rewards.total_rewards = src_rewards.total_rewards;
  3436. clean_rewards.distributed_rewards = src_rewards.distributed_rewards;
  3437. clean_rewards.active = src_rewards.active;
  3438. assert!(are_bytes_equal(&got_rewards_obj, &clean_rewards));
  3439. let result = SyscallGetSysvar::rust(
  3440. &mut invoke_context,
  3441. rewards_id_va,
  3442. got_rewards_buf_va,
  3443. 0,
  3444. EpochRewards::size_of() as u64,
  3445. 0,
  3446. &mut memory_mapping,
  3447. );
  3448. assert_eq!(result.unwrap(), 0);
  3449. let rewards_from_buf = bincode::deserialize::<EpochRewards>(&got_rewards_buf).unwrap();
  3450. assert_eq!(rewards_from_buf, src_rewards);
  3451. // clone is to zero the alignment padding
  3452. assert!(are_bytes_equal(&rewards_from_buf.clone(), &clean_rewards));
  3453. }
  3454. // Test last restart slot sysvar
  3455. {
  3456. let mut got_restart_obj = LastRestartSlot::default();
  3457. let got_restart_obj_va = 0x100000000;
  3458. let mut got_restart_buf = vec![0; LastRestartSlot::size_of()];
  3459. let got_restart_buf_va = 0x200000000;
  3460. let restart_id_va = 0x300000000;
  3461. let restart_id = LastRestartSlot::id().to_bytes();
  3462. let mut memory_mapping = MemoryMapping::new(
  3463. vec![
  3464. MemoryRegion::new_writable(
  3465. bytes_of_mut(&mut got_restart_obj),
  3466. got_restart_obj_va,
  3467. ),
  3468. MemoryRegion::new_writable(&mut got_restart_buf, got_restart_buf_va),
  3469. MemoryRegion::new_readonly(&restart_id, restart_id_va),
  3470. ],
  3471. &config,
  3472. SBPFVersion::V3,
  3473. )
  3474. .unwrap();
  3475. let result = SyscallGetLastRestartSlotSysvar::rust(
  3476. &mut invoke_context,
  3477. got_restart_obj_va,
  3478. 0,
  3479. 0,
  3480. 0,
  3481. 0,
  3482. &mut memory_mapping,
  3483. );
  3484. assert_eq!(result.unwrap(), 0);
  3485. assert_eq!(got_restart_obj, src_restart);
  3486. let mut clean_restart = create_filled_type::<LastRestartSlot>(true);
  3487. clean_restart.last_restart_slot = src_restart.last_restart_slot;
  3488. assert!(are_bytes_equal(&got_restart_obj, &clean_restart));
  3489. let result = SyscallGetSysvar::rust(
  3490. &mut invoke_context,
  3491. restart_id_va,
  3492. got_restart_buf_va,
  3493. 0,
  3494. LastRestartSlot::size_of() as u64,
  3495. 0,
  3496. &mut memory_mapping,
  3497. );
  3498. assert_eq!(result.unwrap(), 0);
  3499. let restart_from_buf =
  3500. bincode::deserialize::<LastRestartSlot>(&got_restart_buf).unwrap();
  3501. assert_eq!(restart_from_buf, src_restart);
  3502. assert!(are_bytes_equal(&restart_from_buf, &clean_restart));
  3503. }
  3504. }
  3505. #[test_case(false; "partial")]
  3506. #[test_case(true; "full")]
  3507. fn test_syscall_get_stake_history(filled: bool) {
  3508. let config = Config::default();
  3509. let mut src_history = StakeHistory::default();
  3510. let epochs = if filled {
  3511. stake_history::MAX_ENTRIES + 1
  3512. } else {
  3513. stake_history::MAX_ENTRIES / 2
  3514. } as u64;
  3515. for epoch in 1..epochs {
  3516. src_history.add(
  3517. epoch,
  3518. StakeHistoryEntry {
  3519. effective: epoch * 2,
  3520. activating: epoch * 3,
  3521. deactivating: epoch * 5,
  3522. },
  3523. );
  3524. }
  3525. let src_history = src_history;
  3526. let mut src_history_buf = vec![0; StakeHistory::size_of()];
  3527. bincode::serialize_into(&mut src_history_buf, &src_history).unwrap();
  3528. let transaction_accounts = vec![(
  3529. sysvar::stake_history::id(),
  3530. create_account_shared_data_for_test(&src_history),
  3531. )];
  3532. with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
  3533. {
  3534. let mut got_history_buf = vec![0; StakeHistory::size_of()];
  3535. let got_history_buf_va = 0x100000000;
  3536. let history_id_va = 0x200000000;
  3537. let history_id = StakeHistory::id().to_bytes();
  3538. let mut memory_mapping = MemoryMapping::new(
  3539. vec![
  3540. MemoryRegion::new_writable(&mut got_history_buf, got_history_buf_va),
  3541. MemoryRegion::new_readonly(&history_id, history_id_va),
  3542. ],
  3543. &config,
  3544. SBPFVersion::V3,
  3545. )
  3546. .unwrap();
  3547. let result = SyscallGetSysvar::rust(
  3548. &mut invoke_context,
  3549. history_id_va,
  3550. got_history_buf_va,
  3551. 0,
  3552. StakeHistory::size_of() as u64,
  3553. 0,
  3554. &mut memory_mapping,
  3555. );
  3556. assert_eq!(result.unwrap(), 0);
  3557. let history_from_buf = bincode::deserialize::<StakeHistory>(&got_history_buf).unwrap();
  3558. assert_eq!(history_from_buf, src_history);
  3559. }
  3560. }
  3561. #[test_case(false; "partial")]
  3562. #[test_case(true; "full")]
  3563. fn test_syscall_get_slot_hashes(filled: bool) {
  3564. let config = Config::default();
  3565. let mut src_hashes = SlotHashes::default();
  3566. let slots = if filled {
  3567. slot_hashes::MAX_ENTRIES + 1
  3568. } else {
  3569. slot_hashes::MAX_ENTRIES / 2
  3570. } as u64;
  3571. for slot in 1..slots {
  3572. src_hashes.add(slot, hashv(&[&slot.to_le_bytes()]));
  3573. }
  3574. let src_hashes = src_hashes;
  3575. let mut src_hashes_buf = vec![0; SlotHashes::size_of()];
  3576. bincode::serialize_into(&mut src_hashes_buf, &src_hashes).unwrap();
  3577. let transaction_accounts = vec![(
  3578. sysvar::slot_hashes::id(),
  3579. create_account_shared_data_for_test(&src_hashes),
  3580. )];
  3581. with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
  3582. {
  3583. let mut got_hashes_buf = vec![0; SlotHashes::size_of()];
  3584. let got_hashes_buf_va = 0x100000000;
  3585. let hashes_id_va = 0x200000000;
  3586. let hashes_id = SlotHashes::id().to_bytes();
  3587. let mut memory_mapping = MemoryMapping::new(
  3588. vec![
  3589. MemoryRegion::new_writable(&mut got_hashes_buf, got_hashes_buf_va),
  3590. MemoryRegion::new_readonly(&hashes_id, hashes_id_va),
  3591. ],
  3592. &config,
  3593. SBPFVersion::V3,
  3594. )
  3595. .unwrap();
  3596. let result = SyscallGetSysvar::rust(
  3597. &mut invoke_context,
  3598. hashes_id_va,
  3599. got_hashes_buf_va,
  3600. 0,
  3601. SlotHashes::size_of() as u64,
  3602. 0,
  3603. &mut memory_mapping,
  3604. );
  3605. assert_eq!(result.unwrap(), 0);
  3606. let hashes_from_buf = bincode::deserialize::<SlotHashes>(&got_hashes_buf).unwrap();
  3607. assert_eq!(hashes_from_buf, src_hashes);
  3608. }
  3609. }
  3610. #[test]
  3611. fn test_syscall_get_sysvar_errors() {
  3612. let config = Config::default();
  3613. let mut src_clock = create_filled_type::<Clock>(false);
  3614. src_clock.slot = 1;
  3615. src_clock.epoch_start_timestamp = 2;
  3616. src_clock.epoch = 3;
  3617. src_clock.leader_schedule_epoch = 4;
  3618. src_clock.unix_timestamp = 5;
  3619. let clock_id_va = 0x100000000;
  3620. let clock_id = Clock::id().to_bytes();
  3621. let mut got_clock_buf_rw = vec![0; Clock::size_of()];
  3622. let got_clock_buf_rw_va = 0x200000000;
  3623. let got_clock_buf_ro = vec![0; Clock::size_of()];
  3624. let got_clock_buf_ro_va = 0x300000000;
  3625. let mut memory_mapping = MemoryMapping::new(
  3626. vec![
  3627. MemoryRegion::new_readonly(&clock_id, clock_id_va),
  3628. MemoryRegion::new_writable(&mut got_clock_buf_rw, got_clock_buf_rw_va),
  3629. MemoryRegion::new_readonly(&got_clock_buf_ro, got_clock_buf_ro_va),
  3630. ],
  3631. &config,
  3632. SBPFVersion::V3,
  3633. )
  3634. .unwrap();
  3635. let access_violation_err =
  3636. std::mem::discriminant(&EbpfError::AccessViolation(AccessType::Load, 0, 0, ""));
  3637. let got_clock_empty = vec![0; Clock::size_of()];
  3638. {
  3639. // start without the clock sysvar because we expect to hit specific errors before loading it
  3640. with_mock_invoke_context!(invoke_context, transaction_context, vec![]);
  3641. // Abort: "Not all bytes in VM memory range `[sysvar_id, sysvar_id + 32)` are readable."
  3642. let e = SyscallGetSysvar::rust(
  3643. &mut invoke_context,
  3644. clock_id_va + 1,
  3645. got_clock_buf_rw_va,
  3646. 0,
  3647. Clock::size_of() as u64,
  3648. 0,
  3649. &mut memory_mapping,
  3650. )
  3651. .unwrap_err();
  3652. assert_eq!(
  3653. std::mem::discriminant(e.downcast_ref::<EbpfError>().unwrap()),
  3654. access_violation_err,
  3655. );
  3656. assert_eq!(got_clock_buf_rw, got_clock_empty);
  3657. // Abort: "Not all bytes in VM memory range `[var_addr, var_addr + length)` are writable."
  3658. let e = SyscallGetSysvar::rust(
  3659. &mut invoke_context,
  3660. clock_id_va,
  3661. got_clock_buf_rw_va + 1,
  3662. 0,
  3663. Clock::size_of() as u64,
  3664. 0,
  3665. &mut memory_mapping,
  3666. )
  3667. .unwrap_err();
  3668. assert_eq!(
  3669. std::mem::discriminant(e.downcast_ref::<EbpfError>().unwrap()),
  3670. access_violation_err,
  3671. );
  3672. assert_eq!(got_clock_buf_rw, got_clock_empty);
  3673. let e = SyscallGetSysvar::rust(
  3674. &mut invoke_context,
  3675. clock_id_va,
  3676. got_clock_buf_ro_va,
  3677. 0,
  3678. Clock::size_of() as u64,
  3679. 0,
  3680. &mut memory_mapping,
  3681. )
  3682. .unwrap_err();
  3683. assert_eq!(
  3684. std::mem::discriminant(e.downcast_ref::<EbpfError>().unwrap()),
  3685. access_violation_err,
  3686. );
  3687. assert_eq!(got_clock_buf_rw, got_clock_empty);
  3688. // Abort: "`offset + length` is not in `[0, 2^64)`."
  3689. let e = SyscallGetSysvar::rust(
  3690. &mut invoke_context,
  3691. clock_id_va,
  3692. got_clock_buf_rw_va,
  3693. u64::MAX - Clock::size_of() as u64 / 2,
  3694. Clock::size_of() as u64,
  3695. 0,
  3696. &mut memory_mapping,
  3697. )
  3698. .unwrap_err();
  3699. assert_eq!(
  3700. *e.downcast_ref::<InstructionError>().unwrap(),
  3701. InstructionError::ArithmeticOverflow,
  3702. );
  3703. assert_eq!(got_clock_buf_rw, got_clock_empty);
  3704. // "`var_addr + length` is not in `[0, 2^64)`" is theoretically impossible to trigger
  3705. // because if the sum extended outside u64::MAX then it would not be writable and translate would fail
  3706. // "`2` if the sysvar data is not present in the Sysvar Cache."
  3707. let result = SyscallGetSysvar::rust(
  3708. &mut invoke_context,
  3709. clock_id_va,
  3710. got_clock_buf_rw_va,
  3711. 0,
  3712. Clock::size_of() as u64,
  3713. 0,
  3714. &mut memory_mapping,
  3715. )
  3716. .unwrap();
  3717. assert_eq!(result, 2);
  3718. assert_eq!(got_clock_buf_rw, got_clock_empty);
  3719. }
  3720. {
  3721. let transaction_accounts = vec![(
  3722. sysvar::clock::id(),
  3723. create_account_shared_data_for_test(&src_clock),
  3724. )];
  3725. with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
  3726. // "`1` if `offset + length` is greater than the length of the sysvar data."
  3727. let result = SyscallGetSysvar::rust(
  3728. &mut invoke_context,
  3729. clock_id_va,
  3730. got_clock_buf_rw_va,
  3731. 1,
  3732. Clock::size_of() as u64,
  3733. 0,
  3734. &mut memory_mapping,
  3735. )
  3736. .unwrap();
  3737. assert_eq!(result, 1);
  3738. assert_eq!(got_clock_buf_rw, got_clock_empty);
  3739. // and now lets succeed
  3740. SyscallGetSysvar::rust(
  3741. &mut invoke_context,
  3742. clock_id_va,
  3743. got_clock_buf_rw_va,
  3744. 0,
  3745. Clock::size_of() as u64,
  3746. 0,
  3747. &mut memory_mapping,
  3748. )
  3749. .unwrap();
  3750. let clock_from_buf = bincode::deserialize::<Clock>(&got_clock_buf_rw).unwrap();
  3751. assert_eq!(clock_from_buf, src_clock);
  3752. }
  3753. }
  3754. type BuiltinFunctionRustInterface<'a> = fn(
  3755. &mut InvokeContext<'a, 'a>,
  3756. u64,
  3757. u64,
  3758. u64,
  3759. u64,
  3760. u64,
  3761. &mut MemoryMapping,
  3762. ) -> Result<u64, Box<dyn std::error::Error>>;
  3763. fn call_program_address_common<'a, 'b: 'a>(
  3764. invoke_context: &'a mut InvokeContext<'b, 'b>,
  3765. seeds: &[&[u8]],
  3766. program_id: &Pubkey,
  3767. overlap_outputs: bool,
  3768. syscall: BuiltinFunctionRustInterface<'b>,
  3769. ) -> Result<(Pubkey, u8), Error> {
  3770. const SEEDS_VA: u64 = 0x100000000;
  3771. const PROGRAM_ID_VA: u64 = 0x200000000;
  3772. const ADDRESS_VA: u64 = 0x300000000;
  3773. const BUMP_SEED_VA: u64 = 0x400000000;
  3774. const SEED_VA: u64 = 0x500000000;
  3775. let config = Config::default();
  3776. let mut address = Pubkey::default();
  3777. let mut bump_seed = 0;
  3778. let mut regions = vec![
  3779. MemoryRegion::new_readonly(bytes_of(program_id), PROGRAM_ID_VA),
  3780. MemoryRegion::new_writable(bytes_of_mut(&mut address), ADDRESS_VA),
  3781. MemoryRegion::new_writable(bytes_of_mut(&mut bump_seed), BUMP_SEED_VA),
  3782. ];
  3783. let mut mock_slices = Vec::with_capacity(seeds.len());
  3784. for (i, seed) in seeds.iter().enumerate() {
  3785. let vm_addr = SEED_VA.saturating_add((i as u64).saturating_mul(0x100000000));
  3786. let mock_slice = MockSlice {
  3787. vm_addr,
  3788. len: seed.len(),
  3789. };
  3790. mock_slices.push(mock_slice);
  3791. regions.push(MemoryRegion::new_readonly(bytes_of_slice(seed), vm_addr));
  3792. }
  3793. regions.push(MemoryRegion::new_readonly(
  3794. bytes_of_slice(&mock_slices),
  3795. SEEDS_VA,
  3796. ));
  3797. let mut memory_mapping = MemoryMapping::new(regions, &config, SBPFVersion::V3).unwrap();
  3798. let result = syscall(
  3799. invoke_context,
  3800. SEEDS_VA,
  3801. seeds.len() as u64,
  3802. PROGRAM_ID_VA,
  3803. ADDRESS_VA,
  3804. if overlap_outputs {
  3805. ADDRESS_VA
  3806. } else {
  3807. BUMP_SEED_VA
  3808. },
  3809. &mut memory_mapping,
  3810. );
  3811. result.map(|_| (address, bump_seed))
  3812. }
  3813. fn create_program_address<'a>(
  3814. invoke_context: &mut InvokeContext<'a, 'a>,
  3815. seeds: &[&[u8]],
  3816. address: &Pubkey,
  3817. ) -> Result<Pubkey, Error> {
  3818. let (address, _) = call_program_address_common(
  3819. invoke_context,
  3820. seeds,
  3821. address,
  3822. false,
  3823. SyscallCreateProgramAddress::rust,
  3824. )?;
  3825. Ok(address)
  3826. }
  3827. fn try_find_program_address<'a>(
  3828. invoke_context: &mut InvokeContext<'a, 'a>,
  3829. seeds: &[&[u8]],
  3830. address: &Pubkey,
  3831. ) -> Result<(Pubkey, u8), Error> {
  3832. call_program_address_common(
  3833. invoke_context,
  3834. seeds,
  3835. address,
  3836. false,
  3837. SyscallTryFindProgramAddress::rust,
  3838. )
  3839. }
  3840. #[test]
  3841. fn test_set_and_get_return_data() {
  3842. const SRC_VA: u64 = 0x100000000;
  3843. const DST_VA: u64 = 0x200000000;
  3844. const PROGRAM_ID_VA: u64 = 0x300000000;
  3845. let data = vec![42; 24];
  3846. let mut data_buffer = vec![0; 16];
  3847. let mut id_buffer = vec![0; 32];
  3848. let config = Config::default();
  3849. let mut memory_mapping = MemoryMapping::new(
  3850. vec![
  3851. MemoryRegion::new_readonly(&data, SRC_VA),
  3852. MemoryRegion::new_writable(&mut data_buffer, DST_VA),
  3853. MemoryRegion::new_writable(&mut id_buffer, PROGRAM_ID_VA),
  3854. ],
  3855. &config,
  3856. SBPFVersion::V3,
  3857. )
  3858. .unwrap();
  3859. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  3860. let result = SyscallSetReturnData::rust(
  3861. &mut invoke_context,
  3862. SRC_VA,
  3863. data.len() as u64,
  3864. 0,
  3865. 0,
  3866. 0,
  3867. &mut memory_mapping,
  3868. );
  3869. assert_eq!(result.unwrap(), 0);
  3870. let result = SyscallGetReturnData::rust(
  3871. &mut invoke_context,
  3872. DST_VA,
  3873. data_buffer.len() as u64,
  3874. PROGRAM_ID_VA,
  3875. 0,
  3876. 0,
  3877. &mut memory_mapping,
  3878. );
  3879. assert_eq!(result.unwrap() as usize, data.len());
  3880. assert_eq!(data.get(0..data_buffer.len()).unwrap(), data_buffer);
  3881. assert_eq!(id_buffer, program_id.to_bytes());
  3882. let result = SyscallGetReturnData::rust(
  3883. &mut invoke_context,
  3884. PROGRAM_ID_VA,
  3885. data_buffer.len() as u64,
  3886. PROGRAM_ID_VA,
  3887. 0,
  3888. 0,
  3889. &mut memory_mapping,
  3890. );
  3891. assert_matches!(
  3892. result,
  3893. Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
  3894. );
  3895. }
  3896. #[test]
  3897. fn test_syscall_sol_get_processed_sibling_instruction() {
  3898. let transaction_accounts = (0..9)
  3899. .map(|_| {
  3900. (
  3901. Pubkey::new_unique(),
  3902. AccountSharedData::new(0, 0, &bpf_loader::id()),
  3903. )
  3904. })
  3905. .collect::<Vec<_>>();
  3906. let instruction_trace = [1, 2, 3, 2, 2, 3, 4, 3];
  3907. with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
  3908. for (index_in_trace, stack_height) in instruction_trace.into_iter().enumerate() {
  3909. while stack_height
  3910. <= invoke_context
  3911. .transaction_context
  3912. .get_instruction_stack_height()
  3913. {
  3914. invoke_context.transaction_context.pop().unwrap();
  3915. }
  3916. if stack_height
  3917. > invoke_context
  3918. .transaction_context
  3919. .get_instruction_stack_height()
  3920. {
  3921. let instruction_accounts = vec![InstructionAccount::new(
  3922. index_in_trace.saturating_add(1) as IndexOfAccount,
  3923. false,
  3924. false,
  3925. )];
  3926. invoke_context
  3927. .transaction_context
  3928. .configure_next_instruction_for_tests(
  3929. 0,
  3930. instruction_accounts,
  3931. vec![index_in_trace as u8],
  3932. )
  3933. .unwrap();
  3934. invoke_context.transaction_context.push().unwrap();
  3935. }
  3936. }
  3937. let syscall_base_cost = invoke_context.get_execution_cost().syscall_base_cost;
  3938. const VM_BASE_ADDRESS: u64 = 0x100000000;
  3939. const META_OFFSET: usize = 0;
  3940. const PROGRAM_ID_OFFSET: usize =
  3941. META_OFFSET + std::mem::size_of::<ProcessedSiblingInstruction>();
  3942. const DATA_OFFSET: usize = PROGRAM_ID_OFFSET + std::mem::size_of::<Pubkey>();
  3943. const ACCOUNTS_OFFSET: usize = DATA_OFFSET + 0x100;
  3944. const END_OFFSET: usize = ACCOUNTS_OFFSET + std::mem::size_of::<AccountInfo>() * 4;
  3945. let mut memory = [0u8; END_OFFSET];
  3946. let config = Config::default();
  3947. let mut memory_mapping = MemoryMapping::new(
  3948. vec![MemoryRegion::new_writable(&mut memory, VM_BASE_ADDRESS)],
  3949. &config,
  3950. SBPFVersion::V3,
  3951. )
  3952. .unwrap();
  3953. let processed_sibling_instruction =
  3954. unsafe { &mut *memory.as_mut_ptr().cast::<ProcessedSiblingInstruction>() };
  3955. processed_sibling_instruction.data_len = 1;
  3956. processed_sibling_instruction.accounts_len = 1;
  3957. invoke_context.mock_set_remaining(syscall_base_cost);
  3958. let result = SyscallGetProcessedSiblingInstruction::rust(
  3959. &mut invoke_context,
  3960. 0,
  3961. VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
  3962. VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
  3963. VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
  3964. VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
  3965. &mut memory_mapping,
  3966. );
  3967. assert_eq!(result.unwrap(), 1);
  3968. {
  3969. let program_id = translate_type::<Pubkey>(
  3970. &memory_mapping,
  3971. VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
  3972. true,
  3973. )
  3974. .unwrap();
  3975. let data = translate_slice::<u8>(
  3976. &memory_mapping,
  3977. VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
  3978. processed_sibling_instruction.data_len,
  3979. true,
  3980. )
  3981. .unwrap();
  3982. let accounts = translate_slice::<AccountMeta>(
  3983. &memory_mapping,
  3984. VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
  3985. processed_sibling_instruction.accounts_len,
  3986. true,
  3987. )
  3988. .unwrap();
  3989. let transaction_context = &invoke_context.transaction_context;
  3990. assert_eq!(processed_sibling_instruction.data_len, 1);
  3991. assert_eq!(processed_sibling_instruction.accounts_len, 1);
  3992. assert_eq!(
  3993. program_id,
  3994. transaction_context.get_key_of_account_at_index(0).unwrap(),
  3995. );
  3996. assert_eq!(data, &[5]);
  3997. assert_eq!(
  3998. accounts,
  3999. &[AccountMeta {
  4000. pubkey: *transaction_context.get_key_of_account_at_index(6).unwrap(),
  4001. is_signer: false,
  4002. is_writable: false
  4003. }]
  4004. );
  4005. }
  4006. invoke_context.mock_set_remaining(syscall_base_cost);
  4007. let result = SyscallGetProcessedSiblingInstruction::rust(
  4008. &mut invoke_context,
  4009. 1,
  4010. VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
  4011. VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
  4012. VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
  4013. VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
  4014. &mut memory_mapping,
  4015. );
  4016. assert_eq!(result.unwrap(), 0);
  4017. invoke_context.mock_set_remaining(syscall_base_cost);
  4018. let result = SyscallGetProcessedSiblingInstruction::rust(
  4019. &mut invoke_context,
  4020. 0,
  4021. VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
  4022. VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
  4023. VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
  4024. VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
  4025. &mut memory_mapping,
  4026. );
  4027. assert_matches!(
  4028. result,
  4029. Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
  4030. );
  4031. }
  4032. #[test]
  4033. fn test_create_program_address() {
  4034. // These tests duplicate the direct tests in solana_pubkey
  4035. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  4036. let address = bpf_loader_upgradeable::id();
  4037. let exceeded_seed = &[127; MAX_SEED_LEN + 1];
  4038. assert_matches!(
  4039. create_program_address(&mut invoke_context, &[exceeded_seed], &address),
  4040. Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
  4041. );
  4042. assert_matches!(
  4043. create_program_address(
  4044. &mut invoke_context,
  4045. &[b"short_seed", exceeded_seed],
  4046. &address,
  4047. ),
  4048. Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
  4049. );
  4050. let max_seed = &[0; MAX_SEED_LEN];
  4051. assert!(create_program_address(&mut invoke_context, &[max_seed], &address).is_ok());
  4052. let exceeded_seeds: &[&[u8]] = &[
  4053. &[1],
  4054. &[2],
  4055. &[3],
  4056. &[4],
  4057. &[5],
  4058. &[6],
  4059. &[7],
  4060. &[8],
  4061. &[9],
  4062. &[10],
  4063. &[11],
  4064. &[12],
  4065. &[13],
  4066. &[14],
  4067. &[15],
  4068. &[16],
  4069. ];
  4070. assert!(create_program_address(&mut invoke_context, exceeded_seeds, &address).is_ok());
  4071. let max_seeds: &[&[u8]] = &[
  4072. &[1],
  4073. &[2],
  4074. &[3],
  4075. &[4],
  4076. &[5],
  4077. &[6],
  4078. &[7],
  4079. &[8],
  4080. &[9],
  4081. &[10],
  4082. &[11],
  4083. &[12],
  4084. &[13],
  4085. &[14],
  4086. &[15],
  4087. &[16],
  4088. &[17],
  4089. ];
  4090. assert_matches!(
  4091. create_program_address(&mut invoke_context, max_seeds, &address),
  4092. Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
  4093. );
  4094. assert_eq!(
  4095. create_program_address(&mut invoke_context, &[b"", &[1]], &address).unwrap(),
  4096. "BwqrghZA2htAcqq8dzP1WDAhTXYTYWj7CHxF5j7TDBAe"
  4097. .parse()
  4098. .unwrap(),
  4099. );
  4100. assert_eq!(
  4101. create_program_address(&mut invoke_context, &["☉".as_ref(), &[0]], &address).unwrap(),
  4102. "13yWmRpaTR4r5nAktwLqMpRNr28tnVUZw26rTvPSSB19"
  4103. .parse()
  4104. .unwrap(),
  4105. );
  4106. assert_eq!(
  4107. create_program_address(&mut invoke_context, &[b"Talking", b"Squirrels"], &address)
  4108. .unwrap(),
  4109. "2fnQrngrQT4SeLcdToJAD96phoEjNL2man2kfRLCASVk"
  4110. .parse()
  4111. .unwrap(),
  4112. );
  4113. let public_key = Pubkey::from_str("SeedPubey1111111111111111111111111111111111").unwrap();
  4114. assert_eq!(
  4115. create_program_address(&mut invoke_context, &[public_key.as_ref(), &[1]], &address)
  4116. .unwrap(),
  4117. "976ymqVnfE32QFe6NfGDctSvVa36LWnvYxhU6G2232YL"
  4118. .parse()
  4119. .unwrap(),
  4120. );
  4121. assert_ne!(
  4122. create_program_address(&mut invoke_context, &[b"Talking", b"Squirrels"], &address)
  4123. .unwrap(),
  4124. create_program_address(&mut invoke_context, &[b"Talking"], &address).unwrap(),
  4125. );
  4126. invoke_context.mock_set_remaining(0);
  4127. assert_matches!(
  4128. create_program_address(&mut invoke_context, &[b"", &[1]], &address),
  4129. Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
  4130. );
  4131. }
  4132. #[test]
  4133. fn test_find_program_address() {
  4134. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  4135. let cost = invoke_context
  4136. .get_execution_cost()
  4137. .create_program_address_units;
  4138. let address = bpf_loader_upgradeable::id();
  4139. let max_tries = 256; // one per seed
  4140. for _ in 0..1_000 {
  4141. let address = Pubkey::new_unique();
  4142. invoke_context.mock_set_remaining(cost * max_tries);
  4143. let (found_address, bump_seed) =
  4144. try_find_program_address(&mut invoke_context, &[b"Lil'", b"Bits"], &address)
  4145. .unwrap();
  4146. assert_eq!(
  4147. found_address,
  4148. create_program_address(
  4149. &mut invoke_context,
  4150. &[b"Lil'", b"Bits", &[bump_seed]],
  4151. &address,
  4152. )
  4153. .unwrap()
  4154. );
  4155. }
  4156. let seeds: &[&[u8]] = &[b""];
  4157. invoke_context.mock_set_remaining(cost * max_tries);
  4158. let (_, bump_seed) =
  4159. try_find_program_address(&mut invoke_context, seeds, &address).unwrap();
  4160. invoke_context.mock_set_remaining(cost * (max_tries - bump_seed as u64));
  4161. try_find_program_address(&mut invoke_context, seeds, &address).unwrap();
  4162. invoke_context.mock_set_remaining(cost * (max_tries - bump_seed as u64 - 1));
  4163. assert_matches!(
  4164. try_find_program_address(&mut invoke_context, seeds, &address),
  4165. Result::Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ComputationalBudgetExceeded
  4166. );
  4167. let exceeded_seed = &[127; MAX_SEED_LEN + 1];
  4168. invoke_context.mock_set_remaining(cost * (max_tries - 1));
  4169. assert_matches!(
  4170. try_find_program_address(&mut invoke_context, &[exceeded_seed], &address),
  4171. Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
  4172. );
  4173. let exceeded_seeds: &[&[u8]] = &[
  4174. &[1],
  4175. &[2],
  4176. &[3],
  4177. &[4],
  4178. &[5],
  4179. &[6],
  4180. &[7],
  4181. &[8],
  4182. &[9],
  4183. &[10],
  4184. &[11],
  4185. &[12],
  4186. &[13],
  4187. &[14],
  4188. &[15],
  4189. &[16],
  4190. &[17],
  4191. ];
  4192. invoke_context.mock_set_remaining(cost * (max_tries - 1));
  4193. assert_matches!(
  4194. try_find_program_address(&mut invoke_context, exceeded_seeds, &address),
  4195. Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded)
  4196. );
  4197. assert_matches!(
  4198. call_program_address_common(
  4199. &mut invoke_context,
  4200. seeds,
  4201. &address,
  4202. true,
  4203. SyscallTryFindProgramAddress::rust,
  4204. ),
  4205. Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
  4206. );
  4207. }
  4208. #[test]
  4209. fn test_syscall_big_mod_exp() {
  4210. let config = Config::default();
  4211. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  4212. const VADDR_PARAMS: u64 = 0x100000000;
  4213. const MAX_LEN: u64 = 512;
  4214. const INV_LEN: u64 = MAX_LEN + 1;
  4215. let data: [u8; INV_LEN as usize] = [0; INV_LEN as usize];
  4216. const VADDR_DATA: u64 = 0x200000000;
  4217. let mut data_out: [u8; INV_LEN as usize] = [0; INV_LEN as usize];
  4218. const VADDR_OUT: u64 = 0x300000000;
  4219. // Test that SyscallBigModExp succeeds with the maximum param size
  4220. {
  4221. let params_max_len = BigModExpParams {
  4222. base: VADDR_DATA as *const u8,
  4223. base_len: MAX_LEN,
  4224. exponent: VADDR_DATA as *const u8,
  4225. exponent_len: MAX_LEN,
  4226. modulus: VADDR_DATA as *const u8,
  4227. modulus_len: MAX_LEN,
  4228. };
  4229. let mut memory_mapping = MemoryMapping::new(
  4230. vec![
  4231. MemoryRegion::new_readonly(bytes_of(&params_max_len), VADDR_PARAMS),
  4232. MemoryRegion::new_readonly(&data, VADDR_DATA),
  4233. MemoryRegion::new_writable(&mut data_out, VADDR_OUT),
  4234. ],
  4235. &config,
  4236. SBPFVersion::V3,
  4237. )
  4238. .unwrap();
  4239. let budget = invoke_context.get_execution_cost();
  4240. invoke_context.mock_set_remaining(
  4241. budget.syscall_base_cost
  4242. + (MAX_LEN * MAX_LEN) / budget.big_modular_exponentiation_cost_divisor
  4243. + budget.big_modular_exponentiation_base_cost,
  4244. );
  4245. let result = SyscallBigModExp::rust(
  4246. &mut invoke_context,
  4247. VADDR_PARAMS,
  4248. VADDR_OUT,
  4249. 0,
  4250. 0,
  4251. 0,
  4252. &mut memory_mapping,
  4253. );
  4254. assert_eq!(result.unwrap(), 0);
  4255. }
  4256. // Test that SyscallBigModExp fails when the maximum param size is exceeded
  4257. {
  4258. let params_inv_len = BigModExpParams {
  4259. base: VADDR_DATA as *const u8,
  4260. base_len: INV_LEN,
  4261. exponent: VADDR_DATA as *const u8,
  4262. exponent_len: INV_LEN,
  4263. modulus: VADDR_DATA as *const u8,
  4264. modulus_len: INV_LEN,
  4265. };
  4266. let mut memory_mapping = MemoryMapping::new(
  4267. vec![
  4268. MemoryRegion::new_readonly(bytes_of(&params_inv_len), VADDR_PARAMS),
  4269. MemoryRegion::new_readonly(&data, VADDR_DATA),
  4270. MemoryRegion::new_writable(&mut data_out, VADDR_OUT),
  4271. ],
  4272. &config,
  4273. SBPFVersion::V3,
  4274. )
  4275. .unwrap();
  4276. let budget = invoke_context.get_execution_cost();
  4277. invoke_context.mock_set_remaining(
  4278. budget.syscall_base_cost
  4279. + (INV_LEN * INV_LEN) / budget.big_modular_exponentiation_cost_divisor
  4280. + budget.big_modular_exponentiation_base_cost,
  4281. );
  4282. let result = SyscallBigModExp::rust(
  4283. &mut invoke_context,
  4284. VADDR_PARAMS,
  4285. VADDR_OUT,
  4286. 0,
  4287. 0,
  4288. 0,
  4289. &mut memory_mapping,
  4290. );
  4291. assert_matches!(
  4292. result,
  4293. Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::InvalidLength
  4294. );
  4295. }
  4296. }
  4297. #[test]
  4298. fn test_syscall_get_epoch_stake_total_stake() {
  4299. let config = Config::default();
  4300. let compute_cost = SVMTransactionExecutionCost::default();
  4301. let mut compute_budget = SVMTransactionExecutionBudget::default();
  4302. let sysvar_cache = Arc::<SysvarCache>::default();
  4303. const EXPECTED_TOTAL_STAKE: u64 = 200_000_000_000_000;
  4304. struct MockCallback {}
  4305. impl InvokeContextCallback for MockCallback {
  4306. fn get_epoch_stake(&self) -> u64 {
  4307. EXPECTED_TOTAL_STAKE
  4308. }
  4309. // Vote accounts are not needed for this test.
  4310. }
  4311. // Compute units, as specified by SIMD-0133.
  4312. // cu = syscall_base_cost
  4313. let expected_cus = compute_cost.syscall_base_cost;
  4314. // Set the compute budget to the expected CUs to ensure the syscall
  4315. // doesn't exceed the expected usage.
  4316. compute_budget.compute_unit_limit = expected_cus;
  4317. with_mock_invoke_context!(invoke_context, transaction_context, vec![]);
  4318. let feature_set = SVMFeatureSet::default();
  4319. let program_runtime_environments = ProgramRuntimeEnvironments::default();
  4320. invoke_context.environment_config = EnvironmentConfig::new(
  4321. Hash::default(),
  4322. 0,
  4323. &MockCallback {},
  4324. &feature_set,
  4325. &program_runtime_environments,
  4326. &program_runtime_environments,
  4327. &sysvar_cache,
  4328. );
  4329. let null_pointer_var = std::ptr::null::<Pubkey>() as u64;
  4330. let mut memory_mapping = MemoryMapping::new(vec![], &config, SBPFVersion::V3).unwrap();
  4331. let result = SyscallGetEpochStake::rust(
  4332. &mut invoke_context,
  4333. null_pointer_var,
  4334. 0,
  4335. 0,
  4336. 0,
  4337. 0,
  4338. &mut memory_mapping,
  4339. )
  4340. .unwrap();
  4341. assert_eq!(result, EXPECTED_TOTAL_STAKE);
  4342. }
  4343. #[test]
  4344. fn test_syscall_get_epoch_stake_vote_account_stake() {
  4345. let config = Config::default();
  4346. let mut compute_budget = SVMTransactionExecutionBudget::default();
  4347. let compute_cost = SVMTransactionExecutionCost::default();
  4348. let sysvar_cache = Arc::<SysvarCache>::default();
  4349. const TARGET_VOTE_ADDRESS: Pubkey = Pubkey::new_from_array([2; 32]);
  4350. const EXPECTED_EPOCH_STAKE: u64 = 55_000_000_000;
  4351. struct MockCallback {}
  4352. impl InvokeContextCallback for MockCallback {
  4353. // Total stake is not needed for this test.
  4354. fn get_epoch_stake_for_vote_account(&self, vote_address: &Pubkey) -> u64 {
  4355. if *vote_address == TARGET_VOTE_ADDRESS {
  4356. EXPECTED_EPOCH_STAKE
  4357. } else {
  4358. 0
  4359. }
  4360. }
  4361. }
  4362. // Compute units, as specified by SIMD-0133.
  4363. // cu = syscall_base_cost
  4364. // + floor(32/cpi_bytes_per_unit)
  4365. // + mem_op_base_cost
  4366. let expected_cus = compute_cost.syscall_base_cost
  4367. + (PUBKEY_BYTES as u64) / compute_cost.cpi_bytes_per_unit
  4368. + compute_cost.mem_op_base_cost;
  4369. // Set the compute budget to the expected CUs to ensure the syscall
  4370. // doesn't exceed the expected usage.
  4371. compute_budget.compute_unit_limit = expected_cus;
  4372. with_mock_invoke_context!(invoke_context, transaction_context, vec![]);
  4373. let feature_set = SVMFeatureSet::default();
  4374. let program_runtime_environments = ProgramRuntimeEnvironments::default();
  4375. invoke_context.environment_config = EnvironmentConfig::new(
  4376. Hash::default(),
  4377. 0,
  4378. &MockCallback {},
  4379. &feature_set,
  4380. &program_runtime_environments,
  4381. &program_runtime_environments,
  4382. &sysvar_cache,
  4383. );
  4384. {
  4385. // The syscall aborts the virtual machine if not all bytes in VM
  4386. // memory range `[vote_addr, vote_addr + 32)` are readable.
  4387. let vote_address_var = 0x100000000;
  4388. let mut memory_mapping = MemoryMapping::new(
  4389. vec![
  4390. // Invalid read-only memory region.
  4391. MemoryRegion::new_readonly(&[2; 31], vote_address_var),
  4392. ],
  4393. &config,
  4394. SBPFVersion::V3,
  4395. )
  4396. .unwrap();
  4397. let result = SyscallGetEpochStake::rust(
  4398. &mut invoke_context,
  4399. vote_address_var,
  4400. 0,
  4401. 0,
  4402. 0,
  4403. 0,
  4404. &mut memory_mapping,
  4405. );
  4406. assert_access_violation!(result, vote_address_var, 32);
  4407. }
  4408. invoke_context.mock_set_remaining(compute_budget.compute_unit_limit);
  4409. {
  4410. // Otherwise, the syscall returns a `u64` integer representing the
  4411. // total active stake delegated to the vote account at the provided
  4412. // address.
  4413. let vote_address_var = 0x100000000;
  4414. let mut memory_mapping = MemoryMapping::new(
  4415. vec![MemoryRegion::new_readonly(
  4416. bytes_of(&TARGET_VOTE_ADDRESS),
  4417. vote_address_var,
  4418. )],
  4419. &config,
  4420. SBPFVersion::V3,
  4421. )
  4422. .unwrap();
  4423. let result = SyscallGetEpochStake::rust(
  4424. &mut invoke_context,
  4425. vote_address_var,
  4426. 0,
  4427. 0,
  4428. 0,
  4429. 0,
  4430. &mut memory_mapping,
  4431. )
  4432. .unwrap();
  4433. assert_eq!(result, EXPECTED_EPOCH_STAKE);
  4434. }
  4435. invoke_context.mock_set_remaining(compute_budget.compute_unit_limit);
  4436. {
  4437. // If the provided vote address corresponds to an account that is
  4438. // not a vote account or does not exist, the syscall will write
  4439. // `0` for active stake.
  4440. let vote_address_var = 0x100000000;
  4441. let not_a_vote_address = Pubkey::new_unique(); // Not a vote account.
  4442. let mut memory_mapping = MemoryMapping::new(
  4443. vec![MemoryRegion::new_readonly(
  4444. bytes_of(&not_a_vote_address),
  4445. vote_address_var,
  4446. )],
  4447. &config,
  4448. SBPFVersion::V3,
  4449. )
  4450. .unwrap();
  4451. let result = SyscallGetEpochStake::rust(
  4452. &mut invoke_context,
  4453. vote_address_var,
  4454. 0,
  4455. 0,
  4456. 0,
  4457. 0,
  4458. &mut memory_mapping,
  4459. )
  4460. .unwrap();
  4461. assert_eq!(result, 0); // `0` for active stake.
  4462. }
  4463. }
  4464. #[test]
  4465. fn test_check_type_assumptions() {
  4466. check_type_assumptions();
  4467. }
  4468. fn bytes_of<T>(val: &T) -> &[u8] {
  4469. let size = mem::size_of::<T>();
  4470. unsafe { slice::from_raw_parts(std::slice::from_ref(val).as_ptr().cast(), size) }
  4471. }
  4472. fn bytes_of_mut<T>(val: &mut T) -> &mut [u8] {
  4473. let size = mem::size_of::<T>();
  4474. unsafe { slice::from_raw_parts_mut(slice::from_mut(val).as_mut_ptr().cast(), size) }
  4475. }
  4476. fn bytes_of_slice<T>(val: &[T]) -> &[u8] {
  4477. let size = val.len().wrapping_mul(mem::size_of::<T>());
  4478. unsafe { slice::from_raw_parts(val.as_ptr().cast(), size) }
  4479. }
  4480. fn bytes_of_slice_mut<T>(val: &mut [T]) -> &mut [u8] {
  4481. let size = val.len().wrapping_mul(mem::size_of::<T>());
  4482. unsafe { slice::from_raw_parts_mut(val.as_mut_ptr().cast(), size) }
  4483. }
  4484. #[test]
  4485. fn test_address_is_aligned() {
  4486. for address in 0..std::mem::size_of::<u64>() {
  4487. assert_eq!(address_is_aligned::<u64>(address as u64), address == 0);
  4488. }
  4489. }
  4490. #[test_case(0x100000004, 0x100000004, &[0x00, 0x00, 0x00, 0x00])] // Intra region match
  4491. #[test_case(0x100000003, 0x100000004, &[0xFF, 0xFF, 0xFF, 0xFF])] // Intra region down
  4492. #[test_case(0x100000005, 0x100000004, &[0x01, 0x00, 0x00, 0x00])] // Intra region up
  4493. #[test_case(0x100000004, 0x200000004, &[0x00, 0x00, 0x00, 0x00])] // Inter region match
  4494. #[test_case(0x100000003, 0x200000004, &[0xFF, 0xFF, 0xFF, 0xFF])] // Inter region down
  4495. #[test_case(0x100000005, 0x200000004, &[0x01, 0x00, 0x00, 0x00])] // Inter region up
  4496. fn test_memcmp_success(src_a: u64, src_b: u64, expected_result: &[u8; 4]) {
  4497. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  4498. let mem = (0..12).collect::<Vec<u8>>();
  4499. let mut result_mem = vec![0; 4];
  4500. let config = Config::default();
  4501. let mut memory_mapping = MemoryMapping::new(
  4502. vec![
  4503. MemoryRegion::new_readonly(&mem, 0x100000000),
  4504. MemoryRegion::new_readonly(&mem, 0x200000000),
  4505. MemoryRegion::new_writable(&mut result_mem, 0x300000000),
  4506. ],
  4507. &config,
  4508. SBPFVersion::V3,
  4509. )
  4510. .unwrap();
  4511. let result = SyscallMemcmp::rust(
  4512. &mut invoke_context,
  4513. src_a,
  4514. src_b,
  4515. 4,
  4516. 0x300000000,
  4517. 0,
  4518. &mut memory_mapping,
  4519. );
  4520. result.unwrap();
  4521. assert_eq!(result_mem, expected_result);
  4522. }
  4523. #[test_case(0x100000002, 0x100000004, 18245498089483734664)] // Down overlapping
  4524. #[test_case(0x100000004, 0x100000002, 6092969436446403628)] // Up overlapping
  4525. #[test_case(0x100000002, 0x100000006, 16598193894146733116)] // Down touching
  4526. #[test_case(0x100000006, 0x100000002, 8940776276357560353)] // Up touching
  4527. #[test_case(0x100000000, 0x100000008, 1288053912680171784)] // Down apart
  4528. #[test_case(0x100000008, 0x100000000, 4652742827052033592)] // Up apart
  4529. #[test_case(0x100000004, 0x200000004, 8833460765081683332)] // Down inter region
  4530. #[test_case(0x200000004, 0x100000004, 11837649335115988407)] // Up inter region
  4531. fn test_memmove_success(dst: u64, src: u64, expected_hash: u64) {
  4532. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  4533. let mut mem = (0..24).collect::<Vec<u8>>();
  4534. let config = Config::default();
  4535. let mut memory_mapping = MemoryMapping::new(
  4536. vec![
  4537. MemoryRegion::new_writable(&mut mem[..12], 0x100000000),
  4538. MemoryRegion::new_writable(&mut mem[12..], 0x200000000),
  4539. ],
  4540. &config,
  4541. SBPFVersion::V3,
  4542. )
  4543. .unwrap();
  4544. let result =
  4545. SyscallMemmove::rust(&mut invoke_context, dst, src, 4, 0, 0, &mut memory_mapping);
  4546. result.unwrap();
  4547. let mut hasher = DefaultHasher::new();
  4548. mem.hash(&mut hasher);
  4549. assert_eq!(hasher.finish(), expected_hash);
  4550. }
  4551. #[test_case(0x100000002, 0x00, 6070675560359421890)]
  4552. #[test_case(0x100000002, 0xFF, 3413209638111181029)]
  4553. fn test_memset_success(dst: u64, value: u64, expected_hash: u64) {
  4554. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  4555. let mut mem = (0..12).collect::<Vec<u8>>();
  4556. let config = Config::default();
  4557. let mut memory_mapping = MemoryMapping::new(
  4558. vec![MemoryRegion::new_writable(&mut mem, 0x100000000)],
  4559. &config,
  4560. SBPFVersion::V3,
  4561. )
  4562. .unwrap();
  4563. let result = SyscallMemset::rust(
  4564. &mut invoke_context,
  4565. dst,
  4566. value,
  4567. 4,
  4568. 0,
  4569. 0,
  4570. &mut memory_mapping,
  4571. );
  4572. result.unwrap();
  4573. let mut hasher = DefaultHasher::new();
  4574. mem.hash(&mut hasher);
  4575. assert_eq!(hasher.finish(), expected_hash);
  4576. }
  4577. #[test_case(0x100000002, 0x100000004)] // Down overlapping
  4578. #[test_case(0x100000004, 0x100000002)] // Up overlapping
  4579. fn test_memcpy_overlapping(dst: u64, src: u64) {
  4580. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  4581. let mut mem = (0..12).collect::<Vec<u8>>();
  4582. let config = Config::default();
  4583. let mut memory_mapping = MemoryMapping::new(
  4584. vec![MemoryRegion::new_writable(&mut mem, 0x100000000)],
  4585. &config,
  4586. SBPFVersion::V3,
  4587. )
  4588. .unwrap();
  4589. let result =
  4590. SyscallMemcpy::rust(&mut invoke_context, dst, src, 4, 0, 0, &mut memory_mapping);
  4591. assert_matches!(
  4592. result,
  4593. Result::Err(error) if error.downcast_ref::<SyscallError>().unwrap() == &SyscallError::CopyOverlapping
  4594. );
  4595. }
  4596. #[test_case(0xFFFFFFFFF, 0x100000006, 0xFFFFFFFFF)] // Dst lower bound
  4597. #[test_case(0x100000010, 0x100000006, 0x100000010)] // Dst upper bound
  4598. #[test_case(0x100000002, 0xFFFFFFFFF, 0xFFFFFFFFF)] // Src lower bound
  4599. #[test_case(0x100000002, 0x100000010, 0x100000010)] // Src upper bound
  4600. fn test_memops_access_violation(dst: u64, src: u64, fault_address: u64) {
  4601. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  4602. let mut mem = (0..12).collect::<Vec<u8>>();
  4603. let config = Config::default();
  4604. let mut memory_mapping = MemoryMapping::new(
  4605. vec![MemoryRegion::new_writable(&mut mem, 0x100000000)],
  4606. &config,
  4607. SBPFVersion::V3,
  4608. )
  4609. .unwrap();
  4610. let result =
  4611. SyscallMemcpy::rust(&mut invoke_context, dst, src, 4, 0, 0, &mut memory_mapping);
  4612. assert_access_violation!(result, fault_address, 4);
  4613. let result =
  4614. SyscallMemmove::rust(&mut invoke_context, dst, src, 4, 0, 0, &mut memory_mapping);
  4615. assert_access_violation!(result, fault_address, 4);
  4616. let result =
  4617. SyscallMemcmp::rust(&mut invoke_context, dst, src, 4, 0, 0, &mut memory_mapping);
  4618. assert_access_violation!(result, fault_address, 4);
  4619. }
  4620. #[test_case(0xFFFFFFFFF)] // Dst lower bound
  4621. #[test_case(0x100000010)] // Dst upper bound
  4622. fn test_memset_access_violation(dst: u64) {
  4623. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  4624. let mut mem = (0..12).collect::<Vec<u8>>();
  4625. let config = Config::default();
  4626. let mut memory_mapping = MemoryMapping::new(
  4627. vec![MemoryRegion::new_writable(&mut mem, 0x100000000)],
  4628. &config,
  4629. SBPFVersion::V3,
  4630. )
  4631. .unwrap();
  4632. let result = SyscallMemset::rust(&mut invoke_context, dst, 0, 4, 0, 0, &mut memory_mapping);
  4633. assert_access_violation!(result, dst, 4);
  4634. }
  4635. #[test]
  4636. fn test_memcmp_result_access_violation() {
  4637. prepare_mockup!(invoke_context, program_id, bpf_loader::id());
  4638. let mem = (0..12).collect::<Vec<u8>>();
  4639. let config = Config::default();
  4640. let mut memory_mapping = MemoryMapping::new(
  4641. vec![MemoryRegion::new_readonly(&mem, 0x100000000)],
  4642. &config,
  4643. SBPFVersion::V3,
  4644. )
  4645. .unwrap();
  4646. let result = SyscallMemcmp::rust(
  4647. &mut invoke_context,
  4648. 0x100000000,
  4649. 0x100000000,
  4650. 4,
  4651. 0x100000000,
  4652. 0,
  4653. &mut memory_mapping,
  4654. );
  4655. assert_access_violation!(result, 0x100000000, 4);
  4656. }
  4657. }