programs.rs 205 KB

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