programs.rs 207 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658
  1. #![cfg(any(feature = "sbf_c", feature = "sbf_rust"))]
  2. #![allow(clippy::clone_on_copy)]
  3. #![allow(clippy::needless_range_loop)]
  4. #![allow(clippy::needless_borrow)]
  5. #![allow(clippy::cmp_owned)]
  6. #![allow(clippy::match_like_matches_macro)]
  7. #![allow(clippy::unnecessary_cast)]
  8. #![allow(clippy::uninlined_format_args)]
  9. #[cfg(feature = "sbf_rust")]
  10. use {
  11. agave_feature_set::{self as feature_set, FeatureSet},
  12. agave_reserved_account_keys::ReservedAccountKeys,
  13. borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize},
  14. solana_account::{AccountSharedData, ReadableAccount, WritableAccount},
  15. solana_account_info::MAX_PERMITTED_DATA_INCREASE,
  16. solana_client_traits::SyncClient,
  17. solana_clock::{UnixTimestamp, MAX_PROCESSING_AGE},
  18. solana_cluster_type::ClusterType,
  19. solana_compute_budget::compute_budget::ComputeBudget,
  20. solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions,
  21. solana_compute_budget_interface::ComputeBudgetInstruction,
  22. solana_fee_calculator::FeeRateGovernor,
  23. solana_fee_structure::{FeeBin, FeeBudgetLimits, FeeStructure},
  24. solana_hash::Hash,
  25. solana_instruction::{error::InstructionError, AccountMeta, Instruction},
  26. solana_keypair::Keypair,
  27. solana_loader_v3_interface::instruction as loader_v3_instruction,
  28. solana_loader_v4_interface::instruction as loader_v4_instruction,
  29. solana_message::{inner_instruction::InnerInstruction, Message, SanitizedMessage},
  30. solana_program_runtime::invoke_context::mock_process_instruction,
  31. solana_pubkey::Pubkey,
  32. solana_rent::Rent,
  33. solana_runtime::{
  34. bank::Bank,
  35. bank_client::BankClient,
  36. bank_forks::BankForks,
  37. genesis_utils::{
  38. bootstrap_validator_stake_lamports, create_genesis_config,
  39. create_genesis_config_with_leader_ex, GenesisConfigInfo,
  40. },
  41. loader_utils::{
  42. create_program, instructions_to_load_program_of_loader_v4, load_program_from_file,
  43. load_program_of_loader_v4, load_upgradeable_buffer,
  44. },
  45. },
  46. solana_runtime_transaction::runtime_transaction::RuntimeTransaction,
  47. solana_sbf_rust_invoke_dep::*,
  48. solana_sbf_rust_realloc_dep::*,
  49. solana_sbf_rust_realloc_invoke_dep::*,
  50. solana_sbpf::vm::ContextObject,
  51. solana_sdk_ids::sysvar::{self as sysvar, clock},
  52. solana_sdk_ids::{bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, loader_v4},
  53. solana_signer::Signer,
  54. solana_svm::{
  55. transaction_commit_result::{CommittedTransaction, TransactionCommitResult},
  56. transaction_processor::ExecutionRecordingConfig,
  57. },
  58. solana_svm_timings::ExecuteTimings,
  59. solana_svm_transaction::svm_message::SVMStaticMessage,
  60. solana_svm_type_overrides::rand,
  61. solana_system_interface::{program as system_program, MAX_PERMITTED_DATA_LENGTH},
  62. solana_transaction::Transaction,
  63. solana_transaction_error::TransactionError,
  64. std::{
  65. assert_eq,
  66. cell::RefCell,
  67. str::FromStr,
  68. sync::{Arc, RwLock},
  69. time::Duration,
  70. },
  71. test_case::test_matrix,
  72. };
  73. #[cfg(all(
  74. any(feature = "sbf_c", feature = "sbf_rust"),
  75. not(feature = "sbf_sanity_list")
  76. ))]
  77. use {
  78. solana_account::Account,
  79. solana_program_runtime::sysvar_cache::SysvarCache,
  80. solana_sdk_ids::sysvar::rent,
  81. solana_svm_test_harness::{self as harness, fixture::instr_context::InstrContext},
  82. };
  83. #[cfg(feature = "sbf_rust")]
  84. fn process_transaction_and_record_inner(
  85. bank: &Bank,
  86. tx: Transaction,
  87. ) -> (
  88. Result<(), TransactionError>,
  89. Vec<Vec<InnerInstruction>>,
  90. Vec<String>,
  91. u64,
  92. ) {
  93. let commit_result = load_execute_and_commit_transaction(bank, tx);
  94. let CommittedTransaction {
  95. inner_instructions,
  96. log_messages,
  97. status,
  98. executed_units,
  99. ..
  100. } = commit_result.unwrap();
  101. let inner_instructions = inner_instructions.expect("cpi recording should be enabled");
  102. let log_messages = log_messages.expect("log recording should be enabled");
  103. (status, inner_instructions, log_messages, executed_units)
  104. }
  105. #[cfg(feature = "sbf_rust")]
  106. fn load_execute_and_commit_transaction(bank: &Bank, tx: Transaction) -> TransactionCommitResult {
  107. let txs = vec![tx];
  108. let tx_batch = bank.prepare_batch_for_tests(txs);
  109. let mut commit_results = bank
  110. .load_execute_and_commit_transactions(
  111. &tx_batch,
  112. MAX_PROCESSING_AGE,
  113. ExecutionRecordingConfig {
  114. enable_cpi_recording: true,
  115. enable_log_recording: true,
  116. enable_return_data_recording: false,
  117. enable_transaction_balance_recording: false,
  118. },
  119. &mut ExecuteTimings::default(),
  120. None,
  121. )
  122. .0;
  123. commit_results.pop().unwrap()
  124. }
  125. #[cfg(feature = "sbf_rust")]
  126. fn bank_with_feature_activated(
  127. bank_forks: &RwLock<BankForks>,
  128. parent: Arc<Bank>,
  129. feature_id: &Pubkey,
  130. ) -> Arc<Bank> {
  131. let slot = parent.slot().saturating_add(1);
  132. let mut bank = Bank::new_from_parent(parent, &Pubkey::new_unique(), slot);
  133. bank.activate_feature(feature_id);
  134. bank_forks
  135. .write()
  136. .unwrap()
  137. .insert(bank)
  138. .clone_without_scheduler()
  139. }
  140. #[cfg(feature = "sbf_rust")]
  141. fn bank_with_feature_deactivated(
  142. bank_forks: &RwLock<BankForks>,
  143. parent: Arc<Bank>,
  144. feature_id: &Pubkey,
  145. ) -> Arc<Bank> {
  146. let slot = parent.slot().saturating_add(1);
  147. let mut bank = Bank::new_from_parent(parent, &Pubkey::new_unique(), slot);
  148. bank.deactivate_feature(feature_id);
  149. bank_forks
  150. .write()
  151. .unwrap()
  152. .insert(bank)
  153. .clone_without_scheduler()
  154. }
  155. #[cfg(feature = "sbf_rust")]
  156. const LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST: u32 = 64 * 1024 * 1024;
  157. #[test]
  158. #[cfg(any(feature = "sbf_c", feature = "sbf_rust"))]
  159. fn test_program_sbf_sanity() {
  160. agave_logger::setup();
  161. let mut programs = Vec::new();
  162. #[cfg(feature = "sbf_c")]
  163. {
  164. programs.extend_from_slice(&[
  165. ("alloc", true),
  166. ("alt_bn128", true),
  167. ("alt_bn128_compression", true),
  168. ("sbf_to_sbf", true),
  169. ("float", true),
  170. ("multiple_static", true),
  171. ("noop", true),
  172. ("noop++", true),
  173. ("panic", false),
  174. ("poseidon", true),
  175. ("relative_call", true),
  176. ("return_data", true),
  177. ("sanity", true),
  178. ("sanity++", true),
  179. ("secp256k1_recover", true),
  180. ("sha", true),
  181. ("stdlib", true),
  182. ("struct_pass", true),
  183. ("struct_ret", true),
  184. ]);
  185. }
  186. #[cfg(feature = "sbf_rust")]
  187. {
  188. programs.extend_from_slice(&[
  189. ("solana_sbf_rust_128bit", true),
  190. ("solana_sbf_rust_alloc", true),
  191. ("solana_sbf_rust_alt_bn128", true),
  192. ("solana_sbf_rust_alt_bn128_compression", true),
  193. ("solana_sbf_rust_curve25519", true),
  194. ("solana_sbf_rust_custom_heap", true),
  195. ("solana_sbf_rust_dep_crate", true),
  196. ("solana_sbf_rust_external_spend", false),
  197. ("solana_sbf_rust_iter", true),
  198. ("solana_sbf_rust_many_args", true),
  199. ("solana_sbf_rust_mem", true),
  200. ("solana_sbf_rust_membuiltins", true),
  201. ("solana_sbf_rust_noop", true),
  202. ("solana_sbf_rust_panic", false),
  203. ("solana_sbf_rust_param_passing", true),
  204. ("solana_sbf_rust_poseidon", true),
  205. ("solana_sbf_rust_rand", true),
  206. ("solana_sbf_rust_remaining_compute_units", true),
  207. ("solana_sbf_rust_sanity", true),
  208. ("solana_sbf_rust_secp256k1_recover", true),
  209. ("solana_sbf_rust_sha", true),
  210. ]);
  211. }
  212. #[cfg(all(feature = "sbf_rust", feature = "sbf_sanity_list"))]
  213. {
  214. // This code generates the list of sanity programs for a CI job to build with
  215. // cargo-build-sbf and ensure it is working correctly.
  216. use std::{env, fs::File, io::Write};
  217. let current_dir = env::current_dir().unwrap();
  218. let mut file =
  219. File::create(current_dir.join("target").join("sanity_programs.txt")).unwrap();
  220. for program in programs.iter() {
  221. writeln!(file, "{}", program.0.trim_start_matches("solana_sbf_rust_"))
  222. .expect("Failed to write to file");
  223. }
  224. }
  225. #[cfg(not(feature = "sbf_sanity_list"))]
  226. for program in programs.iter() {
  227. println!("Test program: {:?}", program.0);
  228. let program_elf = harness::file::load_program_elf(program.0);
  229. let program_id = Pubkey::new_unique();
  230. let feature_set = FeatureSet::all_enabled();
  231. let pubkey1 = Pubkey::new_unique();
  232. let pubkey2 = Pubkey::new_unique();
  233. let account_metas = vec![
  234. AccountMeta::new(pubkey1, true),
  235. AccountMeta::new(pubkey2, false),
  236. ];
  237. let instruction = Instruction::new_with_bytes(program_id, &[1], account_metas);
  238. let accounts = vec![
  239. (
  240. program_id,
  241. Account {
  242. owner: loader_v4::id(),
  243. ..Default::default() // <-- Stubbed
  244. },
  245. ),
  246. (pubkey1, Account::default()),
  247. (pubkey2, Account::default()),
  248. ];
  249. let compute_budget = ComputeBudget::new_with_defaults(false, false);
  250. let mut program_cache =
  251. harness::program_cache::new_with_builtins(&feature_set, /* slot */ 0);
  252. harness::program_cache::add_program(
  253. &mut program_cache,
  254. &program_id,
  255. &loader_v4::id(),
  256. &program_elf,
  257. &feature_set,
  258. &compute_budget,
  259. );
  260. let mut sysvar_cache = SysvarCache::default();
  261. sysvar_cache.fill_missing_entries(|pubkey, callbackback| {
  262. if pubkey == &rent::id() {
  263. // Add the default Rent sysvar.
  264. let rent = Rent::default();
  265. let rent_data = bincode::serialize(&rent).unwrap();
  266. callbackback(&rent_data);
  267. }
  268. });
  269. let context = InstrContext {
  270. feature_set,
  271. accounts,
  272. instruction: instruction.into(),
  273. cu_avail: compute_budget.compute_unit_limit,
  274. };
  275. let effects = harness::instr::execute_instr(
  276. context,
  277. &compute_budget,
  278. &mut program_cache,
  279. &sysvar_cache,
  280. )
  281. .unwrap();
  282. let result = match effects.result {
  283. Some(err) => Err(err),
  284. None => Ok(()),
  285. };
  286. if program.1 {
  287. assert!(result.is_ok(), "{result:?}");
  288. } else {
  289. assert!(result.is_err(), "{result:?}");
  290. }
  291. }
  292. }
  293. #[test]
  294. #[cfg(any(feature = "sbf_c", feature = "sbf_rust"))]
  295. fn test_program_sbf_loader_deprecated() {
  296. agave_logger::setup();
  297. let mut programs = Vec::new();
  298. #[cfg(feature = "sbf_c")]
  299. {
  300. programs.extend_from_slice(&[("deprecated_loader")]);
  301. }
  302. #[cfg(feature = "sbf_rust")]
  303. {
  304. programs.extend_from_slice(&[("solana_sbf_rust_deprecated_loader")]);
  305. }
  306. for program in programs.iter() {
  307. println!("Test program: {:?}", program);
  308. let GenesisConfigInfo {
  309. mut genesis_config,
  310. mint_keypair,
  311. ..
  312. } = create_genesis_config(50);
  313. genesis_config
  314. .accounts
  315. .remove(&agave_feature_set::disable_deploy_of_alloc_free_syscall::id())
  316. .unwrap();
  317. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  318. let program_id = create_program(&bank, &bpf_loader_deprecated::id(), program);
  319. let mut bank_client = BankClient::new_shared(bank);
  320. bank_client
  321. .advance_slot(1, bank_forks.as_ref(), &Pubkey::default())
  322. .expect("Failed to advance the slot");
  323. let account_metas = vec![AccountMeta::new(mint_keypair.pubkey(), true)];
  324. let instruction = Instruction::new_with_bytes(program_id, &[255], account_metas);
  325. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  326. assert!(result.is_ok());
  327. }
  328. }
  329. #[test]
  330. #[cfg(feature = "sbf_rust")]
  331. #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: \
  332. TransactionError(InstructionError(0, InvalidAccountData))")]
  333. fn test_sol_alloc_free_no_longer_deployable_with_upgradeable_loader() {
  334. agave_logger::setup();
  335. let GenesisConfigInfo {
  336. genesis_config,
  337. mint_keypair,
  338. ..
  339. } = create_genesis_config(50);
  340. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  341. let mut bank_client = BankClient::new_shared(bank.clone());
  342. let authority_keypair = Keypair::new();
  343. // Populate loader account with `solana_sbf_rust_deprecated_loader` elf, which
  344. // depends on `sol_alloc_free_` syscall. This can be verified with
  345. // $ elfdump solana_sbf_rust_deprecated_loader.so
  346. // : 0000000000001ab8 000000070000000a R_BPF_64_32 0000000000000000 sol_alloc_free_
  347. // In the symbol table, there is `sol_alloc_free_`.
  348. // In fact, `sol_alloc_free_` is called from sbf allocator, which is originated from
  349. // AccountInfo::realloc() in the program code.
  350. // Expect that deployment to fail. B/C during deployment, there is an elf
  351. // verification step, which uses the runtime to look up relocatable symbols
  352. // in elf inside syscall table. In this case, `sol_alloc_free_` can't be
  353. // found in syscall table. Hence, the verification fails and the deployment
  354. // fails.
  355. let (_bank, _program_id) = load_program_of_loader_v4(
  356. &mut bank_client,
  357. &bank_forks,
  358. &mint_keypair,
  359. &authority_keypair,
  360. "solana_sbf_rust_deprecated_loader",
  361. );
  362. }
  363. #[test]
  364. #[cfg(feature = "sbf_rust")]
  365. fn test_program_sbf_duplicate_accounts() {
  366. agave_logger::setup();
  367. let mut programs = Vec::new();
  368. #[cfg(feature = "sbf_c")]
  369. {
  370. programs.extend_from_slice(&[("dup_accounts")]);
  371. }
  372. #[cfg(feature = "sbf_rust")]
  373. {
  374. programs.extend_from_slice(&[("solana_sbf_rust_dup_accounts")]);
  375. }
  376. for program in programs.iter() {
  377. println!("Test program: {:?}", program);
  378. let GenesisConfigInfo {
  379. genesis_config,
  380. mint_keypair,
  381. ..
  382. } = create_genesis_config(50);
  383. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  384. let mut bank_client = BankClient::new_shared(bank.clone());
  385. let authority_keypair = Keypair::new();
  386. let (bank, program_id) = load_program_of_loader_v4(
  387. &mut bank_client,
  388. &bank_forks,
  389. &mint_keypair,
  390. &authority_keypair,
  391. program,
  392. );
  393. let payee_account = AccountSharedData::new(10, 1, &program_id);
  394. let payee_pubkey = Pubkey::new_unique();
  395. bank.store_account(&payee_pubkey, &payee_account);
  396. let account = AccountSharedData::new(10, 1, &program_id);
  397. let pubkey = Pubkey::new_unique();
  398. let account_metas = vec![
  399. AccountMeta::new(mint_keypair.pubkey(), true),
  400. AccountMeta::new(payee_pubkey, false),
  401. AccountMeta::new(pubkey, false),
  402. AccountMeta::new(pubkey, false),
  403. ];
  404. bank.store_account(&pubkey, &account);
  405. let instruction = Instruction::new_with_bytes(program_id, &[1], account_metas.clone());
  406. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  407. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  408. assert!(result.is_ok());
  409. assert_eq!(data[0], 1);
  410. bank.store_account(&pubkey, &account);
  411. let instruction = Instruction::new_with_bytes(program_id, &[2], account_metas.clone());
  412. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  413. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  414. assert!(result.is_ok());
  415. assert_eq!(data[0], 2);
  416. bank.store_account(&pubkey, &account);
  417. let instruction = Instruction::new_with_bytes(program_id, &[3], account_metas.clone());
  418. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  419. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  420. assert!(result.is_ok());
  421. assert_eq!(data[0], 3);
  422. bank.store_account(&pubkey, &account);
  423. let instruction = Instruction::new_with_bytes(program_id, &[4], account_metas.clone());
  424. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  425. let lamports = bank_client.get_balance(&pubkey).unwrap();
  426. assert!(result.is_ok());
  427. assert_eq!(lamports, 11);
  428. bank.store_account(&pubkey, &account);
  429. let instruction = Instruction::new_with_bytes(program_id, &[5], account_metas.clone());
  430. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  431. let lamports = bank_client.get_balance(&pubkey).unwrap();
  432. assert!(result.is_ok());
  433. assert_eq!(lamports, 12);
  434. bank.store_account(&pubkey, &account);
  435. let instruction = Instruction::new_with_bytes(program_id, &[6], account_metas.clone());
  436. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  437. let lamports = bank_client.get_balance(&pubkey).unwrap();
  438. assert!(result.is_ok());
  439. assert_eq!(lamports, 13);
  440. let keypair = Keypair::new();
  441. let pubkey = keypair.pubkey();
  442. let account_metas = vec![
  443. AccountMeta::new(mint_keypair.pubkey(), true),
  444. AccountMeta::new(payee_pubkey, false),
  445. AccountMeta::new(pubkey, false),
  446. AccountMeta::new_readonly(pubkey, true),
  447. AccountMeta::new_readonly(program_id, false),
  448. ];
  449. bank.store_account(&pubkey, &account);
  450. let instruction = Instruction::new_with_bytes(program_id, &[7], account_metas.clone());
  451. let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
  452. let result = bank_client.send_and_confirm_message(&[&mint_keypair, &keypair], message);
  453. assert!(result.is_ok());
  454. }
  455. }
  456. #[test]
  457. #[cfg(feature = "sbf_rust")]
  458. fn test_program_sbf_error_handling() {
  459. agave_logger::setup();
  460. let mut programs = Vec::new();
  461. #[cfg(feature = "sbf_c")]
  462. {
  463. programs.extend_from_slice(&[("error_handling")]);
  464. }
  465. #[cfg(feature = "sbf_rust")]
  466. {
  467. programs.extend_from_slice(&[("solana_sbf_rust_error_handling")]);
  468. }
  469. for program in programs.iter() {
  470. println!("Test program: {:?}", program);
  471. let GenesisConfigInfo {
  472. genesis_config,
  473. mint_keypair,
  474. ..
  475. } = create_genesis_config(50);
  476. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  477. let mut bank_client = BankClient::new_shared(bank);
  478. let authority_keypair = Keypair::new();
  479. let (_bank, program_id) = load_program_of_loader_v4(
  480. &mut bank_client,
  481. &bank_forks,
  482. &mint_keypair,
  483. &authority_keypair,
  484. program,
  485. );
  486. let account_metas = vec![AccountMeta::new(mint_keypair.pubkey(), true)];
  487. let instruction = Instruction::new_with_bytes(program_id, &[1], account_metas.clone());
  488. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  489. assert!(result.is_ok());
  490. let instruction = Instruction::new_with_bytes(program_id, &[2], account_metas.clone());
  491. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  492. assert_eq!(
  493. result.unwrap_err().unwrap(),
  494. TransactionError::InstructionError(0, InstructionError::InvalidAccountData)
  495. );
  496. let instruction = Instruction::new_with_bytes(program_id, &[3], account_metas.clone());
  497. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  498. assert_eq!(
  499. result.unwrap_err().unwrap(),
  500. TransactionError::InstructionError(0, InstructionError::Custom(0))
  501. );
  502. let instruction = Instruction::new_with_bytes(program_id, &[4], account_metas.clone());
  503. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  504. assert_eq!(
  505. result.unwrap_err().unwrap(),
  506. TransactionError::InstructionError(0, InstructionError::Custom(42))
  507. );
  508. let instruction = Instruction::new_with_bytes(program_id, &[5], account_metas.clone());
  509. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  510. let result = result.unwrap_err().unwrap();
  511. if TransactionError::InstructionError(0, InstructionError::InvalidInstructionData) != result
  512. {
  513. assert_eq!(
  514. result,
  515. TransactionError::InstructionError(0, InstructionError::InvalidError)
  516. );
  517. }
  518. let instruction = Instruction::new_with_bytes(program_id, &[6], account_metas.clone());
  519. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  520. let result = result.unwrap_err().unwrap();
  521. if TransactionError::InstructionError(0, InstructionError::InvalidInstructionData) != result
  522. {
  523. assert_eq!(
  524. result,
  525. TransactionError::InstructionError(0, InstructionError::InvalidError)
  526. );
  527. }
  528. let instruction = Instruction::new_with_bytes(program_id, &[7], account_metas.clone());
  529. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  530. let result = result.unwrap_err().unwrap();
  531. if TransactionError::InstructionError(0, InstructionError::InvalidInstructionData) != result
  532. {
  533. assert_eq!(
  534. result,
  535. TransactionError::InstructionError(0, InstructionError::AccountBorrowFailed)
  536. );
  537. }
  538. let instruction = Instruction::new_with_bytes(program_id, &[8], account_metas.clone());
  539. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  540. assert_eq!(
  541. result.unwrap_err().unwrap(),
  542. TransactionError::InstructionError(0, InstructionError::InvalidInstructionData)
  543. );
  544. let instruction = Instruction::new_with_bytes(program_id, &[9], account_metas.clone());
  545. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  546. assert_eq!(
  547. result.unwrap_err().unwrap(),
  548. TransactionError::InstructionError(0, InstructionError::MaxSeedLengthExceeded)
  549. );
  550. }
  551. }
  552. #[test]
  553. #[cfg(any(feature = "sbf_c", feature = "sbf_rust"))]
  554. fn test_return_data_and_log_data_syscall() {
  555. agave_logger::setup();
  556. let mut programs = Vec::new();
  557. #[cfg(feature = "sbf_c")]
  558. {
  559. programs.extend_from_slice(&[("log_data")]);
  560. }
  561. #[cfg(feature = "sbf_rust")]
  562. {
  563. programs.extend_from_slice(&[("solana_sbf_rust_log_data")]);
  564. }
  565. for program in programs.iter() {
  566. let GenesisConfigInfo {
  567. genesis_config,
  568. mint_keypair,
  569. ..
  570. } = create_genesis_config(50);
  571. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  572. let mut bank_client = BankClient::new_shared(bank.clone());
  573. let authority_keypair = Keypair::new();
  574. let (bank, program_id) = load_program_of_loader_v4(
  575. &mut bank_client,
  576. &bank_forks,
  577. &mint_keypair,
  578. &authority_keypair,
  579. program,
  580. );
  581. bank.freeze();
  582. let account_metas = vec![AccountMeta::new(mint_keypair.pubkey(), true)];
  583. let instruction =
  584. Instruction::new_with_bytes(program_id, &[1, 2, 3, 0, 4, 5, 6], account_metas);
  585. let blockhash = bank.last_blockhash();
  586. let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
  587. let transaction = Transaction::new(&[&mint_keypair], message, blockhash);
  588. let sanitized_tx = RuntimeTransaction::from_transaction_for_tests(transaction);
  589. let result = bank.simulate_transaction(&sanitized_tx, false);
  590. assert!(result.result.is_ok());
  591. assert_eq!(result.logs[1], "Program data: AQID BAUG");
  592. assert_eq!(
  593. result.logs[3],
  594. format!("Program return: {} CAFE", program_id)
  595. );
  596. }
  597. }
  598. #[test]
  599. #[cfg(feature = "sbf_rust")]
  600. fn test_program_sbf_invoke_sanity() {
  601. agave_logger::setup();
  602. #[derive(Debug)]
  603. #[allow(dead_code)]
  604. enum Languages {
  605. C,
  606. Rust,
  607. }
  608. let mut programs = Vec::new();
  609. #[cfg(feature = "sbf_c")]
  610. {
  611. programs.push((Languages::C, "invoke", "invoked", "noop"));
  612. }
  613. #[cfg(feature = "sbf_rust")]
  614. {
  615. programs.push((
  616. Languages::Rust,
  617. "solana_sbf_rust_invoke",
  618. "solana_sbf_rust_invoked",
  619. "solana_sbf_rust_noop",
  620. ));
  621. }
  622. for program in programs.iter() {
  623. println!("Test program: {:?}", program);
  624. let GenesisConfigInfo {
  625. genesis_config,
  626. mint_keypair,
  627. ..
  628. } = create_genesis_config(50);
  629. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  630. let mut bank_client = BankClient::new_shared(bank.clone());
  631. let authority_keypair = Keypair::new();
  632. let (_bank, invoke_program_id) = load_program_of_loader_v4(
  633. &mut bank_client,
  634. &bank_forks,
  635. &mint_keypair,
  636. &authority_keypair,
  637. program.1,
  638. );
  639. let (_bank, invoked_program_id) = load_program_of_loader_v4(
  640. &mut bank_client,
  641. &bank_forks,
  642. &mint_keypair,
  643. &authority_keypair,
  644. program.2,
  645. );
  646. let (bank, noop_program_id) = load_program_of_loader_v4(
  647. &mut bank_client,
  648. &bank_forks,
  649. &mint_keypair,
  650. &authority_keypair,
  651. program.3,
  652. );
  653. let argument_keypair = Keypair::new();
  654. let account = AccountSharedData::new(42, 100, &invoke_program_id);
  655. bank.store_account(&argument_keypair.pubkey(), &account);
  656. let invoked_argument_keypair = Keypair::new();
  657. let account = AccountSharedData::new(20, 10, &invoked_program_id);
  658. bank.store_account(&invoked_argument_keypair.pubkey(), &account);
  659. let from_keypair = Keypair::new();
  660. let account = AccountSharedData::new(84, 0, &system_program::id());
  661. bank.store_account(&from_keypair.pubkey(), &account);
  662. let unexecutable_program_keypair = Keypair::new();
  663. let account = AccountSharedData::new(1, 0, &bpf_loader::id());
  664. bank.store_account(&unexecutable_program_keypair.pubkey(), &account);
  665. let noop_program_keypair = Keypair::new();
  666. let account = AccountSharedData::new(42, 5, &noop_program_id);
  667. bank.store_account(&noop_program_keypair.pubkey(), &account);
  668. let (derived_key1, bump_seed1) =
  669. Pubkey::find_program_address(&[b"You pass butter"], &invoke_program_id);
  670. let (derived_key2, bump_seed2) =
  671. Pubkey::find_program_address(&[b"Lil'", b"Bits"], &invoked_program_id);
  672. let (derived_key3, bump_seed3) =
  673. Pubkey::find_program_address(&[derived_key2.as_ref()], &invoked_program_id);
  674. let mint_pubkey = mint_keypair.pubkey();
  675. let account_metas = vec![
  676. AccountMeta::new(mint_pubkey, true),
  677. AccountMeta::new(argument_keypair.pubkey(), true),
  678. AccountMeta::new_readonly(invoked_program_id, false),
  679. AccountMeta::new(invoked_argument_keypair.pubkey(), true),
  680. AccountMeta::new_readonly(invoked_program_id, false),
  681. AccountMeta::new(argument_keypair.pubkey(), true),
  682. AccountMeta::new(derived_key1, false),
  683. AccountMeta::new(derived_key2, false),
  684. AccountMeta::new_readonly(derived_key3, false),
  685. AccountMeta::new_readonly(system_program::id(), false),
  686. AccountMeta::new(from_keypair.pubkey(), true),
  687. AccountMeta::new_readonly(solana_sdk_ids::ed25519_program::id(), false),
  688. AccountMeta::new_readonly(invoke_program_id, false),
  689. AccountMeta::new_readonly(unexecutable_program_keypair.pubkey(), false),
  690. AccountMeta::new_readonly(noop_program_id, false),
  691. ];
  692. let do_invoke = |test: u8, additional_instructions: &[Instruction], bank: &Bank| {
  693. let instruction_data = &[test, bump_seed1, bump_seed2, bump_seed3];
  694. let signers = vec![
  695. &mint_keypair,
  696. &argument_keypair,
  697. &invoked_argument_keypair,
  698. &from_keypair,
  699. ];
  700. let mut instructions = vec![Instruction::new_with_bytes(
  701. invoke_program_id,
  702. instruction_data,
  703. account_metas.clone(),
  704. )];
  705. instructions.extend_from_slice(additional_instructions);
  706. let message = Message::new(&instructions, Some(&mint_pubkey));
  707. let tx = Transaction::new(&signers, message.clone(), bank.last_blockhash());
  708. let (result, inner_instructions, log_messages, executed_units) =
  709. process_transaction_and_record_inner(bank, tx);
  710. let invoked_programs: Vec<Pubkey> = inner_instructions
  711. .first()
  712. .map(|instructions| {
  713. instructions
  714. .iter()
  715. .filter_map(|ix| {
  716. message
  717. .account_keys
  718. .get(ix.instruction.program_id_index as usize)
  719. })
  720. .cloned()
  721. .collect()
  722. })
  723. .unwrap_or_default();
  724. let no_invoked_programs: Vec<Pubkey> = inner_instructions
  725. .get(1)
  726. .map(|instructions| {
  727. instructions
  728. .iter()
  729. .filter_map(|ix| {
  730. message
  731. .account_keys
  732. .get(ix.instruction.program_id_index as usize)
  733. })
  734. .cloned()
  735. .collect()
  736. })
  737. .unwrap_or_default();
  738. (
  739. result,
  740. log_messages,
  741. executed_units,
  742. invoked_programs,
  743. no_invoked_programs,
  744. )
  745. };
  746. // success cases
  747. let do_invoke_success = |test: u8,
  748. additional_instructions: &[Instruction],
  749. expected_invoked_programs: &[Pubkey],
  750. bank: &Bank| {
  751. println!("Running success test #{:?}", test);
  752. let (result, _log_messages, _executed_units, invoked_programs, no_invoked_programs) =
  753. do_invoke(test, additional_instructions, bank);
  754. assert_eq!(result, Ok(()));
  755. assert_eq!(invoked_programs.len(), expected_invoked_programs.len());
  756. assert_eq!(invoked_programs, expected_invoked_programs);
  757. assert_eq!(no_invoked_programs.len(), 0);
  758. };
  759. do_invoke_success(
  760. TEST_SUCCESS,
  761. &[Instruction::new_with_bytes(noop_program_id, &[], vec![])],
  762. match program.0 {
  763. Languages::C => vec![
  764. system_program::id(),
  765. system_program::id(),
  766. invoked_program_id.clone(),
  767. invoked_program_id.clone(),
  768. invoked_program_id.clone(),
  769. invoked_program_id.clone(),
  770. invoked_program_id.clone(),
  771. invoked_program_id.clone(),
  772. invoked_program_id.clone(),
  773. invoked_program_id.clone(),
  774. invoked_program_id.clone(),
  775. invoked_program_id.clone(),
  776. invoked_program_id.clone(),
  777. invoked_program_id.clone(),
  778. invoked_program_id.clone(),
  779. invoked_program_id.clone(),
  780. invoked_program_id.clone(),
  781. invoked_program_id.clone(),
  782. invoked_program_id.clone(),
  783. ],
  784. Languages::Rust => vec![
  785. system_program::id(),
  786. system_program::id(),
  787. invoked_program_id.clone(),
  788. invoked_program_id.clone(),
  789. invoked_program_id.clone(),
  790. invoked_program_id.clone(),
  791. invoked_program_id.clone(),
  792. invoked_program_id.clone(),
  793. invoked_program_id.clone(),
  794. invoked_program_id.clone(),
  795. invoked_program_id.clone(),
  796. invoked_program_id.clone(),
  797. invoked_program_id.clone(),
  798. invoked_program_id.clone(),
  799. invoked_program_id.clone(),
  800. invoked_program_id.clone(),
  801. invoked_program_id.clone(),
  802. invoked_program_id.clone(),
  803. invoked_program_id.clone(),
  804. invoked_program_id.clone(),
  805. invoked_program_id.clone(),
  806. system_program::id(),
  807. invoked_program_id.clone(),
  808. invoked_program_id.clone(),
  809. ],
  810. }
  811. .as_ref(),
  812. &bank,
  813. );
  814. // With SIMD-0268 enabled, eight nested invokes should pass.
  815. let bank = bank_with_feature_activated(
  816. &bank_forks,
  817. bank,
  818. &feature_set::raise_cpi_nesting_limit_to_8::id(),
  819. );
  820. assert!(bank
  821. .feature_set
  822. .is_active(&feature_set::raise_cpi_nesting_limit_to_8::id()));
  823. {
  824. // Reset the account balances for `ARGUMENT` and `INVOKED_ARGUMENT`
  825. let account = AccountSharedData::new(42, 100, &invoke_program_id);
  826. bank.store_account(&argument_keypair.pubkey(), &account);
  827. let account = AccountSharedData::new(20, 10, &invoked_program_id);
  828. bank.store_account(&invoked_argument_keypair.pubkey(), &account);
  829. }
  830. do_invoke_success(
  831. TEST_NESTED_INVOKE_SIMD_0268_OK,
  832. &[],
  833. &[invoked_program_id.clone(); 16], // 16, 8 for each invoke
  834. &bank,
  835. );
  836. do_invoke_success(
  837. TEST_MAX_ACCOUNT_INFOS_OK,
  838. &[],
  839. std::slice::from_ref(&invoked_program_id),
  840. &bank,
  841. );
  842. do_invoke_success(
  843. TEST_CU_USAGE_MINIMUM,
  844. &[],
  845. std::slice::from_ref(&noop_program_id),
  846. &bank,
  847. );
  848. do_invoke_success(
  849. TEST_CU_USAGE_BASELINE,
  850. &[],
  851. std::slice::from_ref(&noop_program_id),
  852. &bank,
  853. );
  854. do_invoke_success(
  855. TEST_CU_USAGE_MAX,
  856. &[],
  857. std::slice::from_ref(&noop_program_id),
  858. &bank,
  859. );
  860. let bank = bank_with_feature_deactivated(
  861. &bank_forks,
  862. bank,
  863. &feature_set::increase_cpi_account_info_limit::id(),
  864. );
  865. assert!(!bank
  866. .feature_set
  867. .is_active(&feature_set::increase_cpi_account_info_limit::id()));
  868. do_invoke_success(
  869. TEST_MAX_ACCOUNT_INFOS_OK_BEFORE_SIMD_0339,
  870. &[],
  871. std::slice::from_ref(&invoked_program_id),
  872. &bank,
  873. );
  874. let bank = bank_with_feature_deactivated(
  875. &bank_forks,
  876. bank,
  877. &feature_set::increase_tx_account_lock_limit::id(),
  878. );
  879. assert!(!bank
  880. .feature_set
  881. .is_active(&feature_set::increase_tx_account_lock_limit::id()));
  882. do_invoke_success(
  883. TEST_MAX_ACCOUNT_INFOS_OK_BEFORE_INCREASE_TX_ACCOUNT_LOCK_BEFORE_SIMD_0339,
  884. &[],
  885. std::slice::from_ref(&invoked_program_id),
  886. &bank,
  887. );
  888. let bank = bank_with_feature_activated(
  889. &bank_forks,
  890. bank,
  891. &feature_set::increase_tx_account_lock_limit::id(),
  892. );
  893. assert!(bank
  894. .feature_set
  895. .is_active(&feature_set::increase_tx_account_lock_limit::id()));
  896. let bank = bank_with_feature_activated(
  897. &bank_forks,
  898. bank,
  899. &feature_set::increase_cpi_account_info_limit::id(),
  900. );
  901. assert!(bank
  902. .feature_set
  903. .is_active(&feature_set::increase_cpi_account_info_limit::id()));
  904. // failure cases
  905. let do_invoke_failure_test_local_with_compute_check =
  906. |test: u8,
  907. expected_error: TransactionError,
  908. expected_invoked_programs: &[Pubkey],
  909. expected_log_messages: Option<Vec<String>>,
  910. should_deplete_compute_meter: bool,
  911. bank: &Bank| {
  912. println!("Running failure test #{:?}", test);
  913. let compute_unit_limit = 1_000_000;
  914. let (result, log_messages, executed_units, invoked_programs, _) = do_invoke(
  915. test,
  916. &[ComputeBudgetInstruction::set_compute_unit_limit(
  917. compute_unit_limit,
  918. )],
  919. bank,
  920. );
  921. assert_eq!(result, Err(expected_error));
  922. assert_eq!(invoked_programs, expected_invoked_programs);
  923. if should_deplete_compute_meter {
  924. assert_eq!(executed_units, compute_unit_limit as u64);
  925. } else {
  926. assert!(executed_units < compute_unit_limit as u64);
  927. }
  928. if let Some(expected_log_messages) = expected_log_messages {
  929. assert_eq!(log_messages.len(), expected_log_messages.len());
  930. expected_log_messages
  931. .into_iter()
  932. .zip(log_messages)
  933. .for_each(|(expected_log_message, log_message)| {
  934. if expected_log_message != String::from("skip") {
  935. assert_eq!(log_message, expected_log_message);
  936. }
  937. });
  938. }
  939. };
  940. let do_invoke_failure_test_local =
  941. |test: u8,
  942. expected_error: TransactionError,
  943. expected_invoked_programs: &[Pubkey],
  944. expected_log_messages: Option<Vec<String>>,
  945. bank: &Bank| {
  946. do_invoke_failure_test_local_with_compute_check(
  947. test,
  948. expected_error,
  949. expected_invoked_programs,
  950. expected_log_messages,
  951. false, // should_deplete_compute_meter
  952. bank,
  953. )
  954. };
  955. let program_lang = match program.0 {
  956. Languages::Rust => "Rust",
  957. Languages::C => "C",
  958. };
  959. do_invoke_failure_test_local(
  960. TEST_PRIVILEGE_ESCALATION_SIGNER,
  961. TransactionError::InstructionError(0, InstructionError::PrivilegeEscalation),
  962. std::slice::from_ref(&invoked_program_id),
  963. None,
  964. &bank,
  965. );
  966. do_invoke_failure_test_local(
  967. TEST_PRIVILEGE_ESCALATION_WRITABLE,
  968. TransactionError::InstructionError(0, InstructionError::PrivilegeEscalation),
  969. std::slice::from_ref(&invoked_program_id),
  970. None,
  971. &bank,
  972. );
  973. do_invoke_failure_test_local(
  974. TEST_PPROGRAM_NOT_OWNED_BY_LOADER,
  975. TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId),
  976. &[argument_keypair.pubkey()],
  977. None,
  978. &bank,
  979. );
  980. do_invoke_failure_test_local(
  981. TEST_PPROGRAM_NOT_EXECUTABLE,
  982. TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId),
  983. &[unexecutable_program_keypair.pubkey()],
  984. None,
  985. &bank,
  986. );
  987. do_invoke_failure_test_local(
  988. TEST_EMPTY_ACCOUNTS_SLICE,
  989. TransactionError::InstructionError(0, InstructionError::MissingAccount),
  990. &[],
  991. None,
  992. &bank,
  993. );
  994. do_invoke_failure_test_local(
  995. TEST_CAP_SEEDS,
  996. TransactionError::InstructionError(0, InstructionError::MaxSeedLengthExceeded),
  997. &[],
  998. None,
  999. &bank,
  1000. );
  1001. do_invoke_failure_test_local(
  1002. TEST_CAP_SIGNERS,
  1003. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete),
  1004. &[],
  1005. None,
  1006. &bank,
  1007. );
  1008. do_invoke_failure_test_local(
  1009. TEST_MAX_INSTRUCTION_DATA_LEN_EXCEEDED,
  1010. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete),
  1011. &[],
  1012. Some(vec![
  1013. format!("Program {invoke_program_id} invoke [1]"),
  1014. format!("Program log: invoke {program_lang} program"),
  1015. "Program log: Test max instruction data len exceeded".into(),
  1016. "skip".into(), // don't compare compute consumption logs
  1017. format!(
  1018. "Program {invoke_program_id} failed: Invoked an instruction with data that is \
  1019. too large (10241 > 10240)"
  1020. ),
  1021. ]),
  1022. &bank,
  1023. );
  1024. do_invoke_failure_test_local(
  1025. TEST_MAX_INSTRUCTION_ACCOUNTS_EXCEEDED,
  1026. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete),
  1027. &[],
  1028. Some(vec![
  1029. format!("Program {invoke_program_id} invoke [1]"),
  1030. format!("Program log: invoke {program_lang} program"),
  1031. "Program log: Test max instruction accounts exceeded".into(),
  1032. "skip".into(), // don't compare compute consumption logs
  1033. format!(
  1034. "Program {invoke_program_id} failed: Invoked an instruction with too many \
  1035. accounts (256 > 255)"
  1036. ),
  1037. ]),
  1038. &bank,
  1039. );
  1040. do_invoke_failure_test_local(
  1041. TEST_MAX_ACCOUNT_INFOS_EXCEEDED,
  1042. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete),
  1043. &[],
  1044. Some(vec![
  1045. format!("Program {invoke_program_id} invoke [1]"),
  1046. format!("Program log: invoke {program_lang} program"),
  1047. "Program log: Test max account infos exceeded".into(),
  1048. "skip".into(), // don't compare compute consumption logs
  1049. format!(
  1050. "Program {invoke_program_id} failed: Invoked an instruction with too many \
  1051. account info's (256 > 255)"
  1052. ),
  1053. ]),
  1054. &bank,
  1055. );
  1056. let bank = bank_with_feature_deactivated(
  1057. &bank_forks,
  1058. bank,
  1059. &feature_set::increase_cpi_account_info_limit::id(),
  1060. );
  1061. assert!(!bank
  1062. .feature_set
  1063. .is_active(&feature_set::increase_cpi_account_info_limit::id()));
  1064. do_invoke_failure_test_local(
  1065. TEST_MAX_ACCOUNT_INFOS_EXCEEDED_BEFORE_SIMD_0339,
  1066. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete),
  1067. &[],
  1068. Some(vec![
  1069. format!("Program {invoke_program_id} invoke [1]"),
  1070. format!("Program log: invoke {program_lang} program"),
  1071. "Program log: Test max account infos exceeded before SIMD-0339".into(),
  1072. "skip".into(), // don't compare compute consumption logs
  1073. format!(
  1074. "Program {invoke_program_id} failed: Invoked an instruction with too many \
  1075. account info's (129 > 128)"
  1076. ),
  1077. ]),
  1078. &bank,
  1079. );
  1080. let bank = bank_with_feature_deactivated(
  1081. &bank_forks,
  1082. bank,
  1083. &feature_set::increase_tx_account_lock_limit::id(),
  1084. );
  1085. assert!(!bank
  1086. .feature_set
  1087. .is_active(&feature_set::increase_tx_account_lock_limit::id()));
  1088. do_invoke_failure_test_local(
  1089. TEST_MAX_ACCOUNT_INFOS_EXCEEDED_BEFORE_INCREASE_TX_ACCOUNT_LOCK_BEFORE_SIMD_0339,
  1090. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete),
  1091. &[],
  1092. Some(vec![
  1093. format!("Program {invoke_program_id} invoke [1]"),
  1094. format!("Program log: invoke {program_lang} program"),
  1095. "Program log: Test max account infos exceeded before SIMD-0339 and before \
  1096. increase cpi info"
  1097. .into(),
  1098. "skip".into(), // don't compare compute consumption logs
  1099. format!(
  1100. "Program {invoke_program_id} failed: Invoked an instruction with too many \
  1101. account info's (65 > 64)"
  1102. ),
  1103. ]),
  1104. &bank,
  1105. );
  1106. do_invoke_failure_test_local(
  1107. TEST_RETURN_ERROR,
  1108. TransactionError::InstructionError(0, InstructionError::Custom(42)),
  1109. std::slice::from_ref(&invoked_program_id),
  1110. None,
  1111. &bank,
  1112. );
  1113. do_invoke_failure_test_local(
  1114. TEST_PRIVILEGE_DEESCALATION_ESCALATION_SIGNER,
  1115. TransactionError::InstructionError(0, InstructionError::PrivilegeEscalation),
  1116. std::slice::from_ref(&invoked_program_id),
  1117. None,
  1118. &bank,
  1119. );
  1120. do_invoke_failure_test_local(
  1121. TEST_PRIVILEGE_DEESCALATION_ESCALATION_WRITABLE,
  1122. TransactionError::InstructionError(0, InstructionError::PrivilegeEscalation),
  1123. std::slice::from_ref(&invoked_program_id),
  1124. None,
  1125. &bank,
  1126. );
  1127. do_invoke_failure_test_local_with_compute_check(
  1128. TEST_WRITABLE_DEESCALATION_WRITABLE,
  1129. TransactionError::InstructionError(0, InstructionError::ReadonlyDataModified),
  1130. std::slice::from_ref(&invoked_program_id),
  1131. None,
  1132. true, // should_deplete_compute_meter
  1133. &bank,
  1134. );
  1135. // With SIMD-0268 disabled, five nested invokes is too deep.
  1136. let bank = bank_with_feature_deactivated(
  1137. &bank_forks,
  1138. bank,
  1139. &feature_set::raise_cpi_nesting_limit_to_8::id(),
  1140. );
  1141. assert!(!bank
  1142. .feature_set
  1143. .is_active(&feature_set::raise_cpi_nesting_limit_to_8::id()));
  1144. do_invoke_failure_test_local(
  1145. TEST_NESTED_INVOKE_TOO_DEEP,
  1146. TransactionError::InstructionError(0, InstructionError::CallDepth),
  1147. &[
  1148. invoked_program_id.clone(),
  1149. invoked_program_id.clone(),
  1150. invoked_program_id.clone(),
  1151. invoked_program_id.clone(),
  1152. invoked_program_id.clone(),
  1153. ],
  1154. None,
  1155. &bank,
  1156. );
  1157. // With SIMD-0268 enabled, nine nested invokes is too deep.
  1158. let bank = bank_with_feature_activated(
  1159. &bank_forks,
  1160. bank,
  1161. &feature_set::raise_cpi_nesting_limit_to_8::id(),
  1162. );
  1163. assert!(bank
  1164. .feature_set
  1165. .is_active(&feature_set::raise_cpi_nesting_limit_to_8::id()));
  1166. do_invoke_failure_test_local(
  1167. TEST_NESTED_INVOKE_SIMD_0268_TOO_DEEP,
  1168. TransactionError::InstructionError(0, InstructionError::CallDepth),
  1169. &[
  1170. invoked_program_id.clone(),
  1171. invoked_program_id.clone(),
  1172. invoked_program_id.clone(),
  1173. invoked_program_id.clone(),
  1174. invoked_program_id.clone(),
  1175. invoked_program_id.clone(),
  1176. invoked_program_id.clone(),
  1177. invoked_program_id.clone(),
  1178. invoked_program_id.clone(),
  1179. ],
  1180. None,
  1181. &bank,
  1182. );
  1183. do_invoke_failure_test_local(
  1184. TEST_RETURN_DATA_TOO_LARGE,
  1185. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete),
  1186. &[],
  1187. None,
  1188. &bank,
  1189. );
  1190. do_invoke_failure_test_local(
  1191. TEST_DUPLICATE_PRIVILEGE_ESCALATION_SIGNER,
  1192. TransactionError::InstructionError(0, InstructionError::PrivilegeEscalation),
  1193. std::slice::from_ref(&invoked_program_id),
  1194. None,
  1195. &bank,
  1196. );
  1197. do_invoke_failure_test_local(
  1198. TEST_DUPLICATE_PRIVILEGE_ESCALATION_WRITABLE,
  1199. TransactionError::InstructionError(0, InstructionError::PrivilegeEscalation),
  1200. std::slice::from_ref(&invoked_program_id),
  1201. None,
  1202. &bank,
  1203. );
  1204. // Check resulting state
  1205. assert_eq!(43, bank.get_balance(&derived_key1));
  1206. let account = bank.get_account(&derived_key1).unwrap();
  1207. assert_eq!(&invoke_program_id, account.owner());
  1208. assert_eq!(
  1209. MAX_PERMITTED_DATA_INCREASE,
  1210. bank.get_account(&derived_key1).unwrap().data().len()
  1211. );
  1212. for i in 0..20 {
  1213. assert_eq!(i as u8, account.data()[i]);
  1214. }
  1215. // Attempt to realloc into unauthorized address space
  1216. let account = AccountSharedData::new(84, 0, &system_program::id());
  1217. bank.store_account(&from_keypair.pubkey(), &account);
  1218. bank.store_account(&derived_key1, &AccountSharedData::default());
  1219. let instruction = Instruction::new_with_bytes(
  1220. invoke_program_id,
  1221. &[
  1222. TEST_ALLOC_ACCESS_VIOLATION,
  1223. bump_seed1,
  1224. bump_seed2,
  1225. bump_seed3,
  1226. ],
  1227. account_metas.clone(),
  1228. );
  1229. let message = Message::new(&[instruction], Some(&mint_pubkey));
  1230. let tx = Transaction::new(
  1231. &[
  1232. &mint_keypair,
  1233. &argument_keypair,
  1234. &invoked_argument_keypair,
  1235. &from_keypair,
  1236. ],
  1237. message.clone(),
  1238. bank.last_blockhash(),
  1239. );
  1240. let (result, inner_instructions, _log_messages, _executed_units) =
  1241. process_transaction_and_record_inner(&bank, tx);
  1242. let invoked_programs: Vec<Pubkey> = inner_instructions[0]
  1243. .iter()
  1244. .map(|ix| &message.account_keys[ix.instruction.program_id_index as usize])
  1245. .cloned()
  1246. .collect();
  1247. assert_eq!(invoked_programs, vec![]);
  1248. assert_eq!(
  1249. result.unwrap_err(),
  1250. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete)
  1251. );
  1252. }
  1253. }
  1254. #[test]
  1255. #[cfg(feature = "sbf_rust")]
  1256. fn test_program_sbf_program_id_spoofing() {
  1257. let GenesisConfigInfo {
  1258. genesis_config,
  1259. mint_keypair,
  1260. ..
  1261. } = create_genesis_config(50);
  1262. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  1263. let mut bank_client = BankClient::new_shared(bank.clone());
  1264. let authority_keypair = Keypair::new();
  1265. let (_bank, malicious_swap_pubkey) = load_program_of_loader_v4(
  1266. &mut bank_client,
  1267. &bank_forks,
  1268. &mint_keypair,
  1269. &authority_keypair,
  1270. "solana_sbf_rust_spoof1",
  1271. );
  1272. let (bank, malicious_system_pubkey) = load_program_of_loader_v4(
  1273. &mut bank_client,
  1274. &bank_forks,
  1275. &mint_keypair,
  1276. &authority_keypair,
  1277. "solana_sbf_rust_spoof1_system",
  1278. );
  1279. let from_pubkey = Pubkey::new_unique();
  1280. let account = AccountSharedData::new(10, 0, &system_program::id());
  1281. bank.store_account(&from_pubkey, &account);
  1282. let to_pubkey = Pubkey::new_unique();
  1283. let account = AccountSharedData::new(0, 0, &system_program::id());
  1284. bank.store_account(&to_pubkey, &account);
  1285. let account_metas = vec![
  1286. AccountMeta::new_readonly(system_program::id(), false),
  1287. AccountMeta::new_readonly(malicious_system_pubkey, false),
  1288. AccountMeta::new(from_pubkey, false),
  1289. AccountMeta::new(to_pubkey, false),
  1290. ];
  1291. let instruction =
  1292. Instruction::new_with_bytes(malicious_swap_pubkey, &[], account_metas.clone());
  1293. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  1294. assert_eq!(
  1295. result.unwrap_err().unwrap(),
  1296. TransactionError::InstructionError(0, InstructionError::MissingRequiredSignature)
  1297. );
  1298. assert_eq!(10, bank.get_balance(&from_pubkey));
  1299. assert_eq!(0, bank.get_balance(&to_pubkey));
  1300. }
  1301. #[test]
  1302. #[cfg(feature = "sbf_rust")]
  1303. fn test_program_sbf_caller_has_access_to_cpi_program() {
  1304. let GenesisConfigInfo {
  1305. genesis_config,
  1306. mint_keypair,
  1307. ..
  1308. } = create_genesis_config(50);
  1309. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  1310. let mut bank_client = BankClient::new_shared(bank.clone());
  1311. let authority_keypair = Keypair::new();
  1312. let (_bank, caller_pubkey) = load_program_of_loader_v4(
  1313. &mut bank_client,
  1314. &bank_forks,
  1315. &mint_keypair,
  1316. &authority_keypair,
  1317. "solana_sbf_rust_caller_access",
  1318. );
  1319. let (_bank, caller2_pubkey) = load_program_of_loader_v4(
  1320. &mut bank_client,
  1321. &bank_forks,
  1322. &mint_keypair,
  1323. &authority_keypair,
  1324. "solana_sbf_rust_caller_access",
  1325. );
  1326. let account_metas = vec![
  1327. AccountMeta::new_readonly(caller_pubkey, false),
  1328. AccountMeta::new_readonly(caller2_pubkey, false),
  1329. ];
  1330. let instruction = Instruction::new_with_bytes(caller_pubkey, &[1], account_metas.clone());
  1331. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  1332. assert_eq!(
  1333. result.unwrap_err().unwrap(),
  1334. TransactionError::InstructionError(0, InstructionError::MissingAccount),
  1335. );
  1336. }
  1337. #[test]
  1338. #[cfg(feature = "sbf_rust")]
  1339. fn test_program_sbf_ro_modify() {
  1340. agave_logger::setup();
  1341. let GenesisConfigInfo {
  1342. genesis_config,
  1343. mint_keypair,
  1344. ..
  1345. } = create_genesis_config(50);
  1346. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  1347. let mut bank_client = BankClient::new_shared(bank.clone());
  1348. let authority_keypair = Keypair::new();
  1349. let (bank, program_pubkey) = load_program_of_loader_v4(
  1350. &mut bank_client,
  1351. &bank_forks,
  1352. &mint_keypair,
  1353. &authority_keypair,
  1354. "solana_sbf_rust_ro_modify",
  1355. );
  1356. let test_keypair = Keypair::new();
  1357. let account = AccountSharedData::new(10, 0, &system_program::id());
  1358. bank.store_account(&test_keypair.pubkey(), &account);
  1359. let account_metas = vec![
  1360. AccountMeta::new_readonly(system_program::id(), false),
  1361. AccountMeta::new(test_keypair.pubkey(), true),
  1362. ];
  1363. let instruction = Instruction::new_with_bytes(program_pubkey, &[1], account_metas.clone());
  1364. let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
  1365. let result = bank_client.send_and_confirm_message(&[&mint_keypair, &test_keypair], message);
  1366. assert_eq!(
  1367. result.unwrap_err().unwrap(),
  1368. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete)
  1369. );
  1370. let instruction = Instruction::new_with_bytes(program_pubkey, &[3], account_metas.clone());
  1371. let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
  1372. let result = bank_client.send_and_confirm_message(&[&mint_keypair, &test_keypair], message);
  1373. assert_eq!(
  1374. result.unwrap_err().unwrap(),
  1375. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete)
  1376. );
  1377. let instruction = Instruction::new_with_bytes(program_pubkey, &[4], account_metas.clone());
  1378. let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
  1379. let result = bank_client.send_and_confirm_message(&[&mint_keypair, &test_keypair], message);
  1380. assert_eq!(
  1381. result.unwrap_err().unwrap(),
  1382. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete)
  1383. );
  1384. }
  1385. #[test]
  1386. #[cfg(feature = "sbf_rust")]
  1387. fn test_program_sbf_call_depth() {
  1388. agave_logger::setup();
  1389. let GenesisConfigInfo {
  1390. genesis_config,
  1391. mint_keypair,
  1392. ..
  1393. } = create_genesis_config(50);
  1394. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  1395. let mut bank_client = BankClient::new_shared(bank);
  1396. let authority_keypair = Keypair::new();
  1397. let (_bank, program_id) = load_program_of_loader_v4(
  1398. &mut bank_client,
  1399. &bank_forks,
  1400. &mint_keypair,
  1401. &authority_keypair,
  1402. "solana_sbf_rust_call_depth",
  1403. );
  1404. let budget = ComputeBudget::new_with_defaults(
  1405. genesis_config
  1406. .accounts
  1407. .contains_key(&feature_set::raise_cpi_nesting_limit_to_8::id()),
  1408. genesis_config
  1409. .accounts
  1410. .contains_key(&feature_set::increase_cpi_account_info_limit::id()),
  1411. );
  1412. let instruction =
  1413. Instruction::new_with_bincode(program_id, &(budget.max_call_depth - 1), vec![]);
  1414. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  1415. assert!(result.is_ok());
  1416. let instruction = Instruction::new_with_bincode(program_id, &budget.max_call_depth, vec![]);
  1417. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  1418. assert!(result.is_err());
  1419. }
  1420. #[test]
  1421. #[cfg(feature = "sbf_rust")]
  1422. fn test_program_sbf_compute_budget() {
  1423. agave_logger::setup();
  1424. let GenesisConfigInfo {
  1425. genesis_config,
  1426. mint_keypair,
  1427. ..
  1428. } = create_genesis_config(50);
  1429. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  1430. let mut bank_client = BankClient::new_shared(bank);
  1431. let authority_keypair = Keypair::new();
  1432. let (_bank, program_id) = load_program_of_loader_v4(
  1433. &mut bank_client,
  1434. &bank_forks,
  1435. &mint_keypair,
  1436. &authority_keypair,
  1437. "solana_sbf_rust_noop",
  1438. );
  1439. let message = Message::new(
  1440. &[
  1441. ComputeBudgetInstruction::set_compute_unit_limit(150),
  1442. Instruction::new_with_bincode(program_id, &0, vec![]),
  1443. ],
  1444. Some(&mint_keypair.pubkey()),
  1445. );
  1446. let result = bank_client.send_and_confirm_message(&[&mint_keypair], message);
  1447. assert_eq!(
  1448. result.unwrap_err().unwrap(),
  1449. TransactionError::InstructionError(1, InstructionError::ProgramFailedToComplete),
  1450. );
  1451. }
  1452. #[test]
  1453. fn assert_instruction_count() {
  1454. agave_logger::setup();
  1455. let mut programs = Vec::new();
  1456. #[cfg(feature = "sbf_c")]
  1457. {
  1458. programs.extend_from_slice(&[
  1459. ("alloc", 18572),
  1460. ("sbf_to_sbf", 316),
  1461. ("multiple_static", 210),
  1462. ("noop", 5),
  1463. ("noop++", 5),
  1464. ("relative_call", 212),
  1465. ("return_data", 1026),
  1466. ("sanity", 2371),
  1467. ("sanity++", 2271),
  1468. ("secp256k1_recover", 25421),
  1469. ("sha", 1446),
  1470. ("struct_pass", 108),
  1471. ("struct_ret", 122),
  1472. ]);
  1473. }
  1474. #[cfg(feature = "sbf_rust")]
  1475. {
  1476. programs.extend_from_slice(&[
  1477. ("solana_sbf_rust_128bit", 784),
  1478. ("solana_sbf_rust_alloc", 4934),
  1479. ("solana_sbf_rust_custom_heap", 343),
  1480. ("solana_sbf_rust_dep_crate", 22),
  1481. ("solana_sbf_rust_iter", 1514),
  1482. ("solana_sbf_rust_many_args", 1287),
  1483. ("solana_sbf_rust_mem", 1326),
  1484. ("solana_sbf_rust_membuiltins", 329),
  1485. ("solana_sbf_rust_noop", 342),
  1486. ("solana_sbf_rust_param_passing", 108),
  1487. ("solana_sbf_rust_rand", 315),
  1488. ("solana_sbf_rust_sanity", 14223),
  1489. ("solana_sbf_rust_secp256k1_recover", 88615),
  1490. ("solana_sbf_rust_sha", 21998),
  1491. ]);
  1492. }
  1493. println!("\n {:36} expected actual diff", "SBF program");
  1494. for (program_name, expected_consumption) in programs.iter() {
  1495. let loader_id = bpf_loader::id();
  1496. let program_key = Pubkey::new_unique();
  1497. let mut transaction_accounts = vec![
  1498. (program_key, AccountSharedData::new(0, 0, &loader_id)),
  1499. (
  1500. Pubkey::new_unique(),
  1501. AccountSharedData::new(0, 0, &program_key),
  1502. ),
  1503. ];
  1504. let instruction_accounts = vec![AccountMeta {
  1505. pubkey: transaction_accounts[1].0,
  1506. is_signer: false,
  1507. is_writable: false,
  1508. }];
  1509. transaction_accounts[0]
  1510. .1
  1511. .set_data_from_slice(&load_program_from_file(program_name));
  1512. transaction_accounts[0].1.set_executable(true);
  1513. let prev_compute_meter = RefCell::new(0);
  1514. print!(" {:36} {:8}", program_name, *expected_consumption);
  1515. mock_process_instruction(
  1516. &loader_id,
  1517. Some(0),
  1518. &[],
  1519. transaction_accounts,
  1520. instruction_accounts,
  1521. Ok(()),
  1522. solana_bpf_loader_program::Entrypoint::vm,
  1523. |invoke_context| {
  1524. *prev_compute_meter.borrow_mut() = invoke_context.get_remaining();
  1525. solana_bpf_loader_program::test_utils::load_all_invoked_programs(invoke_context);
  1526. },
  1527. |invoke_context| {
  1528. let consumption = prev_compute_meter
  1529. .borrow()
  1530. .saturating_sub(invoke_context.get_remaining());
  1531. let diff: i64 = consumption as i64 - *expected_consumption as i64;
  1532. println!(
  1533. "{:6} {:+5} ({:+3.0}%)",
  1534. consumption,
  1535. diff,
  1536. 100.0_f64 * consumption as f64 / *expected_consumption as f64 - 100.0_f64,
  1537. );
  1538. assert!(consumption <= *expected_consumption);
  1539. },
  1540. );
  1541. }
  1542. }
  1543. #[test]
  1544. #[cfg(feature = "sbf_rust")]
  1545. fn test_program_sbf_instruction_introspection() {
  1546. agave_logger::setup();
  1547. let GenesisConfigInfo {
  1548. genesis_config,
  1549. mint_keypair,
  1550. ..
  1551. } = create_genesis_config(50_000);
  1552. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  1553. let mut bank_client = BankClient::new_shared(bank.clone());
  1554. let authority_keypair = Keypair::new();
  1555. let (_bank, program_id) = load_program_of_loader_v4(
  1556. &mut bank_client,
  1557. &bank_forks,
  1558. &mint_keypair,
  1559. &authority_keypair,
  1560. "solana_sbf_rust_instruction_introspection",
  1561. );
  1562. // Passing transaction
  1563. let account_metas = vec![
  1564. AccountMeta::new_readonly(program_id, false),
  1565. AccountMeta::new_readonly(sysvar::instructions::id(), false),
  1566. ];
  1567. let instruction0 = Instruction::new_with_bytes(program_id, &[0u8, 0u8], account_metas.clone());
  1568. let instruction1 = Instruction::new_with_bytes(program_id, &[0u8, 1u8], account_metas.clone());
  1569. let instruction2 = Instruction::new_with_bytes(program_id, &[0u8, 2u8], account_metas);
  1570. let message = Message::new(
  1571. &[instruction0, instruction1, instruction2],
  1572. Some(&mint_keypair.pubkey()),
  1573. );
  1574. let result = bank_client.send_and_confirm_message(&[&mint_keypair], message);
  1575. assert!(result.is_ok());
  1576. // writable special instructions11111 key, should not be allowed
  1577. let account_metas = vec![AccountMeta::new(sysvar::instructions::id(), false)];
  1578. let instruction = Instruction::new_with_bytes(program_id, &[0], account_metas);
  1579. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  1580. assert_eq!(
  1581. result.unwrap_err().unwrap(),
  1582. // sysvar write locks are demoted to read only. So this will no longer
  1583. // cause InvalidAccountIndex error.
  1584. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete),
  1585. );
  1586. // No accounts, should error
  1587. let instruction = Instruction::new_with_bytes(program_id, &[0], vec![]);
  1588. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  1589. #[allow(deprecated)]
  1590. let expected_error =
  1591. TransactionError::InstructionError(0, InstructionError::NotEnoughAccountKeys);
  1592. assert!(result.is_err());
  1593. assert_eq!(result.unwrap_err().unwrap(), expected_error,);
  1594. assert!(bank.get_account(&sysvar::instructions::id()).is_none());
  1595. }
  1596. #[test_matrix(
  1597. [0, 1, 2, 5, 10, 15, 20],
  1598. [1, 10, 50, 100, 255, 500, 1000, 1024] // MAX_RETURN_DATA = 1024
  1599. )]
  1600. #[allow(clippy::arithmetic_side_effects)]
  1601. #[cfg(feature = "sbf_rust")]
  1602. fn test_program_sbf_r2_instruction_data_pointer(num_accounts: usize, input_data_len: usize) {
  1603. agave_logger::setup();
  1604. let GenesisConfigInfo {
  1605. genesis_config,
  1606. mint_keypair,
  1607. ..
  1608. } = create_genesis_config(50);
  1609. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  1610. let mut bank_client = BankClient::new_shared(bank.clone());
  1611. let authority_keypair = Keypair::new();
  1612. let (bank, program_id) = load_program_of_loader_v4(
  1613. &mut bank_client,
  1614. &bank_forks,
  1615. &mint_keypair,
  1616. &authority_keypair,
  1617. "solana_sbf_rust_r2_instruction_data_pointer",
  1618. );
  1619. let mut account_metas = Vec::new();
  1620. for i in 0..num_accounts {
  1621. let pubkey = Pubkey::new_unique();
  1622. // Mixed account sizes.
  1623. bank.store_account(
  1624. &pubkey,
  1625. &AccountSharedData::new(0, 100 + (i * 50), &program_id),
  1626. );
  1627. // Mixed account roles.
  1628. if i % 2 == 0 {
  1629. account_metas.push(AccountMeta::new(pubkey, false));
  1630. } else {
  1631. account_metas.push(AccountMeta::new_readonly(pubkey, false));
  1632. }
  1633. }
  1634. bank.freeze();
  1635. // The provided instruction data will be set to the return data.
  1636. let input_data: Vec<u8> = (0..input_data_len).map(|i| (i % 256) as u8).collect();
  1637. let instruction = Instruction::new_with_bytes(program_id, &input_data, account_metas);
  1638. let blockhash = bank.last_blockhash();
  1639. let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
  1640. let transaction = Transaction::new(&[&mint_keypair], message, blockhash);
  1641. let sanitized_tx = RuntimeTransaction::from_transaction_for_tests(transaction);
  1642. let result = bank.simulate_transaction(&sanitized_tx, false);
  1643. assert!(result.result.is_ok());
  1644. let return_data = result.return_data.unwrap().data;
  1645. assert_eq!(input_data, return_data);
  1646. }
  1647. fn get_stable_genesis_config() -> GenesisConfigInfo {
  1648. let validator_pubkey =
  1649. Pubkey::from_str("GLh546CXmtZdvpEzL8sxzqhhUf7KPvmGaRpFHB5W1sjV").unwrap();
  1650. let mint_keypair = Keypair::from_base58_string(
  1651. "4YTH9JSRgZocmK9ezMZeJCCV2LVeR2NatTBA8AFXkg2x83fqrt8Vwyk91961E7ns4vee9yUBzuDfztb8i9iwTLFd",
  1652. );
  1653. let voting_keypair = Keypair::from_base58_string(
  1654. "4EPWEn72zdNY1JSKkzyZ2vTZcKdPW3jM5WjAgUadnoz83FR5cDFApbo7s5mwBcYXn8afVe2syReJaqBi4fkhG3mH",
  1655. );
  1656. let stake_pubkey = Pubkey::from_str("HGq9JF77xFXRgWRJy8VQuhdbdugrT856RvQDzr1KJo6E").unwrap();
  1657. let mut genesis_config = create_genesis_config_with_leader_ex(
  1658. 123,
  1659. &mint_keypair.pubkey(),
  1660. &validator_pubkey,
  1661. &voting_keypair.pubkey(),
  1662. &stake_pubkey,
  1663. None,
  1664. bootstrap_validator_stake_lamports(),
  1665. 42,
  1666. FeeRateGovernor::new(0, 0), // most tests can't handle transaction fees
  1667. Rent::free(), // most tests don't expect rent
  1668. ClusterType::Development,
  1669. vec![],
  1670. );
  1671. genesis_config.creation_time = Duration::ZERO.as_secs() as UnixTimestamp;
  1672. GenesisConfigInfo {
  1673. genesis_config,
  1674. mint_keypair,
  1675. voting_keypair,
  1676. validator_pubkey,
  1677. }
  1678. }
  1679. #[test]
  1680. #[ignore]
  1681. #[cfg(feature = "sbf_rust")]
  1682. fn test_program_sbf_invoke_stable_genesis_and_bank() {
  1683. // The purpose of this test is to exercise various code branches of runtime/VM and
  1684. // assert that the resulting bank hash matches with the expected value.
  1685. // The assert check is commented out by default. Please refer to the last few lines
  1686. // of the test to enable the assertion.
  1687. agave_logger::setup();
  1688. let GenesisConfigInfo {
  1689. genesis_config,
  1690. mint_keypair,
  1691. ..
  1692. } = get_stable_genesis_config();
  1693. let bank = Bank::new_for_tests(&genesis_config);
  1694. let bank = Arc::new(bank);
  1695. let bank_client = BankClient::new_shared(bank.clone());
  1696. // Deploy upgradeable program
  1697. let buffer_keypair = Keypair::from_base58_string(
  1698. "4q4UvWxh2oMifTGbChDeWCbdN8eJEUQ1E6cuNnmymJ6AN5CMUT2VW5A1RKnG9dy7ypLczB9inMUAafh5TkpXrtxg",
  1699. );
  1700. let program_keypair = Keypair::from_base58_string(
  1701. "3LQpBxgpaFNJPit5a8t51pJKMkUmNUn5PhSTcuuhuuBxe43cTeqVPhMtKkFNr5VpFzCExf4ihibvuZgGxmjy6t8n",
  1702. );
  1703. let program_id = program_keypair.pubkey();
  1704. let authority_keypair = Keypair::from_base58_string(
  1705. "285XFW2NTWd6CMvtHzvYYS1kWzmzcGBnyEXbH1v8hq6YJqJsLMTYMPkbEQqeE7m7UqhoMeK5V3HMJLf9DdxwU2Gy",
  1706. );
  1707. let instruction =
  1708. Instruction::new_with_bytes(program_id, &[0], vec![AccountMeta::new(clock::id(), false)]);
  1709. // Call program before its deployed
  1710. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction.clone());
  1711. assert_eq!(
  1712. result.unwrap_err().unwrap(),
  1713. TransactionError::ProgramAccountNotFound
  1714. );
  1715. #[allow(deprecated)]
  1716. solana_runtime::loader_utils::load_upgradeable_program(
  1717. &bank_client,
  1718. &mint_keypair,
  1719. &buffer_keypair,
  1720. &program_keypair,
  1721. &authority_keypair,
  1722. "solana_sbf_rust_noop",
  1723. );
  1724. // Deploy indirect invocation program
  1725. let indirect_program_keypair = Keypair::from_base58_string(
  1726. "2BgE4gD5wUCwiAVPYbmWd2xzXSsD9W2fWgNjwmVkm8WL7i51vK9XAXNnX1VB6oKQZmjaUPRd5RzE6RggB9DeKbZC",
  1727. );
  1728. #[allow(deprecated)]
  1729. solana_runtime::loader_utils::load_upgradeable_program(
  1730. &bank_client,
  1731. &mint_keypair,
  1732. &buffer_keypair,
  1733. &indirect_program_keypair,
  1734. &authority_keypair,
  1735. "solana_sbf_rust_invoke_and_return",
  1736. );
  1737. let invoke_instruction =
  1738. Instruction::new_with_bytes(program_id, &[0], vec![AccountMeta::new(clock::id(), false)]);
  1739. let indirect_invoke_instruction = Instruction::new_with_bytes(
  1740. indirect_program_keypair.pubkey(),
  1741. &[0],
  1742. vec![
  1743. AccountMeta::new_readonly(program_id, false),
  1744. AccountMeta::new_readonly(clock::id(), false),
  1745. ],
  1746. );
  1747. // Prepare redeployment
  1748. let buffer_keypair = Keypair::from_base58_string(
  1749. "5T5L31FiUphXh4N6mxiWhEKPrdLhvMJSbaHo1Ne7zZYkw6YT1fVkqsWdA6pHMtqATiMTc4sfx5yTV9M9AnWDoBkW",
  1750. );
  1751. load_upgradeable_buffer(
  1752. &bank_client,
  1753. &mint_keypair,
  1754. &buffer_keypair,
  1755. &authority_keypair,
  1756. "solana_sbf_rust_panic",
  1757. );
  1758. let redeployment_instruction = loader_v3_instruction::upgrade(
  1759. &program_id,
  1760. &buffer_keypair.pubkey(),
  1761. &authority_keypair.pubkey(),
  1762. &mint_keypair.pubkey(),
  1763. );
  1764. // Redeployment causes programs to be unavailable to both top-level-instructions and CPI instructions
  1765. for invoke_instruction in [invoke_instruction, indirect_invoke_instruction] {
  1766. // Call upgradeable program
  1767. let result =
  1768. bank_client.send_and_confirm_instruction(&mint_keypair, invoke_instruction.clone());
  1769. assert!(result.is_ok());
  1770. // Upgrade the program and invoke in same tx
  1771. let message = Message::new(
  1772. &[redeployment_instruction.clone(), invoke_instruction],
  1773. Some(&mint_keypair.pubkey()),
  1774. );
  1775. let tx = Transaction::new(
  1776. &[&mint_keypair, &authority_keypair],
  1777. message.clone(),
  1778. bank.last_blockhash(),
  1779. );
  1780. let (result, _, _, _) = process_transaction_and_record_inner(&bank, tx);
  1781. assert_eq!(
  1782. result.unwrap_err(),
  1783. TransactionError::InstructionError(1, InstructionError::InvalidAccountData),
  1784. );
  1785. }
  1786. // Prepare undeployment
  1787. let (programdata_address, _) = Pubkey::find_program_address(
  1788. &[program_keypair.pubkey().as_ref()],
  1789. &bpf_loader_upgradeable::id(),
  1790. );
  1791. let undeployment_instruction = loader_v3_instruction::close_any(
  1792. &programdata_address,
  1793. &mint_keypair.pubkey(),
  1794. Some(&authority_keypair.pubkey()),
  1795. Some(&program_id),
  1796. );
  1797. let invoke_instruction =
  1798. Instruction::new_with_bytes(program_id, &[1], vec![AccountMeta::new(clock::id(), false)]);
  1799. let indirect_invoke_instruction = Instruction::new_with_bytes(
  1800. indirect_program_keypair.pubkey(),
  1801. &[1],
  1802. vec![
  1803. AccountMeta::new_readonly(program_id, false),
  1804. AccountMeta::new_readonly(clock::id(), false),
  1805. ],
  1806. );
  1807. // Undeployment is visible to both top-level-instructions and CPI instructions
  1808. for invoke_instruction in [invoke_instruction, indirect_invoke_instruction] {
  1809. // Call upgradeable program
  1810. let result =
  1811. bank_client.send_and_confirm_instruction(&mint_keypair, invoke_instruction.clone());
  1812. assert!(result.is_ok());
  1813. // Undeploy the program and invoke in same tx
  1814. let message = Message::new(
  1815. &[undeployment_instruction.clone(), invoke_instruction],
  1816. Some(&mint_keypair.pubkey()),
  1817. );
  1818. let tx = Transaction::new(
  1819. &[&mint_keypair, &authority_keypair],
  1820. message.clone(),
  1821. bank.last_blockhash(),
  1822. );
  1823. let (result, _, _, _) = process_transaction_and_record_inner(&bank, tx);
  1824. assert_eq!(
  1825. result.unwrap_err(),
  1826. TransactionError::InstructionError(1, InstructionError::InvalidAccountData),
  1827. );
  1828. }
  1829. bank.freeze();
  1830. let expected_hash = Hash::from_str("2A2vqbUKExRbnaAzSnDFXdsBZRZSpCjGZCAA3mFZG2sV")
  1831. .expect("Failed to generate hash");
  1832. println!("Stable test produced bank hash: {}", bank.hash());
  1833. println!("Expected hash: {}", expected_hash);
  1834. // Enable the following code to match the bank hash with the expected bank hash.
  1835. // Follow these steps.
  1836. // 1. Run this test on the baseline/master commit, and get the expected bank hash.
  1837. // 2. Update the `expected_hash` to match the expected bank hash.
  1838. // 3. Run the test in the PR branch that's being tested.
  1839. // If the hash doesn't match, the PR likely has runtime changes that can lead to
  1840. // consensus failure.
  1841. // assert_eq!(bank.hash(), expected_hash);
  1842. }
  1843. #[test]
  1844. #[cfg(feature = "sbf_rust")]
  1845. fn test_program_sbf_invoke_in_same_tx_as_deployment() {
  1846. agave_logger::setup();
  1847. let GenesisConfigInfo {
  1848. genesis_config,
  1849. mint_keypair,
  1850. ..
  1851. } = create_genesis_config(50);
  1852. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  1853. let mut bank_client = BankClient::new_shared(bank.clone());
  1854. // Deploy upgradeable program
  1855. let authority_keypair = Keypair::new();
  1856. let (program_keypair, deployment_instructions) = instructions_to_load_program_of_loader_v4(
  1857. &bank_client,
  1858. &mint_keypair,
  1859. &authority_keypair,
  1860. "solana_sbf_rust_noop",
  1861. None,
  1862. None,
  1863. );
  1864. let program_id = program_keypair.pubkey();
  1865. // Deploy indirect invocation program
  1866. let (bank, indirect_program_id) = load_program_of_loader_v4(
  1867. &mut bank_client,
  1868. &bank_forks,
  1869. &mint_keypair,
  1870. &authority_keypair,
  1871. "solana_sbf_rust_invoke_and_return",
  1872. );
  1873. // Prepare invocations
  1874. let invoke_instruction =
  1875. Instruction::new_with_bytes(program_id, &[0], vec![AccountMeta::new(clock::id(), false)]);
  1876. let indirect_invoke_instruction = Instruction::new_with_bytes(
  1877. indirect_program_id,
  1878. &[0],
  1879. vec![
  1880. AccountMeta::new_readonly(program_id, false),
  1881. AccountMeta::new_readonly(clock::id(), false),
  1882. ],
  1883. );
  1884. // Deployment is invisible to both top-level-instructions and CPI instructions
  1885. for (index, invoke_instruction) in [invoke_instruction, indirect_invoke_instruction]
  1886. .into_iter()
  1887. .enumerate()
  1888. {
  1889. let mut instructions = deployment_instructions.clone();
  1890. instructions.push(invoke_instruction);
  1891. let tx = Transaction::new(
  1892. &[&mint_keypair, &program_keypair, &authority_keypair],
  1893. Message::new(&instructions, Some(&mint_keypair.pubkey())),
  1894. bank.last_blockhash(),
  1895. );
  1896. if index == 0 {
  1897. let result = load_execute_and_commit_transaction(&bank, tx);
  1898. assert_eq!(
  1899. result.unwrap().status,
  1900. Err(TransactionError::ProgramAccountNotFound),
  1901. );
  1902. } else {
  1903. let (result, _, _, _) = process_transaction_and_record_inner(&bank, tx);
  1904. if let TransactionError::InstructionError(instr_no, ty) = result.unwrap_err() {
  1905. // Asserting the instruction number as an upper bound, since the quantity of
  1906. // instructions depends on the program size, which in turn depends on the SBPF
  1907. // versions.
  1908. assert!(instr_no <= 40);
  1909. assert_eq!(ty, InstructionError::UnsupportedProgramId);
  1910. } else {
  1911. panic!("Invalid error type");
  1912. }
  1913. }
  1914. }
  1915. }
  1916. #[test]
  1917. #[cfg(feature = "sbf_rust")]
  1918. fn test_program_sbf_invoke_in_same_tx_as_redeployment() {
  1919. agave_logger::setup();
  1920. let GenesisConfigInfo {
  1921. genesis_config,
  1922. mint_keypair,
  1923. ..
  1924. } = create_genesis_config(50);
  1925. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  1926. let mut bank_client = BankClient::new_shared(bank.clone());
  1927. // Deploy upgradeable program
  1928. let authority_keypair = Keypair::new();
  1929. let (_bank, program_id) = load_program_of_loader_v4(
  1930. &mut bank_client,
  1931. &bank_forks,
  1932. &mint_keypair,
  1933. &authority_keypair,
  1934. "solana_sbf_rust_noop",
  1935. );
  1936. let (source_program_keypair, mut deployment_instructions) =
  1937. instructions_to_load_program_of_loader_v4(
  1938. &bank_client,
  1939. &mint_keypair,
  1940. &authority_keypair,
  1941. "solana_sbf_rust_panic",
  1942. None,
  1943. Some(&program_id),
  1944. );
  1945. let undeployment_instruction =
  1946. loader_v4_instruction::retract(&program_id, &authority_keypair.pubkey());
  1947. let redeployment_instructions =
  1948. deployment_instructions.split_off(deployment_instructions.len() - 3);
  1949. let signers: &[&[&Keypair]] = &[
  1950. &[&mint_keypair, &source_program_keypair],
  1951. &[&mint_keypair, &authority_keypair],
  1952. ];
  1953. let signers = std::iter::once(signers[0]).chain(std::iter::repeat(signers[1]));
  1954. for (instruction, signers) in deployment_instructions.into_iter().zip(signers) {
  1955. let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
  1956. bank_client
  1957. .send_and_confirm_message(signers, message)
  1958. .unwrap();
  1959. }
  1960. // Deploy indirect invocation program
  1961. let (bank, indirect_program_id) = load_program_of_loader_v4(
  1962. &mut bank_client,
  1963. &bank_forks,
  1964. &mint_keypair,
  1965. &authority_keypair,
  1966. "solana_sbf_rust_invoke_and_return",
  1967. );
  1968. // Prepare invocations
  1969. let invoke_instruction =
  1970. Instruction::new_with_bytes(program_id, &[0], vec![AccountMeta::new(clock::id(), false)]);
  1971. let indirect_invoke_instruction = Instruction::new_with_bytes(
  1972. indirect_program_id,
  1973. &[0],
  1974. vec![
  1975. AccountMeta::new_readonly(program_id, false),
  1976. AccountMeta::new_readonly(clock::id(), false),
  1977. ],
  1978. );
  1979. // Redeployment fails when top-level-instructions invoke the program because of write lock demotion
  1980. // and the program becomes unavailable to CPI instructions
  1981. for (invoke_instruction, expected_error) in [
  1982. (
  1983. invoke_instruction,
  1984. TransactionError::InstructionError(0, InstructionError::InvalidArgument),
  1985. ),
  1986. (
  1987. indirect_invoke_instruction,
  1988. TransactionError::InstructionError(4, InstructionError::UnsupportedProgramId),
  1989. ),
  1990. ] {
  1991. // Call upgradeable program
  1992. let result =
  1993. bank_client.send_and_confirm_instruction(&mint_keypair, invoke_instruction.clone());
  1994. assert!(result.is_ok());
  1995. // Upgrade the program and invoke in same tx
  1996. let message = Message::new(
  1997. &[
  1998. undeployment_instruction.clone(),
  1999. redeployment_instructions[0].clone(),
  2000. redeployment_instructions[1].clone(),
  2001. redeployment_instructions[2].clone(),
  2002. invoke_instruction,
  2003. ],
  2004. Some(&mint_keypair.pubkey()),
  2005. );
  2006. let tx = Transaction::new(
  2007. &[&mint_keypair, &authority_keypair],
  2008. message.clone(),
  2009. bank.last_blockhash(),
  2010. );
  2011. let (result, _, _, _) = process_transaction_and_record_inner(&bank, tx);
  2012. assert_eq!(result.unwrap_err(), expected_error,);
  2013. }
  2014. }
  2015. #[test]
  2016. #[cfg(feature = "sbf_rust")]
  2017. fn test_program_sbf_invoke_in_same_tx_as_undeployment() {
  2018. agave_logger::setup();
  2019. let GenesisConfigInfo {
  2020. genesis_config,
  2021. mint_keypair,
  2022. ..
  2023. } = create_genesis_config(50);
  2024. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  2025. let mut bank_client = BankClient::new_shared(bank.clone());
  2026. // Deploy upgradeable program
  2027. let authority_keypair = Keypair::new();
  2028. let (_bank, program_id) = load_program_of_loader_v4(
  2029. &mut bank_client,
  2030. &bank_forks,
  2031. &mint_keypair,
  2032. &authority_keypair,
  2033. "solana_sbf_rust_noop",
  2034. );
  2035. // Deploy indirect invocation program
  2036. let (bank, indirect_program_id) = load_program_of_loader_v4(
  2037. &mut bank_client,
  2038. &bank_forks,
  2039. &mint_keypair,
  2040. &authority_keypair,
  2041. "solana_sbf_rust_invoke_and_return",
  2042. );
  2043. // Prepare invocations
  2044. let invoke_instruction =
  2045. Instruction::new_with_bytes(program_id, &[0], vec![AccountMeta::new(clock::id(), false)]);
  2046. let indirect_invoke_instruction = Instruction::new_with_bytes(
  2047. indirect_program_id,
  2048. &[0],
  2049. vec![
  2050. AccountMeta::new_readonly(program_id, false),
  2051. AccountMeta::new_readonly(clock::id(), false),
  2052. ],
  2053. );
  2054. // Prepare undeployment
  2055. let undeployment_instruction =
  2056. loader_v4_instruction::retract(&program_id, &authority_keypair.pubkey());
  2057. // Undeployment fails when top-level-instructions invoke the program because of write lock demotion
  2058. // and the program becomes unavailable to CPI instructions
  2059. for (invoke_instruction, expected_error) in [
  2060. (
  2061. invoke_instruction,
  2062. TransactionError::InstructionError(0, InstructionError::InvalidArgument),
  2063. ),
  2064. (
  2065. indirect_invoke_instruction,
  2066. TransactionError::InstructionError(1, InstructionError::UnsupportedProgramId),
  2067. ),
  2068. ] {
  2069. // Call upgradeable program
  2070. let result =
  2071. bank_client.send_and_confirm_instruction(&mint_keypair, invoke_instruction.clone());
  2072. assert!(result.is_ok());
  2073. // Upgrade the program and invoke in same tx
  2074. let message = Message::new(
  2075. &[undeployment_instruction.clone(), invoke_instruction],
  2076. Some(&mint_keypair.pubkey()),
  2077. );
  2078. let tx = Transaction::new(
  2079. &[&mint_keypair, &authority_keypair],
  2080. message.clone(),
  2081. bank.last_blockhash(),
  2082. );
  2083. let (result, _, _, _) = process_transaction_and_record_inner(&bank, tx);
  2084. assert_eq!(result.unwrap_err(), expected_error,);
  2085. }
  2086. }
  2087. #[test]
  2088. #[cfg(any(feature = "sbf_c", feature = "sbf_rust"))]
  2089. fn test_program_sbf_disguised_as_sbf_loader() {
  2090. agave_logger::setup();
  2091. let mut programs = Vec::new();
  2092. #[cfg(feature = "sbf_c")]
  2093. {
  2094. programs.extend_from_slice(&[("noop")]);
  2095. }
  2096. #[cfg(feature = "sbf_rust")]
  2097. {
  2098. programs.extend_from_slice(&[("solana_sbf_rust_noop")]);
  2099. }
  2100. for program in programs.iter() {
  2101. let GenesisConfigInfo {
  2102. genesis_config,
  2103. mint_keypair,
  2104. ..
  2105. } = create_genesis_config(50);
  2106. let mut bank = Bank::new_for_tests(&genesis_config);
  2107. bank.deactivate_feature(&agave_feature_set::remove_bpf_loader_incorrect_program_id::id());
  2108. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  2109. let mut bank_client = BankClient::new_shared(bank);
  2110. let authority_keypair = Keypair::new();
  2111. let (_bank, program_id) = load_program_of_loader_v4(
  2112. &mut bank_client,
  2113. &bank_forks,
  2114. &mint_keypair,
  2115. &authority_keypair,
  2116. program,
  2117. );
  2118. let account_metas = vec![AccountMeta::new_readonly(program_id, false)];
  2119. let instruction = Instruction::new_with_bytes(bpf_loader::id(), &[1], account_metas);
  2120. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  2121. assert_eq!(
  2122. result.unwrap_err().unwrap(),
  2123. TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId)
  2124. );
  2125. }
  2126. }
  2127. #[test]
  2128. #[cfg(feature = "sbf_c")]
  2129. fn test_program_reads_from_program_account() {
  2130. use solana_loader_v4_interface::state as loader_v4_state;
  2131. agave_logger::setup();
  2132. let GenesisConfigInfo {
  2133. genesis_config,
  2134. mint_keypair,
  2135. ..
  2136. } = create_genesis_config(50);
  2137. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  2138. let mut bank_client = BankClient::new_shared(bank);
  2139. let authority_keypair = Keypair::new();
  2140. let (_bank, program_id) = load_program_of_loader_v4(
  2141. &mut bank_client,
  2142. &bank_forks,
  2143. &mint_keypair,
  2144. &authority_keypair,
  2145. "read_program",
  2146. );
  2147. let data = bank_client.get_account_data(&program_id).unwrap().unwrap();
  2148. let account_metas = vec![AccountMeta::new_readonly(program_id, false)];
  2149. let instruction = Instruction::new_with_bytes(
  2150. program_id,
  2151. &data[0..loader_v4_state::LoaderV4State::program_data_offset()],
  2152. account_metas,
  2153. );
  2154. bank_client
  2155. .send_and_confirm_instruction(&mint_keypair, instruction)
  2156. .unwrap();
  2157. }
  2158. #[test]
  2159. #[cfg(feature = "sbf_c")]
  2160. fn test_program_sbf_c_dup() {
  2161. agave_logger::setup();
  2162. let GenesisConfigInfo {
  2163. genesis_config,
  2164. mint_keypair,
  2165. ..
  2166. } = create_genesis_config(50);
  2167. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  2168. let account_address = Pubkey::new_unique();
  2169. let account = AccountSharedData::new_data(42, &[1_u8, 2, 3], &system_program::id()).unwrap();
  2170. bank.store_account(&account_address, &account);
  2171. let mut bank_client = BankClient::new_shared(bank);
  2172. let authority_keypair = Keypair::new();
  2173. let (_bank, program_id) = load_program_of_loader_v4(
  2174. &mut bank_client,
  2175. &bank_forks,
  2176. &mint_keypair,
  2177. &authority_keypair,
  2178. "ser",
  2179. );
  2180. let account_metas = vec![
  2181. AccountMeta::new_readonly(account_address, false),
  2182. AccountMeta::new_readonly(account_address, false),
  2183. ];
  2184. let instruction = Instruction::new_with_bytes(program_id, &[4, 5, 6, 7], account_metas);
  2185. bank_client
  2186. .send_and_confirm_instruction(&mint_keypair, instruction)
  2187. .unwrap();
  2188. }
  2189. #[test]
  2190. #[cfg(feature = "sbf_rust")]
  2191. fn test_program_sbf_upgrade() {
  2192. agave_logger::setup();
  2193. let GenesisConfigInfo {
  2194. genesis_config,
  2195. mint_keypair,
  2196. ..
  2197. } = create_genesis_config(50);
  2198. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  2199. let mut bank_client = BankClient::new_shared(bank);
  2200. // Deploy upgrade program
  2201. let authority_keypair = Keypair::new();
  2202. let (_bank, program_id) = load_program_of_loader_v4(
  2203. &mut bank_client,
  2204. &bank_forks,
  2205. &mint_keypair,
  2206. &authority_keypair,
  2207. "solana_sbf_rust_upgradeable",
  2208. );
  2209. // Call upgradeable program
  2210. let mut instruction =
  2211. Instruction::new_with_bytes(program_id, &[0], vec![AccountMeta::new(clock::id(), false)]);
  2212. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction.clone());
  2213. assert_eq!(
  2214. result.unwrap_err().unwrap(),
  2215. TransactionError::InstructionError(0, InstructionError::Custom(42))
  2216. );
  2217. // Set authority
  2218. let new_authority_keypair = Keypair::new();
  2219. let authority_instruction = loader_v4_instruction::transfer_authority(
  2220. &program_id,
  2221. &authority_keypair.pubkey(),
  2222. &new_authority_keypair.pubkey(),
  2223. );
  2224. let message = Message::new(&[authority_instruction], Some(&mint_keypair.pubkey()));
  2225. bank_client
  2226. .send_and_confirm_message(
  2227. &[&mint_keypair, &authority_keypair, &new_authority_keypair],
  2228. message,
  2229. )
  2230. .unwrap();
  2231. // Upgrade program
  2232. let (source_program_keypair, mut deployment_instructions) =
  2233. instructions_to_load_program_of_loader_v4(
  2234. &bank_client,
  2235. &mint_keypair,
  2236. &new_authority_keypair,
  2237. "solana_sbf_rust_upgraded",
  2238. None,
  2239. Some(&program_id),
  2240. );
  2241. deployment_instructions.insert(
  2242. deployment_instructions.len() - 3,
  2243. loader_v4_instruction::retract(&program_id, &new_authority_keypair.pubkey()),
  2244. );
  2245. let signers: &[&[&Keypair]] = &[
  2246. &[&mint_keypair, &source_program_keypair],
  2247. &[&mint_keypair, &new_authority_keypair],
  2248. ];
  2249. let signers = std::iter::once(signers[0]).chain(std::iter::repeat(signers[1]));
  2250. for (instruction, signers) in deployment_instructions.into_iter().zip(signers) {
  2251. let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
  2252. bank_client
  2253. .send_and_confirm_message(signers, message)
  2254. .unwrap();
  2255. }
  2256. bank_client
  2257. .advance_slot(1, &bank_forks, &Pubkey::default())
  2258. .expect("Failed to advance the slot");
  2259. // Call upgraded program
  2260. instruction.data[0] += 1;
  2261. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction.clone());
  2262. assert_eq!(
  2263. result.unwrap_err().unwrap(),
  2264. TransactionError::InstructionError(0, InstructionError::Custom(43))
  2265. );
  2266. }
  2267. #[test]
  2268. #[cfg(feature = "sbf_rust")]
  2269. fn test_program_sbf_upgrade_via_cpi() {
  2270. agave_logger::setup();
  2271. let GenesisConfigInfo {
  2272. genesis_config,
  2273. mint_keypair,
  2274. ..
  2275. } = create_genesis_config(50);
  2276. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  2277. let mut bank_client = BankClient::new_shared(bank);
  2278. let authority_keypair = Keypair::new();
  2279. let (_bank, invoke_and_return) = load_program_of_loader_v4(
  2280. &mut bank_client,
  2281. &bank_forks,
  2282. &mint_keypair,
  2283. &authority_keypair,
  2284. "solana_sbf_rust_invoke_and_return",
  2285. );
  2286. // Deploy upgradeable program
  2287. let authority_keypair = Keypair::new();
  2288. let (_bank, program_id) = load_program_of_loader_v4(
  2289. &mut bank_client,
  2290. &bank_forks,
  2291. &mint_keypair,
  2292. &authority_keypair,
  2293. "solana_sbf_rust_upgradeable",
  2294. );
  2295. // Call the upgradable program via CPI
  2296. let mut instruction = Instruction::new_with_bytes(
  2297. invoke_and_return,
  2298. &[0],
  2299. vec![
  2300. AccountMeta::new_readonly(program_id, false),
  2301. AccountMeta::new_readonly(clock::id(), false),
  2302. ],
  2303. );
  2304. instruction.data[0] += 1;
  2305. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction.clone());
  2306. assert_eq!(
  2307. result.unwrap_err().unwrap(),
  2308. TransactionError::InstructionError(0, InstructionError::Custom(42))
  2309. );
  2310. // Set authority via CPI
  2311. let new_authority_keypair = Keypair::new();
  2312. let mut authority_instruction = loader_v4_instruction::transfer_authority(
  2313. &program_id,
  2314. &authority_keypair.pubkey(),
  2315. &new_authority_keypair.pubkey(),
  2316. );
  2317. authority_instruction.program_id = invoke_and_return;
  2318. authority_instruction
  2319. .accounts
  2320. .insert(0, AccountMeta::new(loader_v4::id(), false));
  2321. let message = Message::new(&[authority_instruction], Some(&mint_keypair.pubkey()));
  2322. bank_client
  2323. .send_and_confirm_message(
  2324. &[&mint_keypair, &authority_keypair, &new_authority_keypair],
  2325. message,
  2326. )
  2327. .unwrap();
  2328. // Upgrade program via CPI
  2329. let (source_program_keypair, mut deployment_instructions) =
  2330. instructions_to_load_program_of_loader_v4(
  2331. &bank_client,
  2332. &mint_keypair,
  2333. &new_authority_keypair,
  2334. "solana_sbf_rust_upgraded",
  2335. None,
  2336. Some(&program_id),
  2337. );
  2338. deployment_instructions.insert(
  2339. deployment_instructions.len() - 3,
  2340. loader_v4_instruction::retract(&program_id, &new_authority_keypair.pubkey()),
  2341. );
  2342. let mut upgrade_instruction = deployment_instructions.pop().unwrap();
  2343. let signers: &[&[&Keypair]] = &[
  2344. &[&mint_keypair, &source_program_keypair],
  2345. &[&mint_keypair, &new_authority_keypair],
  2346. ];
  2347. let signers = std::iter::once(signers[0]).chain(std::iter::repeat(signers[1]));
  2348. for (instruction, signers) in deployment_instructions.into_iter().zip(signers) {
  2349. let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
  2350. bank_client
  2351. .send_and_confirm_message(signers, message)
  2352. .unwrap();
  2353. }
  2354. upgrade_instruction.program_id = invoke_and_return;
  2355. upgrade_instruction
  2356. .accounts
  2357. .insert(0, AccountMeta::new(loader_v4::id(), false));
  2358. let message = Message::new(&[upgrade_instruction], Some(&mint_keypair.pubkey()));
  2359. bank_client
  2360. .send_and_confirm_message(&[&mint_keypair, &new_authority_keypair], message)
  2361. .unwrap();
  2362. bank_client
  2363. .advance_slot(1, &bank_forks, &Pubkey::default())
  2364. .expect("Failed to advance the slot");
  2365. // Call the upgraded program via CPI
  2366. instruction.data[0] += 1;
  2367. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction.clone());
  2368. assert_eq!(
  2369. result.unwrap_err().unwrap(),
  2370. TransactionError::InstructionError(0, InstructionError::Custom(43))
  2371. );
  2372. }
  2373. #[test]
  2374. #[cfg(feature = "sbf_rust")]
  2375. fn test_program_sbf_ro_account_modify() {
  2376. agave_logger::setup();
  2377. let GenesisConfigInfo {
  2378. genesis_config,
  2379. mint_keypair,
  2380. ..
  2381. } = create_genesis_config(50);
  2382. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  2383. let mut bank_client = BankClient::new_shared(bank.clone());
  2384. let authority_keypair = Keypair::new();
  2385. let (bank, program_id) = load_program_of_loader_v4(
  2386. &mut bank_client,
  2387. &bank_forks,
  2388. &mint_keypair,
  2389. &authority_keypair,
  2390. "solana_sbf_rust_ro_account_modify",
  2391. );
  2392. let argument_keypair = Keypair::new();
  2393. let account = AccountSharedData::new(42, 100, &program_id);
  2394. bank.store_account(&argument_keypair.pubkey(), &account);
  2395. let from_keypair = Keypair::new();
  2396. let account = AccountSharedData::new(84, 0, &system_program::id());
  2397. bank.store_account(&from_keypair.pubkey(), &account);
  2398. let mint_pubkey = mint_keypair.pubkey();
  2399. let account_metas = vec![
  2400. AccountMeta::new_readonly(argument_keypair.pubkey(), false),
  2401. AccountMeta::new_readonly(program_id, false),
  2402. ];
  2403. let instruction = Instruction::new_with_bytes(program_id, &[0], account_metas.clone());
  2404. let message = Message::new(&[instruction], Some(&mint_pubkey));
  2405. let result = bank_client.send_and_confirm_message(&[&mint_keypair], message);
  2406. assert_eq!(
  2407. result.unwrap_err().unwrap(),
  2408. TransactionError::InstructionError(0, InstructionError::ReadonlyDataModified)
  2409. );
  2410. let instruction = Instruction::new_with_bytes(program_id, &[1], account_metas.clone());
  2411. let message = Message::new(&[instruction], Some(&mint_pubkey));
  2412. let result = bank_client.send_and_confirm_message(&[&mint_keypair], message);
  2413. assert_eq!(
  2414. result.unwrap_err().unwrap(),
  2415. TransactionError::InstructionError(0, InstructionError::ReadonlyDataModified)
  2416. );
  2417. let instruction = Instruction::new_with_bytes(program_id, &[2], account_metas.clone());
  2418. let message = Message::new(&[instruction], Some(&mint_pubkey));
  2419. let result = bank_client.send_and_confirm_message(&[&mint_keypair], message);
  2420. assert_eq!(
  2421. result.unwrap_err().unwrap(),
  2422. TransactionError::InstructionError(0, InstructionError::ReadonlyDataModified)
  2423. );
  2424. }
  2425. #[test]
  2426. #[cfg(feature = "sbf_rust")]
  2427. fn test_program_sbf_realloc() {
  2428. agave_logger::setup();
  2429. const START_BALANCE: u64 = 100_000_000_000;
  2430. let GenesisConfigInfo {
  2431. genesis_config,
  2432. mint_keypair,
  2433. ..
  2434. } = create_genesis_config(1_000_000_000_000);
  2435. let mint_pubkey = mint_keypair.pubkey();
  2436. let signer = &[&mint_keypair];
  2437. for stricter_abi_and_runtime_constraints in [false, true] {
  2438. let mut bank = Bank::new_for_tests(&genesis_config);
  2439. let feature_set = Arc::make_mut(&mut bank.feature_set);
  2440. // by default test banks have all features enabled, so we only need to
  2441. // disable when needed
  2442. if !stricter_abi_and_runtime_constraints {
  2443. feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
  2444. feature_set.deactivate(&feature_set::account_data_direct_mapping::id());
  2445. }
  2446. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  2447. let mut bank_client = BankClient::new_shared(bank.clone());
  2448. let authority_keypair = Keypair::new();
  2449. let (bank, program_id) = load_program_of_loader_v4(
  2450. &mut bank_client,
  2451. &bank_forks,
  2452. &mint_keypair,
  2453. &authority_keypair,
  2454. "solana_sbf_rust_realloc",
  2455. );
  2456. let mut bump = 0;
  2457. let keypair = Keypair::new();
  2458. let pubkey = keypair.pubkey();
  2459. let account = AccountSharedData::new(START_BALANCE, 5, &program_id);
  2460. bank.store_account(&pubkey, &account);
  2461. // Realloc RO account
  2462. let mut instruction = realloc(&program_id, &pubkey, 0, &mut bump);
  2463. instruction.accounts[0].is_writable = false;
  2464. assert_eq!(
  2465. bank_client
  2466. .send_and_confirm_message(
  2467. signer,
  2468. Message::new(
  2469. &[
  2470. instruction,
  2471. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2472. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  2473. ),
  2474. ],
  2475. Some(&mint_pubkey),
  2476. ),
  2477. )
  2478. .unwrap_err()
  2479. .unwrap(),
  2480. TransactionError::InstructionError(0, InstructionError::ReadonlyDataModified)
  2481. );
  2482. // Realloc account to overflow
  2483. assert_eq!(
  2484. bank_client
  2485. .send_and_confirm_message(
  2486. signer,
  2487. Message::new(
  2488. &[
  2489. realloc(&program_id, &pubkey, usize::MAX, &mut bump),
  2490. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2491. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  2492. ),
  2493. ],
  2494. Some(&mint_pubkey),
  2495. ),
  2496. )
  2497. .unwrap_err()
  2498. .unwrap(),
  2499. TransactionError::InstructionError(0, InstructionError::InvalidRealloc)
  2500. );
  2501. // Realloc account to 0
  2502. bank_client
  2503. .send_and_confirm_message(
  2504. signer,
  2505. Message::new(
  2506. &[
  2507. realloc(&program_id, &pubkey, 0, &mut bump),
  2508. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2509. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2510. ),
  2511. ],
  2512. Some(&mint_pubkey),
  2513. ),
  2514. )
  2515. .unwrap();
  2516. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  2517. assert_eq!(0, data.len());
  2518. // Realloc account to max then undo
  2519. bank_client
  2520. .send_and_confirm_message(
  2521. signer,
  2522. Message::new(
  2523. &[
  2524. realloc_extend_and_undo(
  2525. &program_id,
  2526. &pubkey,
  2527. MAX_PERMITTED_DATA_INCREASE,
  2528. &mut bump,
  2529. ),
  2530. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2531. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2532. ),
  2533. ],
  2534. Some(&mint_pubkey),
  2535. ),
  2536. )
  2537. .unwrap();
  2538. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  2539. assert_eq!(0, data.len());
  2540. // Realloc account to max + 1 then undo
  2541. assert_eq!(
  2542. bank_client
  2543. .send_and_confirm_message(
  2544. signer,
  2545. Message::new(
  2546. &[
  2547. realloc_extend_and_undo(
  2548. &program_id,
  2549. &pubkey,
  2550. MAX_PERMITTED_DATA_INCREASE + 1,
  2551. &mut bump,
  2552. ),
  2553. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2554. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  2555. ),
  2556. ],
  2557. Some(&mint_pubkey),
  2558. ),
  2559. )
  2560. .unwrap_err()
  2561. .unwrap(),
  2562. TransactionError::InstructionError(0, InstructionError::InvalidRealloc)
  2563. );
  2564. // Realloc to max + 1
  2565. assert_eq!(
  2566. bank_client
  2567. .send_and_confirm_message(
  2568. signer,
  2569. Message::new(
  2570. &[
  2571. realloc(
  2572. &program_id,
  2573. &pubkey,
  2574. MAX_PERMITTED_DATA_INCREASE + 1,
  2575. &mut bump
  2576. ),
  2577. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2578. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  2579. ),
  2580. ],
  2581. Some(&mint_pubkey),
  2582. ),
  2583. )
  2584. .unwrap_err()
  2585. .unwrap(),
  2586. TransactionError::InstructionError(0, InstructionError::InvalidRealloc)
  2587. );
  2588. // Realloc to max length in max increase increments
  2589. for i in 0..MAX_PERMITTED_DATA_LENGTH as usize / MAX_PERMITTED_DATA_INCREASE {
  2590. let mut bump = i as u64;
  2591. bank_client
  2592. .send_and_confirm_message(
  2593. signer,
  2594. Message::new(
  2595. &[
  2596. realloc_extend_and_fill(
  2597. &program_id,
  2598. &pubkey,
  2599. MAX_PERMITTED_DATA_INCREASE,
  2600. 1,
  2601. &mut bump,
  2602. ),
  2603. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2604. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2605. ),
  2606. ],
  2607. Some(&mint_pubkey),
  2608. ),
  2609. )
  2610. .unwrap();
  2611. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  2612. assert_eq!((i + 1) * MAX_PERMITTED_DATA_INCREASE, data.len());
  2613. }
  2614. for i in 0..data.len() {
  2615. assert_eq!(data[i], 1);
  2616. }
  2617. // and one more time should fail
  2618. assert_eq!(
  2619. bank_client
  2620. .send_and_confirm_message(
  2621. signer,
  2622. Message::new(
  2623. &[
  2624. realloc_extend(
  2625. &program_id,
  2626. &pubkey,
  2627. MAX_PERMITTED_DATA_INCREASE,
  2628. &mut bump
  2629. ),
  2630. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2631. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  2632. ),
  2633. ],
  2634. Some(&mint_pubkey),
  2635. )
  2636. )
  2637. .unwrap_err()
  2638. .unwrap(),
  2639. TransactionError::InstructionError(0, InstructionError::InvalidRealloc)
  2640. );
  2641. // Realloc to 6 bytes
  2642. bank_client
  2643. .send_and_confirm_message(
  2644. signer,
  2645. Message::new(
  2646. &[
  2647. realloc(&program_id, &pubkey, 6, &mut bump),
  2648. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2649. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2650. ),
  2651. ],
  2652. Some(&mint_pubkey),
  2653. ),
  2654. )
  2655. .unwrap();
  2656. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  2657. assert_eq!(6, data.len());
  2658. // Extend by 2 bytes and write a u64. This ensures that we can do writes that span the original
  2659. // account length (6 bytes) and the realloc data (2 bytes).
  2660. bank_client
  2661. .send_and_confirm_message(
  2662. signer,
  2663. Message::new(
  2664. &[
  2665. extend_and_write_u64(&program_id, &pubkey, 0x1122334455667788),
  2666. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2667. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2668. ),
  2669. ],
  2670. Some(&mint_pubkey),
  2671. ),
  2672. )
  2673. .unwrap();
  2674. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  2675. assert_eq!(8, data.len());
  2676. assert_eq!(0x1122334455667788, unsafe { *data.as_ptr().cast::<u64>() });
  2677. // Realloc to 0
  2678. bank_client
  2679. .send_and_confirm_message(
  2680. signer,
  2681. Message::new(
  2682. &[
  2683. realloc(&program_id, &pubkey, 0, &mut bump),
  2684. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2685. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2686. ),
  2687. ],
  2688. Some(&mint_pubkey),
  2689. ),
  2690. )
  2691. .unwrap();
  2692. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  2693. assert_eq!(0, data.len());
  2694. // Realloc and assign
  2695. bank_client
  2696. .send_and_confirm_message(
  2697. signer,
  2698. Message::new(
  2699. &[
  2700. Instruction::new_with_bytes(
  2701. program_id,
  2702. &[REALLOC_AND_ASSIGN],
  2703. vec![AccountMeta::new(pubkey, false)],
  2704. ),
  2705. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2706. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2707. ),
  2708. ],
  2709. Some(&mint_pubkey),
  2710. ),
  2711. )
  2712. .unwrap();
  2713. let account = bank.get_account(&pubkey).unwrap();
  2714. assert_eq!(&solana_system_interface::program::id(), account.owner());
  2715. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  2716. assert_eq!(MAX_PERMITTED_DATA_INCREASE, data.len());
  2717. // Realloc to 0 with wrong owner
  2718. assert_eq!(
  2719. bank_client
  2720. .send_and_confirm_message(
  2721. signer,
  2722. Message::new(
  2723. &[
  2724. realloc(&program_id, &pubkey, 0, &mut bump),
  2725. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2726. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  2727. ),
  2728. ],
  2729. Some(&mint_pubkey),
  2730. ),
  2731. )
  2732. .unwrap_err()
  2733. .unwrap(),
  2734. TransactionError::InstructionError(0, InstructionError::AccountDataSizeChanged)
  2735. );
  2736. // realloc and assign to self via cpi
  2737. assert_eq!(
  2738. bank_client
  2739. .send_and_confirm_message(
  2740. &[&mint_keypair, &keypair],
  2741. Message::new(
  2742. &[
  2743. Instruction::new_with_bytes(
  2744. program_id,
  2745. &[REALLOC_AND_ASSIGN_TO_SELF_VIA_SYSTEM_PROGRAM],
  2746. vec![
  2747. AccountMeta::new(pubkey, true),
  2748. AccountMeta::new(solana_system_interface::program::id(), false),
  2749. ],
  2750. ),
  2751. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2752. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  2753. ),
  2754. ],
  2755. Some(&mint_pubkey),
  2756. )
  2757. )
  2758. .unwrap_err()
  2759. .unwrap(),
  2760. TransactionError::InstructionError(0, InstructionError::AccountDataSizeChanged)
  2761. );
  2762. // Assign to self and realloc via cpi
  2763. bank_client
  2764. .send_and_confirm_message(
  2765. &[&mint_keypair, &keypair],
  2766. Message::new(
  2767. &[
  2768. Instruction::new_with_bytes(
  2769. program_id,
  2770. &[ASSIGN_TO_SELF_VIA_SYSTEM_PROGRAM_AND_REALLOC],
  2771. vec![
  2772. AccountMeta::new(pubkey, true),
  2773. AccountMeta::new(solana_system_interface::program::id(), false),
  2774. ],
  2775. ),
  2776. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2777. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2778. ),
  2779. ],
  2780. Some(&mint_pubkey),
  2781. ),
  2782. )
  2783. .unwrap();
  2784. let account = bank.get_account(&pubkey).unwrap();
  2785. assert_eq!(&program_id, account.owner());
  2786. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  2787. assert_eq!(2 * MAX_PERMITTED_DATA_INCREASE, data.len());
  2788. // Realloc to 0
  2789. bank_client
  2790. .send_and_confirm_message(
  2791. signer,
  2792. Message::new(
  2793. &[
  2794. realloc(&program_id, &pubkey, 0, &mut bump),
  2795. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2796. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2797. ),
  2798. ],
  2799. Some(&mint_pubkey),
  2800. ),
  2801. )
  2802. .unwrap();
  2803. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  2804. assert_eq!(0, data.len());
  2805. // zero-init
  2806. bank_client
  2807. .send_and_confirm_message(
  2808. &[&mint_keypair, &keypair],
  2809. Message::new(
  2810. &[
  2811. Instruction::new_with_bytes(
  2812. program_id,
  2813. &[ZERO_INIT],
  2814. vec![AccountMeta::new(pubkey, true)],
  2815. ),
  2816. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2817. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2818. ),
  2819. ],
  2820. Some(&mint_pubkey),
  2821. ),
  2822. )
  2823. .unwrap();
  2824. }
  2825. }
  2826. #[test]
  2827. #[cfg(feature = "sbf_rust")]
  2828. fn test_program_sbf_realloc_invoke() {
  2829. agave_logger::setup();
  2830. const START_BALANCE: u64 = 100_000_000_000;
  2831. let GenesisConfigInfo {
  2832. mut genesis_config,
  2833. mint_keypair,
  2834. ..
  2835. } = create_genesis_config(1_000_000_000_000);
  2836. genesis_config.rent = Rent::default();
  2837. let mint_pubkey = mint_keypair.pubkey();
  2838. let signer = &[&mint_keypair];
  2839. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  2840. let mut bank_client = BankClient::new_shared(bank.clone());
  2841. let authority_keypair = Keypair::new();
  2842. let (_bank, realloc_program_id) = load_program_of_loader_v4(
  2843. &mut bank_client,
  2844. &bank_forks,
  2845. &mint_keypair,
  2846. &authority_keypair,
  2847. "solana_sbf_rust_realloc",
  2848. );
  2849. let (bank, realloc_invoke_program_id) = load_program_of_loader_v4(
  2850. &mut bank_client,
  2851. &bank_forks,
  2852. &mint_keypair,
  2853. &authority_keypair,
  2854. "solana_sbf_rust_realloc_invoke",
  2855. );
  2856. let mut bump = 0;
  2857. let keypair = Keypair::new();
  2858. let pubkey = keypair.pubkey().clone();
  2859. let account = AccountSharedData::new(START_BALANCE, 5, &realloc_program_id);
  2860. bank.store_account(&pubkey, &account);
  2861. let invoke_keypair = Keypair::new();
  2862. let invoke_pubkey = invoke_keypair.pubkey().clone();
  2863. // Realloc RO account
  2864. assert_eq!(
  2865. bank_client
  2866. .send_and_confirm_message(
  2867. signer,
  2868. Message::new(
  2869. &[
  2870. Instruction::new_with_bytes(
  2871. realloc_invoke_program_id,
  2872. &[INVOKE_REALLOC_ZERO_RO],
  2873. vec![
  2874. AccountMeta::new_readonly(pubkey, false),
  2875. AccountMeta::new_readonly(realloc_program_id, false),
  2876. ],
  2877. ),
  2878. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2879. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  2880. ),
  2881. ],
  2882. Some(&mint_pubkey),
  2883. )
  2884. )
  2885. .unwrap_err()
  2886. .unwrap(),
  2887. TransactionError::InstructionError(0, InstructionError::ReadonlyDataModified)
  2888. );
  2889. let account = bank.get_account(&pubkey).unwrap();
  2890. assert_eq!(account.lamports(), START_BALANCE);
  2891. // Realloc account to 0
  2892. bank_client
  2893. .send_and_confirm_message(
  2894. signer,
  2895. Message::new(
  2896. &[
  2897. realloc(&realloc_program_id, &pubkey, 0, &mut bump),
  2898. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2899. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2900. ),
  2901. ],
  2902. Some(&mint_pubkey),
  2903. ),
  2904. )
  2905. .unwrap();
  2906. let account = bank.get_account(&pubkey).unwrap();
  2907. assert_eq!(account.lamports(), START_BALANCE);
  2908. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  2909. assert_eq!(0, data.len());
  2910. // Realloc to max + 1
  2911. assert_eq!(
  2912. bank_client
  2913. .send_and_confirm_message(
  2914. signer,
  2915. Message::new(
  2916. &[
  2917. Instruction::new_with_bytes(
  2918. realloc_invoke_program_id,
  2919. &[INVOKE_REALLOC_MAX_PLUS_ONE],
  2920. vec![
  2921. AccountMeta::new(pubkey, false),
  2922. AccountMeta::new_readonly(realloc_program_id, false),
  2923. ],
  2924. ),
  2925. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2926. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  2927. ),
  2928. ],
  2929. Some(&mint_pubkey),
  2930. )
  2931. )
  2932. .unwrap_err()
  2933. .unwrap(),
  2934. TransactionError::InstructionError(0, InstructionError::InvalidRealloc)
  2935. );
  2936. // Realloc to max twice
  2937. assert_eq!(
  2938. bank_client
  2939. .send_and_confirm_message(
  2940. signer,
  2941. Message::new(
  2942. &[
  2943. Instruction::new_with_bytes(
  2944. realloc_invoke_program_id,
  2945. &[INVOKE_REALLOC_MAX_TWICE],
  2946. vec![
  2947. AccountMeta::new(pubkey, false),
  2948. AccountMeta::new_readonly(realloc_program_id, false),
  2949. ],
  2950. ),
  2951. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2952. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  2953. ),
  2954. ],
  2955. Some(&mint_pubkey),
  2956. )
  2957. )
  2958. .unwrap_err()
  2959. .unwrap(),
  2960. TransactionError::InstructionError(0, InstructionError::InvalidRealloc)
  2961. );
  2962. // Realloc account to 0
  2963. bank_client
  2964. .send_and_confirm_message(
  2965. signer,
  2966. Message::new(
  2967. &[
  2968. realloc(&realloc_program_id, &pubkey, 0, &mut bump),
  2969. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2970. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2971. ),
  2972. ],
  2973. Some(&mint_pubkey),
  2974. ),
  2975. )
  2976. .unwrap();
  2977. let account = bank.get_account(&pubkey).unwrap();
  2978. assert_eq!(account.lamports(), START_BALANCE);
  2979. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  2980. assert_eq!(0, data.len());
  2981. // Realloc and assign
  2982. bank_client
  2983. .send_and_confirm_message(
  2984. signer,
  2985. Message::new(
  2986. &[
  2987. Instruction::new_with_bytes(
  2988. realloc_invoke_program_id,
  2989. &[INVOKE_REALLOC_AND_ASSIGN],
  2990. vec![
  2991. AccountMeta::new(pubkey, false),
  2992. AccountMeta::new_readonly(realloc_program_id, false),
  2993. ],
  2994. ),
  2995. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  2996. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  2997. ),
  2998. ],
  2999. Some(&mint_pubkey),
  3000. ),
  3001. )
  3002. .unwrap();
  3003. let account = bank.get_account(&pubkey).unwrap();
  3004. assert_eq!(&solana_system_interface::program::id(), account.owner());
  3005. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  3006. assert_eq!(MAX_PERMITTED_DATA_INCREASE, data.len());
  3007. // Realloc to 0 with wrong owner
  3008. assert_eq!(
  3009. bank_client
  3010. .send_and_confirm_message(
  3011. signer,
  3012. Message::new(
  3013. &[
  3014. realloc(&realloc_program_id, &pubkey, 0, &mut bump),
  3015. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3016. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  3017. ),
  3018. ],
  3019. Some(&mint_pubkey),
  3020. )
  3021. )
  3022. .unwrap_err()
  3023. .unwrap(),
  3024. TransactionError::InstructionError(0, InstructionError::AccountDataSizeChanged)
  3025. );
  3026. // realloc and assign to self via system program
  3027. assert_eq!(
  3028. bank_client
  3029. .send_and_confirm_message(
  3030. &[&mint_keypair, &keypair],
  3031. Message::new(
  3032. &[
  3033. Instruction::new_with_bytes(
  3034. realloc_invoke_program_id,
  3035. &[INVOKE_REALLOC_AND_ASSIGN_TO_SELF_VIA_SYSTEM_PROGRAM],
  3036. vec![
  3037. AccountMeta::new(pubkey, true),
  3038. AccountMeta::new_readonly(realloc_program_id, false),
  3039. AccountMeta::new_readonly(
  3040. solana_system_interface::program::id(),
  3041. false
  3042. ),
  3043. ],
  3044. ),
  3045. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3046. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  3047. ),
  3048. ],
  3049. Some(&mint_pubkey),
  3050. )
  3051. )
  3052. .unwrap_err()
  3053. .unwrap(),
  3054. TransactionError::InstructionError(0, InstructionError::AccountDataSizeChanged)
  3055. );
  3056. // Assign to self and realloc via system program
  3057. bank_client
  3058. .send_and_confirm_message(
  3059. &[&mint_keypair, &keypair],
  3060. Message::new(
  3061. &[
  3062. Instruction::new_with_bytes(
  3063. realloc_invoke_program_id,
  3064. &[INVOKE_ASSIGN_TO_SELF_VIA_SYSTEM_PROGRAM_AND_REALLOC],
  3065. vec![
  3066. AccountMeta::new(pubkey, true),
  3067. AccountMeta::new_readonly(realloc_program_id, false),
  3068. AccountMeta::new_readonly(
  3069. solana_system_interface::program::id(),
  3070. false,
  3071. ),
  3072. ],
  3073. ),
  3074. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3075. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  3076. ),
  3077. ],
  3078. Some(&mint_pubkey),
  3079. ),
  3080. )
  3081. .unwrap();
  3082. let account = bank.get_account(&pubkey).unwrap();
  3083. assert_eq!(&realloc_program_id, account.owner());
  3084. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  3085. assert_eq!(2 * MAX_PERMITTED_DATA_INCREASE, data.len());
  3086. // Realloc to 0
  3087. bank_client
  3088. .send_and_confirm_message(
  3089. signer,
  3090. Message::new(
  3091. &[
  3092. realloc(&realloc_program_id, &pubkey, 0, &mut bump),
  3093. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3094. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  3095. ),
  3096. ],
  3097. Some(&mint_pubkey),
  3098. ),
  3099. )
  3100. .unwrap();
  3101. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  3102. assert_eq!(0, data.len());
  3103. // Realloc to 100 and check via CPI
  3104. let invoke_account = AccountSharedData::new(START_BALANCE, 5, &realloc_invoke_program_id);
  3105. bank.store_account(&invoke_pubkey, &invoke_account);
  3106. bank_client
  3107. .send_and_confirm_message(
  3108. signer,
  3109. Message::new(
  3110. &[
  3111. Instruction::new_with_bytes(
  3112. realloc_invoke_program_id,
  3113. &[INVOKE_REALLOC_INVOKE_CHECK],
  3114. vec![
  3115. AccountMeta::new(invoke_pubkey, false),
  3116. AccountMeta::new_readonly(realloc_program_id, false),
  3117. ],
  3118. ),
  3119. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3120. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  3121. ),
  3122. ],
  3123. Some(&mint_pubkey),
  3124. ),
  3125. )
  3126. .unwrap();
  3127. let data = bank_client
  3128. .get_account_data(&invoke_pubkey)
  3129. .unwrap()
  3130. .unwrap();
  3131. assert_eq!(100, data.len());
  3132. for i in 0..5 {
  3133. assert_eq!(data[i], 0);
  3134. }
  3135. for i in 5..data.len() {
  3136. assert_eq!(data[i], 2);
  3137. }
  3138. // Create account, realloc, check
  3139. let new_keypair = Keypair::new();
  3140. let new_pubkey = new_keypair.pubkey().clone();
  3141. let mut instruction_data = vec![];
  3142. instruction_data.extend_from_slice(&[INVOKE_CREATE_ACCOUNT_REALLOC_CHECK, 1]);
  3143. instruction_data.extend_from_slice(&100_usize.to_le_bytes());
  3144. bank_client
  3145. .send_and_confirm_message(
  3146. &[&mint_keypair, &new_keypair],
  3147. Message::new(
  3148. &[
  3149. Instruction::new_with_bytes(
  3150. realloc_invoke_program_id,
  3151. &instruction_data,
  3152. vec![
  3153. AccountMeta::new(mint_pubkey, true),
  3154. AccountMeta::new(new_pubkey, true),
  3155. AccountMeta::new(solana_system_interface::program::id(), false),
  3156. AccountMeta::new_readonly(realloc_invoke_program_id, false),
  3157. ],
  3158. ),
  3159. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3160. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  3161. ),
  3162. ],
  3163. Some(&mint_pubkey),
  3164. ),
  3165. )
  3166. .unwrap();
  3167. let data = bank_client.get_account_data(&new_pubkey).unwrap().unwrap();
  3168. assert_eq!(200, data.len());
  3169. let account = bank.get_account(&new_pubkey).unwrap();
  3170. assert_eq!(&realloc_invoke_program_id, account.owner());
  3171. // Invoke, dealloc, and assign
  3172. let pre_len = 100;
  3173. let new_len = pre_len * 2;
  3174. let mut invoke_account = AccountSharedData::new(START_BALANCE, pre_len, &realloc_program_id);
  3175. invoke_account.set_data_from_slice(&vec![1; pre_len]);
  3176. bank.store_account(&invoke_pubkey, &invoke_account);
  3177. let mut instruction_data = vec![];
  3178. instruction_data.extend_from_slice(&[INVOKE_DEALLOC_AND_ASSIGN, 1]);
  3179. instruction_data.extend_from_slice(&pre_len.to_le_bytes());
  3180. bank_client
  3181. .send_and_confirm_message(
  3182. signer,
  3183. Message::new(
  3184. &[
  3185. Instruction::new_with_bytes(
  3186. realloc_invoke_program_id,
  3187. &instruction_data,
  3188. vec![
  3189. AccountMeta::new(invoke_pubkey, false),
  3190. AccountMeta::new_readonly(realloc_invoke_program_id, false),
  3191. AccountMeta::new_readonly(realloc_program_id, false),
  3192. ],
  3193. ),
  3194. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3195. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  3196. ),
  3197. ],
  3198. Some(&mint_pubkey),
  3199. ),
  3200. )
  3201. .unwrap();
  3202. let data = bank_client
  3203. .get_account_data(&invoke_pubkey)
  3204. .unwrap()
  3205. .unwrap();
  3206. assert_eq!(new_len, data.len());
  3207. for i in 0..new_len {
  3208. assert_eq!(data[i], 0);
  3209. }
  3210. // Realloc to max invoke max
  3211. let invoke_account = AccountSharedData::new(42, 0, &realloc_invoke_program_id);
  3212. bank.store_account(&invoke_pubkey, &invoke_account);
  3213. assert_eq!(
  3214. bank_client
  3215. .send_and_confirm_message(
  3216. signer,
  3217. Message::new(
  3218. &[
  3219. Instruction::new_with_bytes(
  3220. realloc_invoke_program_id,
  3221. &[INVOKE_REALLOC_MAX_INVOKE_MAX],
  3222. vec![
  3223. AccountMeta::new(invoke_pubkey, false),
  3224. AccountMeta::new_readonly(realloc_program_id, false),
  3225. ],
  3226. ),
  3227. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3228. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  3229. ),
  3230. ],
  3231. Some(&mint_pubkey),
  3232. )
  3233. )
  3234. .unwrap_err()
  3235. .unwrap(),
  3236. TransactionError::InstructionError(0, InstructionError::InvalidRealloc)
  3237. );
  3238. // CPI realloc extend then local realloc extend
  3239. for (cpi_extend_bytes, local_extend_bytes, should_succeed) in [
  3240. (0, 0, true),
  3241. (MAX_PERMITTED_DATA_INCREASE, 0, true),
  3242. (0, MAX_PERMITTED_DATA_INCREASE, true),
  3243. (MAX_PERMITTED_DATA_INCREASE, 1, false),
  3244. (1, MAX_PERMITTED_DATA_INCREASE, false),
  3245. ] {
  3246. let invoke_account = AccountSharedData::new(100_000_000, 0, &realloc_invoke_program_id);
  3247. bank.store_account(&invoke_pubkey, &invoke_account);
  3248. let mut instruction_data = vec![];
  3249. instruction_data.extend_from_slice(&[INVOKE_REALLOC_TO_THEN_LOCAL_REALLOC_EXTEND, 1]);
  3250. instruction_data.extend_from_slice(&cpi_extend_bytes.to_le_bytes());
  3251. instruction_data.extend_from_slice(&local_extend_bytes.to_le_bytes());
  3252. let result = bank_client.send_and_confirm_message(
  3253. signer,
  3254. Message::new(
  3255. &[
  3256. Instruction::new_with_bytes(
  3257. realloc_invoke_program_id,
  3258. &instruction_data,
  3259. vec![
  3260. AccountMeta::new(invoke_pubkey, false),
  3261. AccountMeta::new_readonly(realloc_invoke_program_id, false),
  3262. ],
  3263. ),
  3264. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3265. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  3266. ),
  3267. ],
  3268. Some(&mint_pubkey),
  3269. ),
  3270. );
  3271. if should_succeed {
  3272. assert!(
  3273. result.is_ok(),
  3274. "cpi: {cpi_extend_bytes} local: {local_extend_bytes}, err: {:?}",
  3275. result.err()
  3276. );
  3277. } else {
  3278. assert_eq!(
  3279. result.unwrap_err().unwrap(),
  3280. TransactionError::InstructionError(0, InstructionError::InvalidRealloc),
  3281. "cpi: {cpi_extend_bytes} local: {local_extend_bytes}",
  3282. );
  3283. }
  3284. }
  3285. // Realloc invoke max twice
  3286. let invoke_account = AccountSharedData::new(42, 0, &realloc_program_id);
  3287. bank.store_account(&invoke_pubkey, &invoke_account);
  3288. assert_eq!(
  3289. bank_client
  3290. .send_and_confirm_message(
  3291. signer,
  3292. Message::new(
  3293. &[
  3294. Instruction::new_with_bytes(
  3295. realloc_invoke_program_id,
  3296. &[INVOKE_INVOKE_MAX_TWICE],
  3297. vec![
  3298. AccountMeta::new(invoke_pubkey, false),
  3299. AccountMeta::new_readonly(realloc_invoke_program_id, false),
  3300. AccountMeta::new_readonly(realloc_program_id, false),
  3301. ],
  3302. ),
  3303. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3304. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  3305. ),
  3306. ],
  3307. Some(&mint_pubkey),
  3308. )
  3309. )
  3310. .unwrap_err()
  3311. .unwrap(),
  3312. TransactionError::InstructionError(0, InstructionError::InvalidRealloc)
  3313. );
  3314. // Realloc to 0
  3315. bank_client
  3316. .send_and_confirm_message(
  3317. signer,
  3318. Message::new(
  3319. &[realloc(&realloc_program_id, &pubkey, 0, &mut bump)],
  3320. Some(&mint_pubkey),
  3321. ),
  3322. )
  3323. .unwrap();
  3324. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  3325. assert_eq!(0, data.len());
  3326. // Realloc to max length in max increase increments
  3327. for i in 0..MAX_PERMITTED_DATA_LENGTH as usize / MAX_PERMITTED_DATA_INCREASE {
  3328. bank_client
  3329. .send_and_confirm_message(
  3330. signer,
  3331. Message::new(
  3332. &[
  3333. Instruction::new_with_bytes(
  3334. realloc_invoke_program_id,
  3335. &[INVOKE_REALLOC_EXTEND_MAX, 1, i as u8, (i / 255) as u8],
  3336. vec![
  3337. AccountMeta::new(pubkey, false),
  3338. AccountMeta::new_readonly(realloc_program_id, false),
  3339. ],
  3340. ),
  3341. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3342. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  3343. ),
  3344. ],
  3345. Some(&mint_pubkey),
  3346. ),
  3347. )
  3348. .unwrap();
  3349. let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
  3350. assert_eq!((i + 1) * MAX_PERMITTED_DATA_INCREASE, data.len());
  3351. }
  3352. for i in 0..data.len() {
  3353. assert_eq!(data[i], 1);
  3354. }
  3355. // and one more time should fail
  3356. assert_eq!(
  3357. bank_client
  3358. .send_and_confirm_message(
  3359. signer,
  3360. Message::new(
  3361. &[
  3362. Instruction::new_with_bytes(
  3363. realloc_invoke_program_id,
  3364. &[INVOKE_REALLOC_EXTEND_MAX, 2, 1, 1],
  3365. vec![
  3366. AccountMeta::new(pubkey, false),
  3367. AccountMeta::new_readonly(realloc_program_id, false),
  3368. ],
  3369. ),
  3370. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3371. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST
  3372. ),
  3373. ],
  3374. Some(&mint_pubkey),
  3375. )
  3376. )
  3377. .unwrap_err()
  3378. .unwrap(),
  3379. TransactionError::InstructionError(0, InstructionError::InvalidRealloc)
  3380. );
  3381. // Realloc recursively and fill data
  3382. let invoke_keypair = Keypair::new();
  3383. let invoke_pubkey = invoke_keypair.pubkey().clone();
  3384. let invoke_account = AccountSharedData::new(START_BALANCE, 0, &realloc_invoke_program_id);
  3385. bank.store_account(&invoke_pubkey, &invoke_account);
  3386. let mut instruction_data = vec![];
  3387. instruction_data.extend_from_slice(&[INVOKE_REALLOC_RECURSIVE, 1]);
  3388. instruction_data.extend_from_slice(&100_usize.to_le_bytes());
  3389. bank_client
  3390. .send_and_confirm_message(
  3391. signer,
  3392. Message::new(
  3393. &[
  3394. Instruction::new_with_bytes(
  3395. realloc_invoke_program_id,
  3396. &instruction_data,
  3397. vec![
  3398. AccountMeta::new(invoke_pubkey, false),
  3399. AccountMeta::new_readonly(realloc_invoke_program_id, false),
  3400. ],
  3401. ),
  3402. ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(
  3403. LOADED_ACCOUNTS_DATA_SIZE_LIMIT_FOR_TEST,
  3404. ),
  3405. ],
  3406. Some(&mint_pubkey),
  3407. ),
  3408. )
  3409. .unwrap();
  3410. let data = bank_client
  3411. .get_account_data(&invoke_pubkey)
  3412. .unwrap()
  3413. .unwrap();
  3414. assert_eq!(200, data.len());
  3415. for i in 0..100 {
  3416. assert_eq!(data[i], 1);
  3417. }
  3418. for i in 100..200 {
  3419. assert_eq!(data[i], 2);
  3420. }
  3421. }
  3422. #[test]
  3423. #[cfg(feature = "sbf_rust")]
  3424. fn test_program_sbf_processed_inner_instruction() {
  3425. agave_logger::setup();
  3426. let GenesisConfigInfo {
  3427. genesis_config,
  3428. mint_keypair,
  3429. ..
  3430. } = create_genesis_config(50);
  3431. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  3432. let mut bank_client = BankClient::new_shared(bank.clone());
  3433. let authority_keypair = Keypair::new();
  3434. let (_bank, sibling_program_id) = load_program_of_loader_v4(
  3435. &mut bank_client,
  3436. &bank_forks,
  3437. &mint_keypair,
  3438. &authority_keypair,
  3439. "solana_sbf_rust_sibling_instructions",
  3440. );
  3441. let (_bank, sibling_inner_program_id) = load_program_of_loader_v4(
  3442. &mut bank_client,
  3443. &bank_forks,
  3444. &mint_keypair,
  3445. &authority_keypair,
  3446. "solana_sbf_rust_sibling_inner_instructions",
  3447. );
  3448. let (_bank, noop_program_id) = load_program_of_loader_v4(
  3449. &mut bank_client,
  3450. &bank_forks,
  3451. &mint_keypair,
  3452. &authority_keypair,
  3453. "solana_sbf_rust_noop",
  3454. );
  3455. let (_bank, invoke_and_return_program_id) = load_program_of_loader_v4(
  3456. &mut bank_client,
  3457. &bank_forks,
  3458. &mint_keypair,
  3459. &authority_keypair,
  3460. "solana_sbf_rust_invoke_and_return",
  3461. );
  3462. let instruction2 = Instruction::new_with_bytes(
  3463. noop_program_id,
  3464. &[43],
  3465. vec![
  3466. AccountMeta::new_readonly(noop_program_id, false),
  3467. AccountMeta::new(mint_keypair.pubkey(), true),
  3468. ],
  3469. );
  3470. let instruction1 = Instruction::new_with_bytes(
  3471. noop_program_id,
  3472. &[42],
  3473. vec![
  3474. AccountMeta::new(mint_keypair.pubkey(), true),
  3475. AccountMeta::new_readonly(noop_program_id, false),
  3476. ],
  3477. );
  3478. let instruction0 = Instruction::new_with_bytes(
  3479. sibling_program_id,
  3480. &[1, 2, 3, 0, 4, 5, 6],
  3481. vec![
  3482. AccountMeta::new(mint_keypair.pubkey(), true),
  3483. AccountMeta::new_readonly(noop_program_id, false),
  3484. AccountMeta::new_readonly(invoke_and_return_program_id, false),
  3485. AccountMeta::new_readonly(sibling_inner_program_id, false),
  3486. ],
  3487. );
  3488. let message = Message::new(
  3489. &[instruction2, instruction1, instruction0],
  3490. Some(&mint_keypair.pubkey()),
  3491. );
  3492. assert!(bank_client
  3493. .send_and_confirm_message(&[&mint_keypair], message)
  3494. .is_ok());
  3495. }
  3496. #[test]
  3497. #[cfg(feature = "sbf_rust")]
  3498. fn test_program_fees() {
  3499. agave_logger::setup();
  3500. let congestion_multiplier = 1;
  3501. let GenesisConfigInfo {
  3502. mut genesis_config,
  3503. mint_keypair,
  3504. ..
  3505. } = create_genesis_config(500_000_000);
  3506. genesis_config.fee_rate_governor = FeeRateGovernor::new(congestion_multiplier, 0);
  3507. let mut bank = Bank::new_for_tests(&genesis_config);
  3508. let fee_structure = FeeStructure {
  3509. lamports_per_signature: 5000,
  3510. lamports_per_write_lock: 0,
  3511. compute_fee_bins: vec![
  3512. FeeBin {
  3513. limit: 200,
  3514. fee: 500,
  3515. },
  3516. FeeBin {
  3517. limit: 1400000,
  3518. fee: 5000,
  3519. },
  3520. ],
  3521. };
  3522. bank.set_fee_structure(&fee_structure);
  3523. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  3524. let feature_set = bank.feature_set.clone();
  3525. let mut bank_client = BankClient::new_shared(bank.clone());
  3526. let authority_keypair = Keypair::new();
  3527. let (_bank, program_id) = load_program_of_loader_v4(
  3528. &mut bank_client,
  3529. &bank_forks,
  3530. &mint_keypair,
  3531. &authority_keypair,
  3532. "solana_sbf_rust_noop",
  3533. );
  3534. let pre_balance = bank_client.get_balance(&mint_keypair.pubkey()).unwrap();
  3535. let message = Message::new(
  3536. &[Instruction::new_with_bytes(program_id, &[], vec![])],
  3537. Some(&mint_keypair.pubkey()),
  3538. );
  3539. let sanitized_message = SanitizedMessage::try_from_legacy_message(
  3540. message.clone(),
  3541. &ReservedAccountKeys::empty_key_set(),
  3542. )
  3543. .unwrap();
  3544. let fee_budget_limits = FeeBudgetLimits::from(
  3545. process_compute_budget_instructions(
  3546. SVMStaticMessage::program_instructions_iter(&sanitized_message),
  3547. &feature_set,
  3548. )
  3549. .unwrap_or_default(),
  3550. );
  3551. let expected_normal_fee = solana_fee::calculate_fee(
  3552. &sanitized_message,
  3553. congestion_multiplier == 0,
  3554. fee_structure.lamports_per_signature,
  3555. fee_budget_limits.prioritization_fee,
  3556. bank.feature_set.as_ref().into(),
  3557. );
  3558. bank_client
  3559. .send_and_confirm_message(&[&mint_keypair], message)
  3560. .unwrap();
  3561. let post_balance = bank_client.get_balance(&mint_keypair.pubkey()).unwrap();
  3562. assert_eq!(pre_balance - post_balance, expected_normal_fee);
  3563. let pre_balance = bank_client.get_balance(&mint_keypair.pubkey()).unwrap();
  3564. let message = Message::new(
  3565. &[
  3566. ComputeBudgetInstruction::set_compute_unit_price(1),
  3567. Instruction::new_with_bytes(program_id, &[], vec![]),
  3568. ],
  3569. Some(&mint_keypair.pubkey()),
  3570. );
  3571. let sanitized_message = SanitizedMessage::try_from_legacy_message(
  3572. message.clone(),
  3573. &ReservedAccountKeys::empty_key_set(),
  3574. )
  3575. .unwrap();
  3576. let fee_budget_limits = FeeBudgetLimits::from(
  3577. process_compute_budget_instructions(
  3578. SVMStaticMessage::program_instructions_iter(&sanitized_message),
  3579. &feature_set,
  3580. )
  3581. .unwrap_or_default(),
  3582. );
  3583. let expected_prioritized_fee = solana_fee::calculate_fee(
  3584. &sanitized_message,
  3585. congestion_multiplier == 0,
  3586. fee_structure.lamports_per_signature,
  3587. fee_budget_limits.prioritization_fee,
  3588. bank.feature_set.as_ref().into(),
  3589. );
  3590. assert!(expected_normal_fee < expected_prioritized_fee);
  3591. bank_client
  3592. .send_and_confirm_message(&[&mint_keypair], message)
  3593. .unwrap();
  3594. let post_balance = bank_client.get_balance(&mint_keypair.pubkey()).unwrap();
  3595. assert_eq!(pre_balance - post_balance, expected_prioritized_fee);
  3596. }
  3597. #[test]
  3598. #[cfg(feature = "sbf_rust")]
  3599. fn test_program_sbf_inner_instruction_alignment_checks() {
  3600. agave_logger::setup();
  3601. let GenesisConfigInfo {
  3602. genesis_config,
  3603. mint_keypair,
  3604. ..
  3605. } = create_genesis_config(50);
  3606. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  3607. let noop = create_program(&bank, &bpf_loader_deprecated::id(), "solana_sbf_rust_noop");
  3608. let inner_instruction_alignment_check = create_program(
  3609. &bank,
  3610. &bpf_loader_deprecated::id(),
  3611. "solana_sbf_rust_inner_instruction_alignment_check",
  3612. );
  3613. // invoke unaligned program, which will call aligned program twice,
  3614. // unaligned should be allowed once invoke completes
  3615. let mut bank_client = BankClient::new_shared(bank);
  3616. bank_client
  3617. .advance_slot(1, bank_forks.as_ref(), &Pubkey::default())
  3618. .expect("Failed to advance the slot");
  3619. let mut instruction = Instruction::new_with_bytes(
  3620. inner_instruction_alignment_check,
  3621. &[0],
  3622. vec![
  3623. AccountMeta::new_readonly(noop, false),
  3624. AccountMeta::new_readonly(mint_keypair.pubkey(), false),
  3625. ],
  3626. );
  3627. instruction.data[0] += 1;
  3628. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction.clone());
  3629. assert!(result.is_ok(), "{result:?}");
  3630. }
  3631. #[test]
  3632. #[cfg(feature = "sbf_rust")]
  3633. fn test_cpi_account_ownership_writability() {
  3634. agave_logger::setup();
  3635. for stricter_abi_and_runtime_constraints in [false, true] {
  3636. let GenesisConfigInfo {
  3637. genesis_config,
  3638. mint_keypair,
  3639. ..
  3640. } = create_genesis_config(100_123_456_789);
  3641. let mut bank = Bank::new_for_tests(&genesis_config);
  3642. let mut feature_set = FeatureSet::all_enabled();
  3643. if !stricter_abi_and_runtime_constraints {
  3644. feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
  3645. feature_set.deactivate(&feature_set::account_data_direct_mapping::id());
  3646. }
  3647. bank.feature_set = Arc::new(feature_set);
  3648. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  3649. let mut bank_client = BankClient::new_shared(bank);
  3650. let authority_keypair = Keypair::new();
  3651. let (_bank, invoke_program_id) = load_program_of_loader_v4(
  3652. &mut bank_client,
  3653. &bank_forks,
  3654. &mint_keypair,
  3655. &authority_keypair,
  3656. "solana_sbf_rust_invoke",
  3657. );
  3658. let (_bank, invoked_program_id) = load_program_of_loader_v4(
  3659. &mut bank_client,
  3660. &bank_forks,
  3661. &mint_keypair,
  3662. &authority_keypair,
  3663. "solana_sbf_rust_invoked",
  3664. );
  3665. let (bank, realloc_program_id) = load_program_of_loader_v4(
  3666. &mut bank_client,
  3667. &bank_forks,
  3668. &mint_keypair,
  3669. &authority_keypair,
  3670. "solana_sbf_rust_realloc",
  3671. );
  3672. let account_keypair = Keypair::new();
  3673. let mint_pubkey = mint_keypair.pubkey();
  3674. let account_metas = vec![
  3675. AccountMeta::new(mint_pubkey, true),
  3676. AccountMeta::new(account_keypair.pubkey(), false),
  3677. AccountMeta::new_readonly(invoked_program_id, false),
  3678. AccountMeta::new_readonly(invoke_program_id, false),
  3679. AccountMeta::new_readonly(realloc_program_id, false),
  3680. ];
  3681. for (account_size, byte_index) in [
  3682. (0, 0), // first realloc byte
  3683. (0, MAX_PERMITTED_DATA_INCREASE - 1), // last realloc byte
  3684. (2, 0), // first data byte
  3685. (2, 1), // last data byte
  3686. (2, 3), // first realloc byte
  3687. (2, 2 + MAX_PERMITTED_DATA_INCREASE - 1), // last realloc byte
  3688. ] {
  3689. for instruction_id in [
  3690. TEST_FORBID_WRITE_AFTER_OWNERSHIP_CHANGE_IN_CALLEE,
  3691. TEST_FORBID_WRITE_AFTER_OWNERSHIP_CHANGE_IN_CALLER,
  3692. ] {
  3693. bank.register_unique_recent_blockhash_for_test();
  3694. let account = AccountSharedData::new(42, account_size, &invoke_program_id);
  3695. bank.store_account(&account_keypair.pubkey(), &account);
  3696. let mut instruction_data = vec![instruction_id];
  3697. instruction_data.extend_from_slice(byte_index.to_le_bytes().as_ref());
  3698. let instruction = Instruction::new_with_bytes(
  3699. invoke_program_id,
  3700. &instruction_data,
  3701. account_metas.clone(),
  3702. );
  3703. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  3704. if (byte_index as usize) < account_size || stricter_abi_and_runtime_constraints {
  3705. assert_eq!(
  3706. result.unwrap_err().unwrap(),
  3707. TransactionError::InstructionError(
  3708. 0,
  3709. InstructionError::ExternalAccountDataModified,
  3710. )
  3711. );
  3712. } else {
  3713. // without stricter_abi_and_runtime_constraints, changes to the realloc padding
  3714. // outside the account length are ignored
  3715. assert!(result.is_ok(), "{result:?}");
  3716. }
  3717. }
  3718. }
  3719. // Test that the CPI code that updates `ref_to_len_in_vm` fails if we
  3720. // make it write to an invalid location. This is the first variant which
  3721. // correctly triggers ExternalAccountDataModified when stricter_abi_and_runtime_constraints is
  3722. // disabled. When stricter_abi_and_runtime_constraints is enabled this tests fails early
  3723. // because we move the account data pointer.
  3724. // TEST_FORBID_LEN_UPDATE_AFTER_OWNERSHIP_CHANGE is able to make more
  3725. // progress when stricter_abi_and_runtime_constraints is on.
  3726. let account = AccountSharedData::new(42, 0, &invoke_program_id);
  3727. bank.store_account(&account_keypair.pubkey(), &account);
  3728. let instruction_data = vec![
  3729. TEST_FORBID_LEN_UPDATE_AFTER_OWNERSHIP_CHANGE_MOVING_DATA_POINTER,
  3730. 42,
  3731. 42,
  3732. 42,
  3733. ];
  3734. let instruction = Instruction::new_with_bytes(
  3735. invoke_program_id,
  3736. &instruction_data,
  3737. account_metas.clone(),
  3738. );
  3739. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  3740. assert_eq!(
  3741. result.unwrap_err().unwrap(),
  3742. if stricter_abi_and_runtime_constraints {
  3743. // We move the data pointer, stricter_abi_and_runtime_constraints doesn't allow it
  3744. // anymore so it errors out earlier. See
  3745. // test_cpi_invalid_account_info_pointers.
  3746. TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete)
  3747. } else {
  3748. // We managed to make CPI write into the account data, but the
  3749. // usual checks still apply and we get an error.
  3750. TransactionError::InstructionError(0, InstructionError::ExternalAccountDataModified)
  3751. }
  3752. );
  3753. // We're going to try and make CPI write ref_to_len_in_vm into a 2nd
  3754. // account, so we add an extra one here.
  3755. let account2_keypair = Keypair::new();
  3756. let mut account_metas = account_metas.clone();
  3757. account_metas.push(AccountMeta::new(account2_keypair.pubkey(), false));
  3758. for target_account in [1, account_metas.len() as u8 - 1] {
  3759. // Similar to the test above where we try to make CPI write into account
  3760. // data. This variant is for when stricter_abi_and_runtime_constraints is enabled.
  3761. let account = AccountSharedData::new(42, 0, &invoke_program_id);
  3762. bank.store_account(&account_keypair.pubkey(), &account);
  3763. let account = AccountSharedData::new(42, 0, &invoke_program_id);
  3764. bank.store_account(&account2_keypair.pubkey(), &account);
  3765. let instruction_data = vec![
  3766. TEST_FORBID_LEN_UPDATE_AFTER_OWNERSHIP_CHANGE,
  3767. target_account,
  3768. 42,
  3769. 42,
  3770. ];
  3771. let instruction = Instruction::new_with_bytes(
  3772. invoke_program_id,
  3773. &instruction_data,
  3774. account_metas.clone(),
  3775. );
  3776. let message = Message::new(&[instruction], Some(&mint_pubkey));
  3777. let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
  3778. let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
  3779. if stricter_abi_and_runtime_constraints {
  3780. assert_eq!(
  3781. result.unwrap_err(),
  3782. TransactionError::InstructionError(
  3783. 0,
  3784. InstructionError::ProgramFailedToComplete
  3785. )
  3786. );
  3787. // We haven't moved the data pointer, but ref_to_len_vm _is_ in
  3788. // the account data vm range and that's not allowed either.
  3789. assert!(
  3790. logs.iter().any(|log| log.contains("Invalid pointer")),
  3791. "{logs:?}"
  3792. );
  3793. } else {
  3794. // we expect this to succeed as after updating `ref_to_len_in_vm`,
  3795. // CPI will sync the actual account data between the callee and the
  3796. // caller, _always_ writing over the location pointed by
  3797. // `ref_to_len_in_vm`. To verify this, we check that the account
  3798. // data is in fact all zeroes like it is in the callee.
  3799. result.unwrap();
  3800. let account = bank.get_account(&account_keypair.pubkey()).unwrap();
  3801. assert_eq!(account.data(), vec![0; 40]);
  3802. }
  3803. }
  3804. // Test that the caller can write to an account which it received from the callee
  3805. let account = AccountSharedData::new(42, 0, &invoked_program_id);
  3806. bank.store_account(&account_keypair.pubkey(), &account);
  3807. let instruction_data = vec![TEST_ALLOW_WRITE_AFTER_OWNERSHIP_CHANGE_TO_CALLER, 1, 42, 42];
  3808. let instruction =
  3809. Instruction::new_with_bytes(invoke_program_id, &instruction_data, account_metas);
  3810. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  3811. result.unwrap();
  3812. }
  3813. }
  3814. #[test]
  3815. #[cfg(feature = "sbf_rust")]
  3816. fn test_cpi_account_data_updates() {
  3817. agave_logger::setup();
  3818. for (deprecated_callee, deprecated_caller, stricter_abi_and_runtime_constraints) in
  3819. [false, true].into_iter().flat_map(move |z| {
  3820. [false, true]
  3821. .into_iter()
  3822. .flat_map(move |y| [false, true].into_iter().map(move |x| (x, y, z)))
  3823. })
  3824. {
  3825. let GenesisConfigInfo {
  3826. genesis_config,
  3827. mint_keypair,
  3828. ..
  3829. } = create_genesis_config(100_123_456_789);
  3830. let mut bank = Bank::new_for_tests(&genesis_config);
  3831. let mut feature_set = FeatureSet::all_enabled();
  3832. if !stricter_abi_and_runtime_constraints {
  3833. feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
  3834. feature_set.deactivate(&feature_set::account_data_direct_mapping::id());
  3835. }
  3836. bank.feature_set = Arc::new(feature_set);
  3837. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  3838. let mut bank_client = BankClient::new_shared(bank);
  3839. let authority_keypair = Keypair::new();
  3840. let (_bank, invoke_program_id) = load_program_of_loader_v4(
  3841. &mut bank_client,
  3842. &bank_forks,
  3843. &mint_keypair,
  3844. &authority_keypair,
  3845. "solana_sbf_rust_invoke",
  3846. );
  3847. let (bank, realloc_program_id) = load_program_of_loader_v4(
  3848. &mut bank_client,
  3849. &bank_forks,
  3850. &mint_keypair,
  3851. &authority_keypair,
  3852. "solana_sbf_rust_realloc",
  3853. );
  3854. let deprecated_program_id = create_program(
  3855. &bank,
  3856. &bpf_loader_deprecated::id(),
  3857. "solana_sbf_rust_deprecated_loader",
  3858. );
  3859. let account_keypair = Keypair::new();
  3860. let mint_pubkey = mint_keypair.pubkey();
  3861. let account_metas = vec![
  3862. AccountMeta::new(mint_pubkey, true),
  3863. AccountMeta::new(account_keypair.pubkey(), false),
  3864. AccountMeta::new_readonly(
  3865. if deprecated_callee {
  3866. deprecated_program_id
  3867. } else {
  3868. realloc_program_id
  3869. },
  3870. false,
  3871. ),
  3872. AccountMeta::new_readonly(
  3873. if deprecated_caller {
  3874. deprecated_program_id
  3875. } else {
  3876. invoke_program_id
  3877. },
  3878. false,
  3879. ),
  3880. ];
  3881. // This tests the case where a caller extends an account beyond the original
  3882. // data length. The callee should see the extended data (asserted in the
  3883. // callee program, not here).
  3884. let mut account = AccountSharedData::new(42, 0, &account_metas[3].pubkey);
  3885. account.set_data(b"foo".to_vec());
  3886. bank.store_account(&account_keypair.pubkey(), &account);
  3887. let mut instruction_data = vec![TEST_CPI_ACCOUNT_UPDATE_CALLER_GROWS];
  3888. instruction_data.extend_from_slice(b"bar");
  3889. let instruction = Instruction::new_with_bytes(
  3890. account_metas[3].pubkey,
  3891. &instruction_data,
  3892. account_metas.clone(),
  3893. );
  3894. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  3895. if deprecated_caller {
  3896. assert_eq!(
  3897. result.unwrap_err().unwrap(),
  3898. TransactionError::InstructionError(
  3899. 0,
  3900. if stricter_abi_and_runtime_constraints {
  3901. InstructionError::ProgramFailedToComplete
  3902. } else {
  3903. InstructionError::ModifiedProgramId
  3904. }
  3905. )
  3906. );
  3907. } else {
  3908. assert!(result.is_ok(), "{result:?}");
  3909. let account = bank.get_account(&account_keypair.pubkey()).unwrap();
  3910. // "bar" here was copied from the realloc region
  3911. assert_eq!(account.data(), b"foobar");
  3912. }
  3913. // This tests the case where a callee extends an account beyond the original
  3914. // data length. The caller should see the extended data where the realloc
  3915. // region contains the new data. In this test the callee owns the account,
  3916. // the caller can't write but the CPI glue still updates correctly.
  3917. let mut account = AccountSharedData::new(42, 0, &account_metas[2].pubkey);
  3918. account.set_data(b"foo".to_vec());
  3919. bank.store_account(&account_keypair.pubkey(), &account);
  3920. let mut instruction_data = vec![TEST_CPI_ACCOUNT_UPDATE_CALLEE_GROWS];
  3921. instruction_data.extend_from_slice(b"bar");
  3922. let instruction = Instruction::new_with_bytes(
  3923. account_metas[3].pubkey,
  3924. &instruction_data,
  3925. account_metas.clone(),
  3926. );
  3927. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  3928. if deprecated_callee {
  3929. assert!(result.is_ok(), "{result:?}");
  3930. let account = bank.get_account(&account_keypair.pubkey()).unwrap();
  3931. // deprecated_callee is incapable of resizing accounts
  3932. assert_eq!(account.data(), b"foo");
  3933. } else if deprecated_caller {
  3934. assert_eq!(
  3935. result.unwrap_err().unwrap(),
  3936. TransactionError::InstructionError(
  3937. 0,
  3938. if stricter_abi_and_runtime_constraints {
  3939. InstructionError::InvalidRealloc
  3940. } else {
  3941. InstructionError::AccountDataSizeChanged
  3942. }
  3943. )
  3944. );
  3945. } else {
  3946. assert!(result.is_ok(), "{result:?}");
  3947. let account = bank.get_account(&account_keypair.pubkey()).unwrap();
  3948. // "bar" here was copied from the realloc region
  3949. assert_eq!(account.data(), b"foobar");
  3950. }
  3951. // This tests the case where a callee shrinks an account, the caller data
  3952. // slice must be truncated accordingly and post_len..original_data_len must
  3953. // be zeroed (zeroing is checked in the invoked program not here). Same as
  3954. // above, the callee owns the account but the changes are still reflected in
  3955. // the caller even if things are readonly from the caller's POV.
  3956. let mut account = AccountSharedData::new(42, 0, &account_metas[2].pubkey);
  3957. account.set_data(b"foobar".to_vec());
  3958. bank.store_account(&account_keypair.pubkey(), &account);
  3959. let mut instruction_data = vec![
  3960. TEST_CPI_ACCOUNT_UPDATE_CALLEE_SHRINKS_SMALLER_THAN_ORIGINAL_LEN,
  3961. stricter_abi_and_runtime_constraints as u8,
  3962. ];
  3963. instruction_data.extend_from_slice(4usize.to_le_bytes().as_ref());
  3964. let instruction = Instruction::new_with_bytes(
  3965. account_metas[3].pubkey,
  3966. &instruction_data,
  3967. account_metas.clone(),
  3968. );
  3969. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  3970. if deprecated_callee {
  3971. assert!(result.is_ok(), "{result:?}");
  3972. let account = bank.get_account(&account_keypair.pubkey()).unwrap();
  3973. // deprecated_callee is incapable of resizing accounts
  3974. assert_eq!(account.data(), b"foobar");
  3975. } else if deprecated_caller {
  3976. assert_eq!(
  3977. result.unwrap_err().unwrap(),
  3978. TransactionError::InstructionError(
  3979. 0,
  3980. if stricter_abi_and_runtime_constraints && deprecated_callee {
  3981. InstructionError::InvalidRealloc
  3982. } else {
  3983. InstructionError::AccountDataSizeChanged
  3984. }
  3985. )
  3986. );
  3987. } else {
  3988. assert!(result.is_ok(), "{result:?}");
  3989. let account = bank.get_account(&account_keypair.pubkey()).unwrap();
  3990. assert_eq!(account.data(), b"foob");
  3991. }
  3992. // This tests the case where the program extends an account, then calls
  3993. // itself and in the inner call it shrinks the account to a size that is
  3994. // still larger than the original size. The account data must be set to the
  3995. // correct value in the caller frame, and the realloc region must be zeroed
  3996. // (again tested in the invoked program).
  3997. let mut account = AccountSharedData::new(42, 0, &account_metas[3].pubkey);
  3998. account.set_data(b"foo".to_vec());
  3999. bank.store_account(&account_keypair.pubkey(), &account);
  4000. let mut instruction_data = vec![
  4001. TEST_CPI_ACCOUNT_UPDATE_CALLER_GROWS_CALLEE_SHRINKS,
  4002. stricter_abi_and_runtime_constraints as u8,
  4003. ];
  4004. // realloc to "foobazbad" then shrink to "foobazb"
  4005. instruction_data.extend_from_slice(7usize.to_le_bytes().as_ref());
  4006. instruction_data.extend_from_slice(b"bazbad");
  4007. let instruction = Instruction::new_with_bytes(
  4008. account_metas[3].pubkey,
  4009. &instruction_data,
  4010. account_metas.clone(),
  4011. );
  4012. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  4013. if deprecated_caller {
  4014. assert_eq!(
  4015. result.unwrap_err().unwrap(),
  4016. TransactionError::InstructionError(
  4017. 0,
  4018. if stricter_abi_and_runtime_constraints {
  4019. InstructionError::ProgramFailedToComplete
  4020. } else {
  4021. InstructionError::ModifiedProgramId
  4022. }
  4023. )
  4024. );
  4025. } else {
  4026. assert!(result.is_ok(), "{result:?}");
  4027. let account = bank.get_account(&account_keypair.pubkey()).unwrap();
  4028. assert_eq!(account.data(), b"foobazb");
  4029. }
  4030. // Similar to the test above, but this time the nested invocation shrinks to
  4031. // _below_ the original data length. Both the spare capacity in the account
  4032. // data _end_ the realloc region must be zeroed.
  4033. let mut account = AccountSharedData::new(42, 0, &account_metas[3].pubkey);
  4034. account.set_data(b"foo".to_vec());
  4035. bank.store_account(&account_keypair.pubkey(), &account);
  4036. let mut instruction_data = vec![
  4037. TEST_CPI_ACCOUNT_UPDATE_CALLER_GROWS_CALLEE_SHRINKS,
  4038. stricter_abi_and_runtime_constraints as u8,
  4039. ];
  4040. // realloc to "foobazbad" then shrink to "f"
  4041. instruction_data.extend_from_slice(1usize.to_le_bytes().as_ref());
  4042. instruction_data.extend_from_slice(b"bazbad");
  4043. let instruction = Instruction::new_with_bytes(
  4044. account_metas[3].pubkey,
  4045. &instruction_data,
  4046. account_metas.clone(),
  4047. );
  4048. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  4049. if deprecated_caller {
  4050. assert_eq!(
  4051. result.unwrap_err().unwrap(),
  4052. TransactionError::InstructionError(
  4053. 0,
  4054. if stricter_abi_and_runtime_constraints {
  4055. InstructionError::ProgramFailedToComplete
  4056. } else {
  4057. InstructionError::ModifiedProgramId
  4058. }
  4059. )
  4060. );
  4061. } else {
  4062. assert!(result.is_ok(), "{result:?}");
  4063. let account = bank.get_account(&account_keypair.pubkey()).unwrap();
  4064. assert_eq!(account.data(), b"f");
  4065. }
  4066. }
  4067. }
  4068. #[test]
  4069. #[cfg(any(feature = "sbf_c", feature = "sbf_rust"))]
  4070. fn test_cpi_invalid_account_info_pointers() {
  4071. agave_logger::setup();
  4072. let GenesisConfigInfo {
  4073. genesis_config,
  4074. mint_keypair,
  4075. ..
  4076. } = create_genesis_config(100_123_456_789);
  4077. let bank = Bank::new_for_tests(&genesis_config);
  4078. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  4079. let mut bank_client = BankClient::new_shared(bank);
  4080. let authority_keypair = Keypair::new();
  4081. let account_keypair = Keypair::new();
  4082. let mint_pubkey = mint_keypair.pubkey();
  4083. let mut account_metas = vec![
  4084. AccountMeta::new(mint_pubkey, true),
  4085. AccountMeta::new(account_keypair.pubkey(), false),
  4086. ];
  4087. let mut program_ids: Vec<Pubkey> = Vec::with_capacity(2);
  4088. #[allow(unused_mut)]
  4089. let mut bank;
  4090. #[cfg(feature = "sbf_rust")]
  4091. {
  4092. let (new_bank, invoke_program_id) = load_program_of_loader_v4(
  4093. &mut bank_client,
  4094. &bank_forks,
  4095. &mint_keypair,
  4096. &authority_keypair,
  4097. "solana_sbf_rust_invoke",
  4098. );
  4099. account_metas.push(AccountMeta::new_readonly(invoke_program_id, false));
  4100. program_ids.push(invoke_program_id);
  4101. #[allow(unused)]
  4102. {
  4103. bank = new_bank;
  4104. }
  4105. }
  4106. #[cfg(feature = "sbf_c")]
  4107. {
  4108. let (new_bank, c_invoke_program_id) = load_program_of_loader_v4(
  4109. &mut bank_client,
  4110. &bank_forks,
  4111. &mint_keypair,
  4112. &authority_keypair,
  4113. "invoke",
  4114. );
  4115. account_metas.push(AccountMeta::new_readonly(c_invoke_program_id, false));
  4116. program_ids.push(c_invoke_program_id);
  4117. #[allow(unused)]
  4118. {
  4119. bank = new_bank;
  4120. }
  4121. }
  4122. for invoke_program_id in &program_ids {
  4123. for ix in [
  4124. TEST_CPI_INVALID_KEY_POINTER,
  4125. TEST_CPI_INVALID_LAMPORTS_POINTER,
  4126. TEST_CPI_INVALID_OWNER_POINTER,
  4127. TEST_CPI_INVALID_DATA_POINTER,
  4128. ] {
  4129. let account = AccountSharedData::new(42, 5, invoke_program_id);
  4130. bank.store_account(&account_keypair.pubkey(), &account);
  4131. let instruction = Instruction::new_with_bytes(
  4132. *invoke_program_id,
  4133. &[ix, 42, 42, 42],
  4134. account_metas.clone(),
  4135. );
  4136. let message = Message::new(&[instruction], Some(&mint_pubkey));
  4137. let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
  4138. let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
  4139. assert!(result.is_err(), "{result:?}");
  4140. assert!(
  4141. logs.iter().any(|log| log.contains("Invalid pointer")),
  4142. "{logs:?}"
  4143. );
  4144. }
  4145. }
  4146. }
  4147. #[test]
  4148. #[cfg(feature = "sbf_rust")]
  4149. fn test_deplete_cost_meter_with_access_violation() {
  4150. agave_logger::setup();
  4151. let GenesisConfigInfo {
  4152. genesis_config,
  4153. mint_keypair,
  4154. ..
  4155. } = create_genesis_config(100_123_456_789);
  4156. let bank = Bank::new_for_tests(&genesis_config);
  4157. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  4158. let mut bank_client = BankClient::new_shared(bank.clone());
  4159. let authority_keypair = Keypair::new();
  4160. let (bank, invoke_program_id) = load_program_of_loader_v4(
  4161. &mut bank_client,
  4162. bank_forks.as_ref(),
  4163. &mint_keypair,
  4164. &authority_keypair,
  4165. "solana_sbf_rust_invoke",
  4166. );
  4167. let account_keypair = Keypair::new();
  4168. let mint_pubkey = mint_keypair.pubkey();
  4169. let account_metas = vec![
  4170. AccountMeta::new(mint_pubkey, true),
  4171. AccountMeta::new(account_keypair.pubkey(), false),
  4172. AccountMeta::new_readonly(invoke_program_id, false),
  4173. ];
  4174. let mut instruction_data = vec![TEST_WRITE_ACCOUNT, 2];
  4175. instruction_data.extend_from_slice(3usize.to_le_bytes().as_ref());
  4176. instruction_data.push(42);
  4177. let instruction =
  4178. Instruction::new_with_bytes(invoke_program_id, &instruction_data, account_metas.clone());
  4179. let compute_unit_limit = 10_000u32;
  4180. let message = Message::new(
  4181. &[
  4182. ComputeBudgetInstruction::set_compute_unit_limit(compute_unit_limit),
  4183. instruction,
  4184. ],
  4185. Some(&mint_keypair.pubkey()),
  4186. );
  4187. let tx = Transaction::new(&[&mint_keypair], message, bank.last_blockhash());
  4188. let result = load_execute_and_commit_transaction(&bank, tx).unwrap();
  4189. assert_eq!(
  4190. result.status.unwrap_err(),
  4191. TransactionError::InstructionError(1, InstructionError::ReadonlyDataModified)
  4192. );
  4193. // all compute unit limit should be consumed due to SBF VM error
  4194. assert_eq!(result.executed_units, u64::from(compute_unit_limit));
  4195. }
  4196. #[test]
  4197. #[cfg(feature = "sbf_rust")]
  4198. fn test_program_sbf_deplete_cost_meter_with_divide_by_zero() {
  4199. agave_logger::setup();
  4200. let GenesisConfigInfo {
  4201. genesis_config,
  4202. mint_keypair,
  4203. ..
  4204. } = create_genesis_config(50);
  4205. let bank = Bank::new_for_tests(&genesis_config);
  4206. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  4207. let mut bank_client = BankClient::new_shared(bank.clone());
  4208. let authority_keypair = Keypair::new();
  4209. let (bank, program_id) = load_program_of_loader_v4(
  4210. &mut bank_client,
  4211. bank_forks.as_ref(),
  4212. &mint_keypair,
  4213. &authority_keypair,
  4214. "solana_sbf_rust_divide_by_zero",
  4215. );
  4216. let instruction = Instruction::new_with_bytes(program_id, &[], vec![]);
  4217. let compute_unit_limit = 10_000;
  4218. let message = Message::new(
  4219. &[
  4220. ComputeBudgetInstruction::set_compute_unit_limit(compute_unit_limit),
  4221. instruction,
  4222. ],
  4223. Some(&mint_keypair.pubkey()),
  4224. );
  4225. let tx = Transaction::new(&[&mint_keypair], message, bank.last_blockhash());
  4226. let result = load_execute_and_commit_transaction(&bank, tx).unwrap();
  4227. assert_eq!(
  4228. result.status.unwrap_err(),
  4229. TransactionError::InstructionError(1, InstructionError::ProgramFailedToComplete)
  4230. );
  4231. // all compute unit limit should be consumed due to SBF VM error
  4232. assert_eq!(result.executed_units, u64::from(compute_unit_limit));
  4233. }
  4234. #[test]
  4235. #[cfg(feature = "sbf_rust")]
  4236. fn test_deny_access_beyond_current_length() {
  4237. agave_logger::setup();
  4238. let GenesisConfigInfo {
  4239. genesis_config,
  4240. mint_keypair,
  4241. ..
  4242. } = create_genesis_config(100_123_456_789);
  4243. for stricter_abi_and_runtime_constraints in [false, true] {
  4244. let mut bank = Bank::new_for_tests(&genesis_config);
  4245. let feature_set = Arc::make_mut(&mut bank.feature_set);
  4246. // by default test banks have all features enabled, so we only need to
  4247. // disable when needed
  4248. if !stricter_abi_and_runtime_constraints {
  4249. feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
  4250. feature_set.deactivate(&feature_set::account_data_direct_mapping::id());
  4251. }
  4252. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  4253. let mut bank_client = BankClient::new_shared(bank);
  4254. let authority_keypair = Keypair::new();
  4255. let (bank, invoke_program_id) = load_program_of_loader_v4(
  4256. &mut bank_client,
  4257. &bank_forks,
  4258. &mint_keypair,
  4259. &authority_keypair,
  4260. "solana_sbf_rust_invoke",
  4261. );
  4262. let account = AccountSharedData::new(42, 0, &invoke_program_id);
  4263. let readonly_account_keypair = Keypair::new();
  4264. let writable_account_keypair = Keypair::new();
  4265. bank.store_account(&readonly_account_keypair.pubkey(), &account);
  4266. bank.store_account(&writable_account_keypair.pubkey(), &account);
  4267. let mint_pubkey = mint_keypair.pubkey();
  4268. let account_metas = vec![
  4269. AccountMeta::new(mint_pubkey, true),
  4270. AccountMeta::new_readonly(readonly_account_keypair.pubkey(), false),
  4271. AccountMeta::new(writable_account_keypair.pubkey(), false),
  4272. AccountMeta::new_readonly(invoke_program_id, false),
  4273. ];
  4274. for (instruction_account_index, expected_error) in [
  4275. (1, InstructionError::AccountDataTooSmall),
  4276. (2, InstructionError::InvalidRealloc),
  4277. ] {
  4278. let mut instruction_data = vec![TEST_READ_ACCOUNT, instruction_account_index];
  4279. instruction_data.extend_from_slice(3usize.to_le_bytes().as_ref());
  4280. let instruction = Instruction::new_with_bytes(
  4281. invoke_program_id,
  4282. &instruction_data,
  4283. account_metas.clone(),
  4284. );
  4285. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  4286. if stricter_abi_and_runtime_constraints {
  4287. assert_eq!(
  4288. result.unwrap_err().unwrap(),
  4289. TransactionError::InstructionError(0, expected_error)
  4290. );
  4291. } else {
  4292. result.unwrap();
  4293. }
  4294. }
  4295. }
  4296. }
  4297. #[test]
  4298. #[cfg(feature = "sbf_rust")]
  4299. fn test_deny_executable_write() {
  4300. agave_logger::setup();
  4301. let GenesisConfigInfo {
  4302. genesis_config,
  4303. mint_keypair,
  4304. ..
  4305. } = create_genesis_config(100_123_456_789);
  4306. for stricter_abi_and_runtime_constraints in [false, true] {
  4307. let mut bank = Bank::new_for_tests(&genesis_config);
  4308. let feature_set = Arc::make_mut(&mut bank.feature_set);
  4309. // by default test banks have all features enabled, so we only need to
  4310. // disable when needed
  4311. if !stricter_abi_and_runtime_constraints {
  4312. feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
  4313. feature_set.deactivate(&feature_set::account_data_direct_mapping::id());
  4314. }
  4315. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  4316. let mut bank_client = BankClient::new_shared(bank);
  4317. let authority_keypair = Keypair::new();
  4318. let (_bank, invoke_program_id) = load_program_of_loader_v4(
  4319. &mut bank_client,
  4320. &bank_forks,
  4321. &mint_keypair,
  4322. &authority_keypair,
  4323. "solana_sbf_rust_invoke",
  4324. );
  4325. let account_keypair = Keypair::new();
  4326. let mint_pubkey = mint_keypair.pubkey();
  4327. let account_metas = vec![
  4328. AccountMeta::new(mint_pubkey, true),
  4329. AccountMeta::new(account_keypair.pubkey(), false),
  4330. AccountMeta::new_readonly(invoke_program_id, false),
  4331. ];
  4332. let mut instruction_data = vec![TEST_WRITE_ACCOUNT, 2];
  4333. instruction_data.extend_from_slice(3usize.to_le_bytes().as_ref());
  4334. instruction_data.push(42);
  4335. let instruction = Instruction::new_with_bytes(
  4336. invoke_program_id,
  4337. &instruction_data,
  4338. account_metas.clone(),
  4339. );
  4340. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  4341. assert_eq!(
  4342. result.unwrap_err().unwrap(),
  4343. TransactionError::InstructionError(0, InstructionError::ReadonlyDataModified)
  4344. );
  4345. }
  4346. }
  4347. #[test]
  4348. fn test_update_callee_account() {
  4349. // Test that fn update_callee_account() works and we are updating the callee account on CPI.
  4350. agave_logger::setup();
  4351. let GenesisConfigInfo {
  4352. genesis_config,
  4353. mint_keypair,
  4354. ..
  4355. } = create_genesis_config(100_123_456_789);
  4356. for stricter_abi_and_runtime_constraints in [false, true] {
  4357. let mut bank = Bank::new_for_tests(&genesis_config);
  4358. let feature_set = Arc::make_mut(&mut bank.feature_set);
  4359. // by default test banks have all features enabled, so we only need to
  4360. // disable when needed
  4361. if !stricter_abi_and_runtime_constraints {
  4362. feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
  4363. feature_set.deactivate(&feature_set::account_data_direct_mapping::id());
  4364. }
  4365. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  4366. let mut bank_client = BankClient::new_shared(bank.clone());
  4367. let authority_keypair = Keypair::new();
  4368. let (bank, invoke_program_id) = load_program_of_loader_v4(
  4369. &mut bank_client,
  4370. &bank_forks,
  4371. &mint_keypair,
  4372. &authority_keypair,
  4373. "solana_sbf_rust_invoke",
  4374. );
  4375. let account_keypair = Keypair::new();
  4376. let mint_pubkey = mint_keypair.pubkey();
  4377. let account_metas = vec![
  4378. AccountMeta::new(mint_pubkey, true),
  4379. AccountMeta::new(account_keypair.pubkey(), false),
  4380. AccountMeta::new_readonly(invoke_program_id, false),
  4381. ];
  4382. // I. do CPI with account in read only (separate code path with stricter_abi_and_runtime_constraints)
  4383. let mut account = AccountSharedData::new(42, 10240, &invoke_program_id);
  4384. let data: Vec<u8> = (0..10240).map(|n| n as u8).collect();
  4385. account.set_data(data);
  4386. bank.store_account(&account_keypair.pubkey(), &account);
  4387. let mut instruction_data = vec![TEST_CALLEE_ACCOUNT_UPDATES, 0, 0];
  4388. instruction_data.extend_from_slice(20480usize.to_le_bytes().as_ref());
  4389. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4390. instruction_data.extend_from_slice(16384usize.to_le_bytes().as_ref());
  4391. // instruction data for inner CPI (2x)
  4392. instruction_data.extend_from_slice(&[TEST_CALLEE_ACCOUNT_UPDATES, 0, 0]);
  4393. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4394. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4395. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4396. instruction_data.extend_from_slice(&[TEST_CALLEE_ACCOUNT_UPDATES, 0, 0]);
  4397. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4398. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4399. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4400. let instruction = Instruction::new_with_bytes(
  4401. invoke_program_id,
  4402. &instruction_data,
  4403. account_metas.clone(),
  4404. );
  4405. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  4406. assert!(result.is_ok());
  4407. let data = bank_client
  4408. .get_account_data(&account_keypair.pubkey())
  4409. .unwrap()
  4410. .unwrap();
  4411. assert_eq!(data.len(), 20480);
  4412. data.iter().enumerate().for_each(|(i, v)| {
  4413. let expected = match i {
  4414. ..=10240 => i as u8,
  4415. 16384 => 0xe5,
  4416. _ => 0,
  4417. };
  4418. assert_eq!(*v, expected, "offset:{i} {v:#x} != {expected:#x}");
  4419. });
  4420. // II. do CPI with account with resize to smaller and write
  4421. let mut account = AccountSharedData::new(42, 10240, &invoke_program_id);
  4422. let data: Vec<u8> = (0..10240).map(|n| n as u8).collect();
  4423. account.set_data(data);
  4424. bank.store_account(&account_keypair.pubkey(), &account);
  4425. let mut instruction_data = vec![TEST_CALLEE_ACCOUNT_UPDATES, 1, 0];
  4426. instruction_data.extend_from_slice(20480usize.to_le_bytes().as_ref());
  4427. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4428. instruction_data.extend_from_slice(16384usize.to_le_bytes().as_ref());
  4429. // instruction data for inner CPI
  4430. instruction_data.extend_from_slice(&[TEST_CALLEE_ACCOUNT_UPDATES, 0, 0]);
  4431. instruction_data.extend_from_slice(19480usize.to_le_bytes().as_ref());
  4432. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4433. instruction_data.extend_from_slice(8129usize.to_le_bytes().as_ref());
  4434. let instruction = Instruction::new_with_bytes(
  4435. invoke_program_id,
  4436. &instruction_data,
  4437. account_metas.clone(),
  4438. );
  4439. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  4440. assert!(result.is_ok());
  4441. let data = bank_client
  4442. .get_account_data(&account_keypair.pubkey())
  4443. .unwrap()
  4444. .unwrap();
  4445. assert_eq!(data.len(), 19480);
  4446. data.iter().enumerate().for_each(|(i, v)| {
  4447. let expected = match i {
  4448. 8129 => (i as u8) ^ 0xe5,
  4449. ..=10240 => i as u8,
  4450. 16384 => 0xe5,
  4451. _ => 0,
  4452. };
  4453. assert_eq!(*v, expected, "offset:{i} {v:#x} != {expected:#x}");
  4454. });
  4455. // III. do CPI with account with resize to larger and write
  4456. let mut account = AccountSharedData::new(42, 10240, &invoke_program_id);
  4457. let data: Vec<u8> = (0..10240).map(|n| n as u8).collect();
  4458. account.set_data(data);
  4459. bank.store_account(&account_keypair.pubkey(), &account);
  4460. let mut instruction_data = vec![TEST_CALLEE_ACCOUNT_UPDATES, 1, 0];
  4461. instruction_data.extend_from_slice(16384usize.to_le_bytes().as_ref());
  4462. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4463. instruction_data.extend_from_slice(16384usize.to_le_bytes().as_ref());
  4464. // instruction data for inner CPI
  4465. instruction_data.extend_from_slice(&[TEST_CALLEE_ACCOUNT_UPDATES, 0, 0]);
  4466. instruction_data.extend_from_slice(20480usize.to_le_bytes().as_ref());
  4467. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4468. instruction_data.extend_from_slice(16385usize.to_le_bytes().as_ref());
  4469. let instruction = Instruction::new_with_bytes(
  4470. invoke_program_id,
  4471. &instruction_data,
  4472. account_metas.clone(),
  4473. );
  4474. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  4475. assert!(result.is_ok());
  4476. let data = bank_client
  4477. .get_account_data(&account_keypair.pubkey())
  4478. .unwrap()
  4479. .unwrap();
  4480. assert_eq!(data.len(), 20480);
  4481. data.iter().enumerate().for_each(|(i, v)| {
  4482. let expected = match i {
  4483. ..=10240 => i as u8,
  4484. 16384 | 16385 => 0xe5,
  4485. _ => 0,
  4486. };
  4487. assert_eq!(*v, expected, "offset:{i} {v:#x} != {expected:#x}");
  4488. });
  4489. // IV. do CPI with account with resize to larger and write
  4490. let mut account = AccountSharedData::new(42, 10240, &invoke_program_id);
  4491. let data: Vec<u8> = (0..10240).map(|n| n as u8).collect();
  4492. account.set_data(data);
  4493. bank.store_account(&account_keypair.pubkey(), &account);
  4494. let mut instruction_data = vec![TEST_CALLEE_ACCOUNT_UPDATES, 1, 0];
  4495. instruction_data.extend_from_slice(16384usize.to_le_bytes().as_ref());
  4496. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4497. instruction_data.extend_from_slice(16384usize.to_le_bytes().as_ref());
  4498. // instruction data for inner CPI (2x)
  4499. instruction_data.extend_from_slice(&[TEST_CALLEE_ACCOUNT_UPDATES, 1, 0]);
  4500. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4501. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4502. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4503. instruction_data.extend_from_slice(&[TEST_CALLEE_ACCOUNT_UPDATES, 1, 0]);
  4504. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4505. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4506. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4507. // instruction data for inner CPI
  4508. instruction_data.extend_from_slice(&[TEST_CALLEE_ACCOUNT_UPDATES, 0, 0]);
  4509. instruction_data.extend_from_slice(20480usize.to_le_bytes().as_ref());
  4510. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4511. instruction_data.extend_from_slice(16385usize.to_le_bytes().as_ref());
  4512. let instruction = Instruction::new_with_bytes(
  4513. invoke_program_id,
  4514. &instruction_data,
  4515. account_metas.clone(),
  4516. );
  4517. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  4518. assert!(result.is_ok());
  4519. let data = bank_client
  4520. .get_account_data(&account_keypair.pubkey())
  4521. .unwrap()
  4522. .unwrap();
  4523. assert_eq!(data.len(), 20480);
  4524. data.iter().enumerate().for_each(|(i, v)| {
  4525. let expected = match i {
  4526. ..=10240 => i as u8,
  4527. 16384 | 16385 => 0xe5,
  4528. _ => 0,
  4529. };
  4530. assert_eq!(*v, expected, "offset:{i} {v:#x} != {expected:#x}");
  4531. });
  4532. // V. clone data, modify and CPI
  4533. let mut account = AccountSharedData::new(42, 10240, &invoke_program_id);
  4534. let data: Vec<u8> = (0..10240).map(|n| n as u8).collect();
  4535. account.set_data(data);
  4536. bank.store_account(&account_keypair.pubkey(), &account);
  4537. let mut instruction_data = vec![TEST_CALLEE_ACCOUNT_UPDATES, 1, 1];
  4538. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4539. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4540. instruction_data.extend_from_slice(8190usize.to_le_bytes().as_ref());
  4541. // instruction data for inner CPI
  4542. instruction_data.extend_from_slice(&[TEST_CALLEE_ACCOUNT_UPDATES, 1, 0]);
  4543. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4544. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4545. instruction_data.extend_from_slice(8191usize.to_le_bytes().as_ref());
  4546. let instruction = Instruction::new_with_bytes(
  4547. invoke_program_id,
  4548. &instruction_data,
  4549. account_metas.clone(),
  4550. );
  4551. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  4552. if stricter_abi_and_runtime_constraints {
  4553. // changing the data pointer is not permitted
  4554. assert!(result.is_err());
  4555. } else {
  4556. assert!(result.is_ok());
  4557. let data = bank_client
  4558. .get_account_data(&account_keypair.pubkey())
  4559. .unwrap()
  4560. .unwrap();
  4561. assert_eq!(data.len(), 10240);
  4562. data.iter().enumerate().for_each(|(i, v)| {
  4563. let expected = match i {
  4564. // since the data is was cloned, the write to 8191 was lost
  4565. 8190 => (i as u8) ^ 0xe5,
  4566. ..=10240 => i as u8,
  4567. _ => 0,
  4568. };
  4569. assert_eq!(*v, expected, "offset:{i} {v:#x} != {expected:#x}");
  4570. });
  4571. }
  4572. }
  4573. }
  4574. #[test]
  4575. fn test_account_info_in_account() {
  4576. agave_logger::setup();
  4577. let GenesisConfigInfo {
  4578. genesis_config,
  4579. mint_keypair,
  4580. ..
  4581. } = create_genesis_config(100_123_456_789);
  4582. let mut programs = Vec::new();
  4583. #[cfg(feature = "sbf_c")]
  4584. {
  4585. programs.push("invoke");
  4586. }
  4587. #[cfg(feature = "sbf_rust")]
  4588. {
  4589. programs.push("solana_sbf_rust_invoke");
  4590. }
  4591. for program in programs {
  4592. for stricter_abi_and_runtime_constraints in [false, true] {
  4593. let mut bank = Bank::new_for_tests(&genesis_config);
  4594. let feature_set = Arc::make_mut(&mut bank.feature_set);
  4595. // by default test banks have all features enabled, so we only need to
  4596. // disable when needed
  4597. if !stricter_abi_and_runtime_constraints {
  4598. feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
  4599. feature_set.deactivate(&feature_set::account_data_direct_mapping::id());
  4600. }
  4601. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  4602. let mut bank_client = BankClient::new_shared(bank.clone());
  4603. let authority_keypair = Keypair::new();
  4604. let (bank, invoke_program_id) = load_program_of_loader_v4(
  4605. &mut bank_client,
  4606. &bank_forks,
  4607. &mint_keypair,
  4608. &authority_keypair,
  4609. program,
  4610. );
  4611. let account_keypair = Keypair::new();
  4612. let mint_pubkey = mint_keypair.pubkey();
  4613. let account_metas = vec![
  4614. AccountMeta::new(mint_pubkey, true),
  4615. AccountMeta::new(account_keypair.pubkey(), false),
  4616. AccountMeta::new_readonly(invoke_program_id, false),
  4617. ];
  4618. let mut instruction_data = vec![TEST_ACCOUNT_INFO_IN_ACCOUNT];
  4619. instruction_data.extend_from_slice(32usize.to_le_bytes().as_ref());
  4620. let instruction =
  4621. Instruction::new_with_bytes(invoke_program_id, &instruction_data, account_metas);
  4622. let account = AccountSharedData::new(42, 10240, &invoke_program_id);
  4623. bank.store_account(&account_keypair.pubkey(), &account);
  4624. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  4625. if stricter_abi_and_runtime_constraints {
  4626. assert!(result.is_err());
  4627. } else {
  4628. assert!(result.is_ok());
  4629. }
  4630. }
  4631. }
  4632. }
  4633. #[test]
  4634. fn test_account_info_rc_in_account() {
  4635. agave_logger::setup();
  4636. let GenesisConfigInfo {
  4637. genesis_config,
  4638. mint_keypair,
  4639. ..
  4640. } = create_genesis_config(100_123_456_789);
  4641. for stricter_abi_and_runtime_constraints in [false, true] {
  4642. let mut bank = Bank::new_for_tests(&genesis_config);
  4643. let feature_set = Arc::make_mut(&mut bank.feature_set);
  4644. // by default test banks have all features enabled, so we only need to
  4645. // disable when needed
  4646. if !stricter_abi_and_runtime_constraints {
  4647. feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
  4648. feature_set.deactivate(&feature_set::account_data_direct_mapping::id());
  4649. }
  4650. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  4651. let mut bank_client = BankClient::new_shared(bank.clone());
  4652. let authority_keypair = Keypair::new();
  4653. let (bank, invoke_program_id) = load_program_of_loader_v4(
  4654. &mut bank_client,
  4655. &bank_forks,
  4656. &mint_keypair,
  4657. &authority_keypair,
  4658. "solana_sbf_rust_invoke",
  4659. );
  4660. let account_keypair = Keypair::new();
  4661. let mint_pubkey = mint_keypair.pubkey();
  4662. let account_metas = vec![
  4663. AccountMeta::new(mint_pubkey, true),
  4664. AccountMeta::new(account_keypair.pubkey(), false),
  4665. AccountMeta::new_readonly(invoke_program_id, false),
  4666. ];
  4667. let instruction_data = vec![TEST_ACCOUNT_INFO_LAMPORTS_RC, 0, 0, 0];
  4668. let instruction = Instruction::new_with_bytes(
  4669. invoke_program_id,
  4670. &instruction_data,
  4671. account_metas.clone(),
  4672. );
  4673. let account = AccountSharedData::new(42, 10240, &invoke_program_id);
  4674. bank.store_account(&account_keypair.pubkey(), &account);
  4675. let message = Message::new(&[instruction], Some(&mint_pubkey));
  4676. let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
  4677. let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
  4678. if stricter_abi_and_runtime_constraints {
  4679. assert!(
  4680. logs.last().unwrap().ends_with(" failed: Invalid pointer"),
  4681. "{logs:?}"
  4682. );
  4683. assert!(result.is_err());
  4684. } else {
  4685. assert!(result.is_ok(), "{logs:?}");
  4686. }
  4687. let instruction_data = vec![TEST_ACCOUNT_INFO_DATA_RC, 0, 0, 0];
  4688. let instruction =
  4689. Instruction::new_with_bytes(invoke_program_id, &instruction_data, account_metas);
  4690. let account = AccountSharedData::new(42, 10240, &invoke_program_id);
  4691. bank.store_account(&account_keypair.pubkey(), &account);
  4692. let message = Message::new(&[instruction], Some(&mint_pubkey));
  4693. let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
  4694. let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
  4695. if stricter_abi_and_runtime_constraints {
  4696. assert!(
  4697. logs.last().unwrap().ends_with(" failed: Invalid pointer"),
  4698. "{logs:?}"
  4699. );
  4700. assert!(result.is_err());
  4701. } else {
  4702. assert!(result.is_ok(), "{logs:?}");
  4703. }
  4704. }
  4705. }
  4706. #[test]
  4707. fn test_clone_account_data() {
  4708. // Test cloning account data works as expect with
  4709. agave_logger::setup();
  4710. let GenesisConfigInfo {
  4711. genesis_config,
  4712. mint_keypair,
  4713. ..
  4714. } = create_genesis_config(100_123_456_789);
  4715. let mut bank = Bank::new_for_tests(&genesis_config);
  4716. let feature_set = Arc::make_mut(&mut bank.feature_set);
  4717. feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
  4718. feature_set.deactivate(&feature_set::account_data_direct_mapping::id());
  4719. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  4720. let mut bank_client = BankClient::new_shared(bank.clone());
  4721. let authority_keypair = Keypair::new();
  4722. let (_bank, invoke_program_id) = load_program_of_loader_v4(
  4723. &mut bank_client,
  4724. &bank_forks,
  4725. &mint_keypair,
  4726. &authority_keypair,
  4727. "solana_sbf_rust_invoke",
  4728. );
  4729. let (bank, invoke_program_id2) = load_program_of_loader_v4(
  4730. &mut bank_client,
  4731. &bank_forks,
  4732. &mint_keypair,
  4733. &authority_keypair,
  4734. "solana_sbf_rust_invoke",
  4735. );
  4736. let account_keypair = Keypair::new();
  4737. let mint_pubkey = mint_keypair.pubkey();
  4738. let account_metas = vec![
  4739. AccountMeta::new(mint_pubkey, true),
  4740. AccountMeta::new(account_keypair.pubkey(), false),
  4741. AccountMeta::new_readonly(invoke_program_id2, false),
  4742. AccountMeta::new_readonly(invoke_program_id, false),
  4743. ];
  4744. // I. clone data and CPI; modify data in callee.
  4745. // Now the original data in the caller is unmodified, and we get a "instruction modified data of an account it does not own"
  4746. // error in the caller
  4747. let mut account = AccountSharedData::new(42, 10240, &invoke_program_id2);
  4748. let data: Vec<u8> = (0..10240).map(|n| n as u8).collect();
  4749. account.set_data(data);
  4750. bank.store_account(&account_keypair.pubkey(), &account);
  4751. let mut instruction_data = vec![TEST_CALLEE_ACCOUNT_UPDATES, 1, 1];
  4752. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4753. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4754. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4755. // instruction data for inner CPI: modify account
  4756. instruction_data.extend_from_slice(&[TEST_CALLEE_ACCOUNT_UPDATES, 0, 0]);
  4757. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4758. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4759. instruction_data.extend_from_slice(8190usize.to_le_bytes().as_ref());
  4760. let instruction =
  4761. Instruction::new_with_bytes(invoke_program_id, &instruction_data, account_metas.clone());
  4762. let message = Message::new(&[instruction], Some(&mint_pubkey));
  4763. let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
  4764. let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
  4765. assert!(result.is_err(), "{result:?}");
  4766. let error = format!(
  4767. "Program {invoke_program_id} failed: instruction modified data of an account it does not \
  4768. own"
  4769. );
  4770. assert!(logs.iter().any(|log| log.contains(&error)), "{logs:?}");
  4771. // II. clone data, modify and then CPI
  4772. // The deserialize checks should verify that we're not allowed to modify an account we don't own, even though
  4773. // we have only modified a copy of the data. Fails in caller
  4774. let mut account = AccountSharedData::new(42, 10240, &invoke_program_id2);
  4775. let data: Vec<u8> = (0..10240).map(|n| n as u8).collect();
  4776. account.set_data(data);
  4777. bank.store_account(&account_keypair.pubkey(), &account);
  4778. let mut instruction_data = vec![TEST_CALLEE_ACCOUNT_UPDATES, 1, 1];
  4779. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4780. instruction_data.extend_from_slice(8190usize.to_le_bytes().as_ref());
  4781. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4782. // instruction data for inner CPI
  4783. instruction_data.extend_from_slice(&[TEST_CALLEE_ACCOUNT_UPDATES, 0, 0]);
  4784. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4785. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4786. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4787. let instruction =
  4788. Instruction::new_with_bytes(invoke_program_id, &instruction_data, account_metas.clone());
  4789. let message = Message::new(&[instruction], Some(&mint_pubkey));
  4790. let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
  4791. let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
  4792. assert!(result.is_err(), "{result:?}");
  4793. let error = format!(
  4794. "Program {invoke_program_id} failed: instruction modified data of an account it does not \
  4795. own"
  4796. );
  4797. assert!(logs.iter().any(|log| log.contains(&error)), "{logs:?}");
  4798. // II. Clone data, call, modifiy in callee and then make the same change in the caller - transaction succeeds
  4799. // Note the caller needs to modify the original account data, not the copy
  4800. let mut account = AccountSharedData::new(42, 10240, &invoke_program_id2);
  4801. let data: Vec<u8> = (0..10240).map(|n| n as u8).collect();
  4802. account.set_data(data);
  4803. bank.store_account(&account_keypair.pubkey(), &account);
  4804. let mut instruction_data = vec![TEST_CALLEE_ACCOUNT_UPDATES, 1, 1];
  4805. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4806. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4807. instruction_data.extend_from_slice(8190usize.to_le_bytes().as_ref());
  4808. // instruction data for inner CPI
  4809. instruction_data.extend_from_slice(&[TEST_CALLEE_ACCOUNT_UPDATES, 0, 0]);
  4810. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4811. instruction_data.extend_from_slice(0usize.to_le_bytes().as_ref());
  4812. instruction_data.extend_from_slice(8190usize.to_le_bytes().as_ref());
  4813. let instruction =
  4814. Instruction::new_with_bytes(invoke_program_id, &instruction_data, account_metas.clone());
  4815. let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
  4816. // works because the account is exactly the same in caller as callee
  4817. assert!(result.is_ok(), "{result:?}");
  4818. }
  4819. #[test]
  4820. fn test_stack_heap_zeroed() {
  4821. agave_logger::setup();
  4822. let GenesisConfigInfo {
  4823. genesis_config,
  4824. mint_keypair,
  4825. ..
  4826. } = create_genesis_config(100_123_456_789);
  4827. let bank = Bank::new_for_tests(&genesis_config);
  4828. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  4829. let mut bank_client = BankClient::new_shared(bank);
  4830. let authority_keypair = Keypair::new();
  4831. let (bank, invoke_program_id) = load_program_of_loader_v4(
  4832. &mut bank_client,
  4833. &bank_forks,
  4834. &mint_keypair,
  4835. &authority_keypair,
  4836. "solana_sbf_rust_invoke",
  4837. );
  4838. let account_keypair = Keypair::new();
  4839. let mint_pubkey = mint_keypair.pubkey();
  4840. let account_metas = vec![
  4841. AccountMeta::new(mint_pubkey, true),
  4842. AccountMeta::new(account_keypair.pubkey(), false),
  4843. AccountMeta::new_readonly(invoke_program_id, false),
  4844. ];
  4845. // Check multiple heap sizes. It's generally a good idea, and also it's needed to ensure that
  4846. // pooled heap and stack values are reused - and therefore zeroed - across executions.
  4847. for heap_len in [32usize * 1024, 64 * 1024, 128 * 1024, 256 * 1024] {
  4848. // TEST_STACK_HEAP_ZEROED will recursively check that stack and heap are zeroed until it
  4849. // reaches max CPI invoke depth. We make it fail at max depth so we're sure that there's no
  4850. // legit way to access non-zeroed stack and heap regions.
  4851. let mut instruction_data = vec![TEST_STACK_HEAP_ZEROED];
  4852. instruction_data.extend_from_slice(&heap_len.to_le_bytes());
  4853. let instruction = Instruction::new_with_bytes(
  4854. invoke_program_id,
  4855. &instruction_data,
  4856. account_metas.clone(),
  4857. );
  4858. let message = Message::new(
  4859. &[
  4860. ComputeBudgetInstruction::set_compute_unit_limit(1_400_000),
  4861. ComputeBudgetInstruction::request_heap_frame(heap_len as u32),
  4862. instruction,
  4863. ],
  4864. Some(&mint_pubkey),
  4865. );
  4866. let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
  4867. let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
  4868. assert!(result.is_err(), "{result:?}");
  4869. assert!(
  4870. logs.iter()
  4871. .any(|log| log.contains("Cross-program invocation call depth too deep")),
  4872. "{logs:?}"
  4873. );
  4874. }
  4875. }
  4876. #[test]
  4877. fn test_function_call_args() {
  4878. // This function tests edge compiler edge cases when calling functions with more than five
  4879. // arguments and passing by value arguments with more than 16 bytes.
  4880. agave_logger::setup();
  4881. let GenesisConfigInfo {
  4882. genesis_config,
  4883. mint_keypair,
  4884. ..
  4885. } = create_genesis_config(100_123_456_789);
  4886. let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  4887. let mut bank_client = BankClient::new_shared(bank);
  4888. let authority_keypair = Keypair::new();
  4889. let (bank, program_id) = load_program_of_loader_v4(
  4890. &mut bank_client,
  4891. &bank_forks,
  4892. &mint_keypair,
  4893. &authority_keypair,
  4894. "solana_sbf_rust_call_args",
  4895. );
  4896. #[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug)]
  4897. struct Test128 {
  4898. a: u128,
  4899. b: u128,
  4900. }
  4901. #[derive(BorshSerialize)]
  4902. struct InputData {
  4903. test_128: Test128,
  4904. arg1: i64,
  4905. arg2: i64,
  4906. arg3: i64,
  4907. arg4: i64,
  4908. arg5: i64,
  4909. arg6: i64,
  4910. arg7: i64,
  4911. arg8: i64,
  4912. }
  4913. #[derive(BorshDeserialize)]
  4914. struct OutputData {
  4915. res_128: u128,
  4916. res_256: Test128,
  4917. many_args_1: i64,
  4918. many_args_2: i64,
  4919. }
  4920. let input_data = InputData {
  4921. test_128: Test128 {
  4922. a: rand::random::<u128>(),
  4923. b: rand::random::<u128>(),
  4924. },
  4925. arg1: rand::random::<i64>(),
  4926. arg2: rand::random::<i64>(),
  4927. arg3: rand::random::<i64>(),
  4928. arg4: rand::random::<i64>(),
  4929. arg5: rand::random::<i64>(),
  4930. arg6: rand::random::<i64>(),
  4931. arg7: rand::random::<i64>(),
  4932. arg8: rand::random::<i64>(),
  4933. };
  4934. let instruction_data = to_vec(&input_data).unwrap();
  4935. let account_metas = vec![
  4936. AccountMeta::new(mint_keypair.pubkey(), true),
  4937. AccountMeta::new(Keypair::new().pubkey(), false),
  4938. ];
  4939. let instruction = Instruction::new_with_bytes(program_id, &instruction_data, account_metas);
  4940. let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
  4941. let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
  4942. let txs = vec![tx];
  4943. let tx_batch = bank.prepare_batch_for_tests(txs);
  4944. let result = bank
  4945. .load_execute_and_commit_transactions(
  4946. &tx_batch,
  4947. MAX_PROCESSING_AGE,
  4948. ExecutionRecordingConfig {
  4949. enable_cpi_recording: false,
  4950. enable_log_recording: false,
  4951. enable_return_data_recording: true,
  4952. enable_transaction_balance_recording: false,
  4953. },
  4954. &mut ExecuteTimings::default(),
  4955. None,
  4956. )
  4957. .0;
  4958. fn verify_many_args(input: &InputData) -> i64 {
  4959. let a = input
  4960. .arg1
  4961. .overflowing_add(input.arg2)
  4962. .0
  4963. .overflowing_sub(input.arg3)
  4964. .0
  4965. .overflowing_add(input.arg4)
  4966. .0
  4967. .overflowing_sub(input.arg5)
  4968. .0;
  4969. (a % input.arg6)
  4970. .overflowing_sub(input.arg7)
  4971. .0
  4972. .overflowing_add(input.arg8)
  4973. .0
  4974. }
  4975. let return_data = &result[0]
  4976. .as_ref()
  4977. .unwrap()
  4978. .return_data
  4979. .as_ref()
  4980. .unwrap()
  4981. .data;
  4982. let decoded: OutputData = from_slice::<OutputData>(return_data).unwrap();
  4983. assert_eq!(
  4984. decoded.res_128,
  4985. input_data.test_128.a % input_data.test_128.b
  4986. );
  4987. assert_eq!(
  4988. decoded.res_256,
  4989. Test128 {
  4990. a: input_data
  4991. .test_128
  4992. .a
  4993. .overflowing_add(input_data.test_128.b)
  4994. .0,
  4995. b: input_data
  4996. .test_128
  4997. .a
  4998. .overflowing_sub(input_data.test_128.b)
  4999. .0
  5000. }
  5001. );
  5002. assert_eq!(decoded.many_args_1, verify_many_args(&input_data));
  5003. assert_eq!(decoded.many_args_2, verify_many_args(&input_data));
  5004. }
  5005. #[test]
  5006. #[cfg(feature = "sbf_rust")]
  5007. fn test_mem_syscalls_overlap_account_begin_or_end() {
  5008. agave_logger::setup();
  5009. for stricter_abi_and_runtime_constraints in [false, true] {
  5010. let GenesisConfigInfo {
  5011. genesis_config,
  5012. mint_keypair,
  5013. ..
  5014. } = create_genesis_config(100_123_456_789);
  5015. let mut bank = Bank::new_for_tests(&genesis_config);
  5016. let mut feature_set = FeatureSet::all_enabled();
  5017. if !stricter_abi_and_runtime_constraints {
  5018. feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
  5019. feature_set.deactivate(&feature_set::account_data_direct_mapping::id());
  5020. }
  5021. let account_keypair = Keypair::new();
  5022. bank.feature_set = Arc::new(feature_set);
  5023. let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
  5024. let mut bank_client = BankClient::new_shared(bank);
  5025. let authority_keypair = Keypair::new();
  5026. let (bank, loader_v4_program_id) = load_program_of_loader_v4(
  5027. &mut bank_client,
  5028. &bank_forks,
  5029. &mint_keypair,
  5030. &authority_keypair,
  5031. "solana_sbf_rust_account_mem",
  5032. );
  5033. let deprecated_program_id = create_program(
  5034. &bank,
  5035. &bpf_loader_deprecated::id(),
  5036. "solana_sbf_rust_account_mem_deprecated",
  5037. );
  5038. let mint_pubkey = mint_keypair.pubkey();
  5039. for deprecated in [false, true] {
  5040. let program_id = if deprecated {
  5041. deprecated_program_id
  5042. } else {
  5043. loader_v4_program_id
  5044. };
  5045. let account_metas = vec![
  5046. AccountMeta::new(mint_pubkey, true),
  5047. AccountMeta::new_readonly(program_id, false),
  5048. AccountMeta::new(account_keypair.pubkey(), false),
  5049. ];
  5050. let account = AccountSharedData::new(42, 1024, &program_id);
  5051. bank.store_account(&account_keypair.pubkey(), &account);
  5052. for instr in 0..=15 {
  5053. println!(
  5054. "Testing deprecated:{deprecated} \
  5055. stricter_abi_and_runtime_constraints:{stricter_abi_and_runtime_constraints} \
  5056. instruction:{instr}"
  5057. );
  5058. let instruction =
  5059. Instruction::new_with_bytes(program_id, &[instr], account_metas.clone());
  5060. let message = Message::new(&[instruction], Some(&mint_pubkey));
  5061. let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
  5062. let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
  5063. let last_line = logs.last().unwrap();
  5064. if stricter_abi_and_runtime_constraints {
  5065. assert!(last_line.contains(" failed: Access violation"), "{logs:?}");
  5066. } else {
  5067. assert!(result.is_ok(), "{logs:?}");
  5068. }
  5069. }
  5070. let account = AccountSharedData::new(42, 0, &program_id);
  5071. bank.store_account(&account_keypair.pubkey(), &account);
  5072. for instr in 0..=15 {
  5073. println!(
  5074. "Testing deprecated:{deprecated} \
  5075. stricter_abi_and_runtime_constraints:{stricter_abi_and_runtime_constraints} \
  5076. instruction:{instr} zero-length account"
  5077. );
  5078. let instruction =
  5079. Instruction::new_with_bytes(program_id, &[instr, 0], account_metas.clone());
  5080. let message = Message::new(&[instruction], Some(&mint_pubkey));
  5081. let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
  5082. let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
  5083. let last_line = logs.last().unwrap();
  5084. if stricter_abi_and_runtime_constraints && (!deprecated || instr < 8) {
  5085. assert!(
  5086. last_line.contains(" failed: account data too small")
  5087. || last_line.contains(" failed: Failed to reallocate account data")
  5088. || last_line.contains(" failed: Access violation"),
  5089. "{logs:?}",
  5090. );
  5091. } else {
  5092. // stricter_abi_and_runtime_constraints && deprecated && instr >= 8 succeeds with zero-length accounts
  5093. // because there is no MemoryRegion for the account,
  5094. // so there can be no error when leaving that non-existent region.
  5095. assert!(result.is_ok(), "{logs:?}");
  5096. }
  5097. }
  5098. }
  5099. }
  5100. }