programs.rs 198 KB

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