Solana 테스트 스위트에서 solana-test-validator를 실행하면 테스트당 수 초가 소요됩니다 -
프로세스 시작, RPC 연결, 네트워크 왕복 시간을 기다려야 하기 때문입니다.
LiteSVM은 동일한 테스트를 밀리초 단위로 실행합니다. 외부 프로세스도 없고, 네트워크도 없으며,
모든 것이 테스트 러너 내부 메모리에서 처리됩니다.
litesvm-go는 공식 Go 바인딩입니다. 핵심 타입(PublicKey, Hash,
Signature)은 gagliardetto/solana-go에서 직접 가져오므로,
값이 litesvm-go와 나머지 Go Solana 생태계 사이에서 자연스럽게 흐릅니다.
요구사항: Go 1.24 이상. Rust 툴체인 불필요 - 사전 빌드된 정적
아카이브가 모듈에 내장되어 있으며 GOOS / GOARCH에 따라 자동으로 선택됩니다.
지원 플랫폼: macOS (amd64, arm64), Linux (amd64, arm64;
glibc 또는 musl), Windows (amd64).
새로운 LiteSVM 핸들은 에어드롭, 트랜잭션(레거시 + v0),
시뮬레이션, 계정 읽기/쓰기, sysvars, 컴퓨트 예산, 피처 게이트, 시간
이동, 커스텀 프로그램, 트랜잭션 히스토리를 제공하며 - 이 모든 것이 Rust 및 TypeScript SDK를
구동하는 동일한 Rust 코어로 뒷받침됩니다.
빠른 시작
모듈 설치
go get은 의존성을 Go 모듈로 해석하므로, go.mod가 없다면 먼저 초기화하세요:
go mod init mytest
그런 다음 모듈을 추가하세요:
go get github.com/LiteSVM/litesvm-go
keypair, 명령어 및 트랜잭션 빌드를 위해 solana-go도 함께 추가하세요:
go get github.com/gagliardetto/solana-go
Alpine / musl 사용자: 올바른 내장 아카이브가 링크되도록 go build / go test
실행 시 -tags musl을 추가하세요.
SVM 생성
package mytestimport ("testing"litesvm "github.com/LiteSVM/litesvm-go"solana "github.com/gagliardetto/solana-go")func TestSetup(t *testing.T) {svm, err := litesvm.New()if err != nil {t.Fatal(err)}defer svm.Close()// Fund a payerpriv, err := solana.NewRandomPrivateKey()if err != nil {t.Fatal(err)}payer := priv.PublicKey()if err := svm.Airdrop(payer, 5_000_000_000); err != nil {t.Fatal(err)}// Check the balancelamports, ok, err := svm.Balance(payer)if err != nil {t.Fatal(err)}if !ok {t.Fatal("payer account missing")}t.Logf("balance: %d lamports", lamports)}
litesvm.New()는 *LiteSVM과 error를 반환합니다. litesvm-go의 모든 진입점은
동일한 (value, error) 형태를 따르며, Rust 측 패닉은 포착되어 에러로 변환됩니다.
항상 defer svm.Close()를 사용하여 내부 Rust 핸들을 해제하세요 - 또는 파이널라이저에
의존할 수도 있지만, 명시적인 Close 호출이 예측 가능한 정리를 위해 권장됩니다.
핸들 이해하기
litesvm.New() 이후 반환된 *LiteSVM은 다음 기능 그룹을 제공합니다:
| 그룹 | 메서드 |
|---|---|
| 계정 | Airdrop, Balance, GetAccount, SetAccount, MinimumBalanceForRentExemption |
| 트랜잭션 | SendLegacyTransaction, SendVersionedTransaction, SimulateLegacyTransaction, SimulateVersionedTransaction, GetTransaction |
| 블록해시 | LatestBlockhash, ExpireBlockhash |
| 프로그램 | AddProgram, AddProgramFromFile, AddProgramWithLoader |
| 시간 및 sysvars | WarpToSlot, Clock, SetClock, Rent, SetRent, EpochSchedule, SetEpochSchedule, EpochRewards, ... |
| 설정 | SetSigverify, SetBlockhashCheck, SetTransactionHistory, SetLogBytesLimit, SetSysvars, SetBuiltins, ... |
| 컴퓨트 및 피처 | ComputeBudget, SetComputeBudget, SetFeatureSet |
새로운 LiteSVM에는 핵심 Solana 프로그램(System Program, SPL
Token 등)이 사전 로드되어 있어, 간단한 전송이 즉시 작동합니다.
트랜잭션 전송
solana-go로 명령어를 빌드하고, 트랜잭션을 직렬화한 후 바이트를 제출합니다.
litesvm-go는 (*solana.Transaction).MarshalBinary가 생성하는
bincode 인코딩된 바이트를 받아들입니다:
package mytestimport ("testing"litesvm "github.com/LiteSVM/litesvm-go"solana "github.com/gagliardetto/solana-go""github.com/gagliardetto/solana-go/programs/system")func TestTransfer(t *testing.T) {svm, err := litesvm.New()if err != nil {t.Fatal(err)}defer svm.Close()priv, err := solana.NewRandomPrivateKey()if err != nil {t.Fatal(err)}payer := priv.PublicKey()recipient := solana.NewWallet().PublicKey()if err := svm.Airdrop(payer, 2_000_000_000); err != nil {t.Fatal(err)}blockhash, err := svm.LatestBlockhash()if err != nil {t.Fatal(err)}ix := system.NewTransferInstruction(1_000_000_000, payer, recipient).Build()tx, err := solana.NewTransaction([]solana.Instruction{ix},blockhash,solana.TransactionPayer(payer),)if err != nil {t.Fatal(err)}if _, err := tx.Sign(func(k solana.PublicKey) *solana.PrivateKey {if k.Equals(payer) {return &priv}return nil}); err != nil {t.Fatal(err)}txBytes, err := tx.MarshalBinary()if err != nil {t.Fatal(err)}out, err := svm.SendLegacyTransaction(txBytes)if err != nil {t.Fatal(err)}defer out.Close()if !out.IsOk() {t.Fatalf("tx failed: %s\nlogs: %v", out.Error(), out.Logs())}lamports, _, err := svm.Balance(recipient)if err != nil {t.Fatal(err)}if lamports != 1_000_000_000 {t.Fatalf("recipient balance = %d, want 1_000_000_000", lamports)}}
SendLegacyTransaction과 SendVersionedTransaction은 트랜잭션 성공 여부와 관계없이
*TxOutcome을 반환합니다. 성공 전용 필드를 읽기 전에 IsOk()를 확인하고,
항상 defer out.Close()를 사용하여 Rust 핸들을 해제하세요.
TxOutcome 활용하기
모든 send / simulate 진입점은 *TxOutcome을 반환합니다. 동일한 핸들에
성공 및 실패에 대한 메타데이터가 포함됩니다:
out, err := svm.SendLegacyTransaction(txBytes)if err != nil {t.Fatal(err)}defer out.Close()if !out.IsOk() {t.Fatalf("error: %s", out.Error())}_ = out.Signature() // solana.Signature_ = out.ComputeUnits() // uint64_ = out.Fee() // uint64_ = out.Logs() // []string_ = out.InnerInstructions()// Programs that call set_return_data expose it here.if pid, data, ok := out.ReturnData(); ok {_ = pid_ = data}
SimulateLegacyTransaction / SimulateVersionedTransaction의 경우, 동일한
*TxOutcome이 추가로 PostAccounts()를 제공합니다 - 실행 이후의 가상
계정 상태입니다:
sim, err := svm.SimulateLegacyTransaction(txBytes)if err != nil {t.Fatal(err)}defer sim.Close()posts, err := sim.PostAccounts()if err != nil {t.Fatal(err)}for _, p := range posts {_ = p.Address_ = p.Account.Lamports()p.Account.Close()}
설정
litesvm-go는 Rust 크레이트와 동일한 빌더 스위치를 Set* 메서드 형태로 제공합니다:
// Each setter returns an error. In tests where the values are known good,// the calls are infallible and assigning to _ keeps the example readable;// in production code, check the error or wrap with require.NoError(t, ...)._ = svm.SetSigverify(false) // accept unsigned / badly-signed txs_ = svm.SetBlockhashCheck(false) // skip recent-blockhash enforcement_ = svm.SetTransactionHistory(0) // 0 disables dedup; any N caps history_ = svm.SetLogBytesLimit(-1) // negative = unlimited_ = svm.SetLamports(1 << 40) // default lamports for new accounts_ = svm.SetSysvars() // reset sysvars to defaults_ = svm.SetBuiltins() // reload built-in programs_ = svm.SetDefaultPrograms() // reload SPL Token, Memo, etc._ = svm.SetPrecompiles() // enable ed25519 / secp256k1 precompiles_ = svm.WithNativeMints() // seed wrapped-SOL mint
참고 사항
스레드 안전성. *LiteSVM 핸들은 여러 고루틴에서 동시에 사용하기에 안전하지 않습니다
(내부 Rust 타입이 Sync하지 않으며, 대부분의 메서드가 내부 상태를 변경합니다). 핸들을
단일 고루틴에서만 사용하거나, sync.Mutex로 보호하세요.
패닉 동작. 내장된 릴리스 아카이브는 immediate-abort로 빌드됩니다:
Rust 내부에서 발생하는 패닉은 언와인딩 없이 호스트 프로세스를 직접 종료합니다. 이는
더 작은 아카이브를 위한 의도적인 절충입니다. 실제로 발생한 경우, 재현 방법과 함께
이슈를 등록해 주세요.
다음 단계
이 문서는 계정 생성, 명령어 전송, 상태 읽기 등 핵심 핸들을 다룹니다. 메서드별 전체 참조는 API 문서를 확인하세요. 실행 가능한 예제(SOL 전송, 계정 설정, 프로그램 테스트, 시간 기반 로직)는 예제를 참고하세요.
Is this page helpful?