Skip to content

Commit

Permalink
Add upgrading/subtyping support for records.
Browse files Browse the repository at this point in the history
  • Loading branch information
q-uint committed Sep 24, 2024
1 parent 6aa5899 commit 5624e71
Show file tree
Hide file tree
Showing 29 changed files with 1,678 additions and 627 deletions.
38 changes: 38 additions & 0 deletions candid/candid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,41 @@ func TestParseDID(t *testing.T) {
t.Error(err)
}
}

func TestRecordSubtyping(t *testing.T) {
type T struct{ X idl.Nat }
type T_ struct {
X idl.Nat
Y *idl.Nat
}
ONE := idl.NewNat(uint(1))
t.Run("missing field", func(t *testing.T) {
encoded, err := idl.Marshal([]any{T_{X: ONE, Y: &ONE}})
if err != nil {
t.Fatal(err)
}
var value T
if err := idl.Unmarshal(encoded, []any{&value}); err != nil {
t.Fatal(err)
}
if value.X.BigInt().Int64() != 1 {
t.Error(value.X)
}
})
t.Run("extra field", func(t *testing.T) {
encoded, err := idl.Marshal([]any{T{X: ONE}})
if err != nil {
t.Fatal(err)
}
var value T_
if err := idl.Unmarshal(encoded, []any{&value}); err != nil {
t.Fatal(err)
}
if value.X.BigInt().Int64() != 1 {
t.Error(value.X)
}
if value.Y != nil {
t.Error(value.Y)
}
})
}
3 changes: 3 additions & 0 deletions candid/idl/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ func (record RecordType) unmarshalStruct(raw map[string]any, _v reflect.Value) e
for _, f := range record.Fields {
v, ok := findField(f.Name)
if !ok {
if _, ok := f.Type.(*OptionalType); ok {
continue
}
return NewUnmarshalGoError(raw, _v.Interface())
}
v = v.Addr()
Expand Down
4 changes: 1 addition & 3 deletions candid/internal/candid/grammar.go
Original file line number Diff line number Diff line change
Expand Up @@ -733,9 +733,7 @@ func TupType(p *ast.Parser) (*ast.Node, error) {
),
},
),
op.Optional(
Sp,
),
Ws,
')',
},
ArgType,
Expand Down
2 changes: 1 addition & 1 deletion candid/internal/candid/grammar.pegn
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ActorType <-- '{' Ws (MethType (';' Ws MethType)* ';'? Ws)? '}'
MethType <-- Name Sp? ':' Ws (FuncType / Id)
FuncType <-- TupType (Sp '->' Ws TupType (Sp FuncAnn)?)?
FuncAnn <-- 'oneway' / 'query'
TupType <-- '(' Ws (ArgType (',' Sp ArgType)* (',' Ws)?)? Sp? ')' / ArgType
TupType <-- '(' Ws (ArgType (',' Sp ArgType)* (',' Ws)?)? Ws ')' / ArgType
ArgType <-- (Name Sp? ':' Sp)? DataType
FieldType <-- ((Nat / Name) Sp? ':' Sp)? DataType / Nat / Name
DataType <-- ConsType / RefType / PrimType / Id
Expand Down
21 changes: 21 additions & 0 deletions ic/assetstorage/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,27 @@ func (a Agent) CreateChunk(arg0 struct {
return &r0, nil
}

// CreateChunks calls the "create_chunks" method on the "assetstorage" canister.
func (a Agent) CreateChunks(arg0 struct {
BatchId BatchId `ic:"batch_id" json:"batch_id"`
Content [][]byte `ic:"content" json:"content"`
}) (*struct {
ChunkIds []ChunkId `ic:"chunk_ids" json:"chunk_ids"`
}, error) {
var r0 struct {
ChunkIds []ChunkId `ic:"chunk_ids" json:"chunk_ids"`
}
if err := a.Agent.Call(
a.CanisterId,
"create_chunks",
[]any{arg0},
[]any{&r0},
); err != nil {
return nil, err
}
return &r0, nil
}

// Deauthorize calls the "deauthorize" method on the "assetstorage" canister.
func (a Agent) Deauthorize(arg0 principal.Principal) error {
if err := a.Agent.Call(
Expand Down
6 changes: 1 addition & 5 deletions ic/cmc/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,14 @@ func (a Agent) NotifyTopUp(arg0 NotifyTopUpArg) (*NotifyTopUpResult, error) {
type BlockIndex = uint64

type CanisterSettings struct {
Controller *principal.Principal `ic:"controller,omitempty" json:"controller,omitempty"`
Controllers *[]principal.Principal `ic:"controllers,omitempty" json:"controllers,omitempty"`
ComputeAllocation *idl.Nat `ic:"compute_allocation,omitempty" json:"compute_allocation,omitempty"`
MemoryAllocation *idl.Nat `ic:"memory_allocation,omitempty" json:"memory_allocation,omitempty"`
FreezingThreshold *idl.Nat `ic:"freezing_threshold,omitempty" json:"freezing_threshold,omitempty"`
ReservedCyclesLimit *idl.Nat `ic:"reserved_cycles_limit,omitempty" json:"reserved_cycles_limit,omitempty"`
LogVisibility *LogVisibility `ic:"log_visibility,omitempty" json:"log_visibility,omitempty"`
WasmMemoryLimit *idl.Nat `ic:"wasm_memory_limit,omitempty" json:"wasm_memory_limit,omitempty"`
WasmMemoryThreshold *idl.Nat `ic:"wasm_memory_threshold,omitempty" json:"wasm_memory_threshold,omitempty"`
}

type CreateCanisterArg struct {
Expand All @@ -164,10 +164,6 @@ type CreateCanisterError struct {
RefundAmount idl.Nat `ic:"refund_amount" json:"refund_amount"`
CreateError string `ic:"create_error" json:"create_error"`
} `ic:"Refunded,variant"`
RefundFailed *struct {
CreateError string `ic:"create_error" json:"create_error"`
RefundError string `ic:"refund_error" json:"refund_error"`
} `ic:"RefundFailed,variant"`
}

type CreateCanisterResult struct {
Expand Down
293 changes: 223 additions & 70 deletions ic/governance/agent.go

Large diffs are not rendered by default.

111 changes: 28 additions & 83 deletions ic/ic/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,30 +334,6 @@ func (a Agent) EcdsaPublicKeyCall(arg0 EcdsaPublicKeyArgs) (*agent.CandidAPIRequ
)
}

// FetchCanisterLogs calls the "fetch_canister_logs" method on the "ic" canister.
func (a Agent) FetchCanisterLogs(arg0 FetchCanisterLogsArgs) (*FetchCanisterLogsResult, error) {
var r0 FetchCanisterLogsResult
if err := a.Agent.Query(
a.CanisterId,
"fetch_canister_logs",
[]any{arg0},
[]any{&r0},
); err != nil {
return nil, err
}
return &r0, nil
}

// FetchCanisterLogsQuery creates an indirect representation of the "fetch_canister_logs" method on the "ic" canister.
func (a Agent) FetchCanisterLogsQuery(arg0 FetchCanisterLogsArgs) (*agent.CandidAPIRequest, error) {
return a.Agent.CreateCandidAPIRequest(
agent.RequestTypeQuery,
a.CanisterId,
"fetch_canister_logs",
arg0,
)
}

// HttpRequest calls the "http_request" method on the "ic" canister.
func (a Agent) HttpRequest(arg0 HttpRequestArgs) (*HttpRequestResult, error) {
var r0 HttpRequestResult
Expand Down Expand Up @@ -768,32 +744,12 @@ type CanisterInfoResult struct {
Controllers []principal.Principal `ic:"controllers" json:"controllers"`
}

type CanisterInstallMode struct {
Install *idl.Null `ic:"install,variant"`
Reinstall *idl.Null `ic:"reinstall,variant"`
Upgrade **struct {
SkipPreUpgrade *bool `ic:"skip_pre_upgrade,omitempty" json:"skip_pre_upgrade,omitempty"`
WasmMemoryPersistence *struct {
Keep *idl.Null `ic:"keep,variant"`
Replace *idl.Null `ic:"replace,variant"`
} `ic:"wasm_memory_persistence,omitempty" json:"wasm_memory_persistence,omitempty"`
} `ic:"upgrade,variant"`
}

type CanisterLogRecord struct {
Idx uint64 `ic:"idx" json:"idx"`
TimestampNanos uint64 `ic:"timestamp_nanos" json:"timestamp_nanos"`
Content []byte `ic:"content" json:"content"`
}

type CanisterSettings struct {
Controllers *[]principal.Principal `ic:"controllers,omitempty" json:"controllers,omitempty"`
ComputeAllocation *idl.Nat `ic:"compute_allocation,omitempty" json:"compute_allocation,omitempty"`
MemoryAllocation *idl.Nat `ic:"memory_allocation,omitempty" json:"memory_allocation,omitempty"`
FreezingThreshold *idl.Nat `ic:"freezing_threshold,omitempty" json:"freezing_threshold,omitempty"`
ReservedCyclesLimit *idl.Nat `ic:"reserved_cycles_limit,omitempty" json:"reserved_cycles_limit,omitempty"`
LogVisibility *LogVisibility `ic:"log_visibility,omitempty" json:"log_visibility,omitempty"`
WasmMemoryLimit *idl.Nat `ic:"wasm_memory_limit,omitempty" json:"wasm_memory_limit,omitempty"`
}

type CanisterStatusArgs struct {
Expand All @@ -812,12 +768,6 @@ type CanisterStatusResult struct {
Cycles idl.Nat `ic:"cycles" json:"cycles"`
ReservedCycles idl.Nat `ic:"reserved_cycles" json:"reserved_cycles"`
IdleCyclesBurnedPerDay idl.Nat `ic:"idle_cycles_burned_per_day" json:"idle_cycles_burned_per_day"`
QueryStats struct {
NumCallsTotal idl.Nat `ic:"num_calls_total" json:"num_calls_total"`
NumInstructionsTotal idl.Nat `ic:"num_instructions_total" json:"num_instructions_total"`
RequestPayloadBytesTotal idl.Nat `ic:"request_payload_bytes_total" json:"request_payload_bytes_total"`
ResponsePayloadBytesTotal idl.Nat `ic:"response_payload_bytes_total" json:"response_payload_bytes_total"`
} `ic:"query_stats" json:"query_stats"`
}

type Change struct {
Expand Down Expand Up @@ -855,9 +805,7 @@ type ChangeOrigin struct {
} `ic:"from_canister,variant"`
}

type ChunkHash struct {
Hash []byte `ic:"hash" json:"hash"`
}
type ChunkHash = []byte

type ClearChunkStoreArgs struct {
CanisterId CanisterId `ic:"canister_id" json:"canister_id"`
Expand All @@ -878,8 +826,6 @@ type DefiniteCanisterSettings struct {
MemoryAllocation idl.Nat `ic:"memory_allocation" json:"memory_allocation"`
FreezingThreshold idl.Nat `ic:"freezing_threshold" json:"freezing_threshold"`
ReservedCyclesLimit idl.Nat `ic:"reserved_cycles_limit" json:"reserved_cycles_limit"`
LogVisibility LogVisibility `ic:"log_visibility" json:"log_visibility"`
WasmMemoryLimit idl.Nat `ic:"wasm_memory_limit" json:"wasm_memory_limit"`
}

type DeleteCanisterArgs struct {
Expand Down Expand Up @@ -908,14 +854,6 @@ type EcdsaPublicKeyResult struct {
ChainCode []byte `ic:"chain_code" json:"chain_code"`
}

type FetchCanisterLogsArgs struct {
CanisterId CanisterId `ic:"canister_id" json:"canister_id"`
}

type FetchCanisterLogsResult struct {
CanisterLogRecords []CanisterLogRecord `ic:"canister_log_records" json:"canister_log_records"`
}

type HttpHeader struct {
Name string `ic:"name" json:"name"`
Value string `ic:"value" json:"value"`
Expand Down Expand Up @@ -945,34 +883,41 @@ type HttpRequestResult struct {
}

type InstallChunkedCodeArgs struct {
Mode CanisterInstallMode `ic:"mode" json:"mode"`
TargetCanister CanisterId `ic:"target_canister" json:"target_canister"`
StoreCanister *CanisterId `ic:"store_canister,omitempty" json:"store_canister,omitempty"`
ChunkHashesList []ChunkHash `ic:"chunk_hashes_list" json:"chunk_hashes_list"`
WasmModuleHash []byte `ic:"wasm_module_hash" json:"wasm_module_hash"`
Arg []byte `ic:"arg" json:"arg"`
SenderCanisterVersion *uint64 `ic:"sender_canister_version,omitempty" json:"sender_canister_version,omitempty"`
Mode struct {
Install *idl.Null `ic:"install,variant"`
Reinstall *idl.Null `ic:"reinstall,variant"`
Upgrade **struct {
SkipPreUpgrade *bool `ic:"skip_pre_upgrade,omitempty" json:"skip_pre_upgrade,omitempty"`
} `ic:"upgrade,variant"`
} `ic:"mode" json:"mode"`
TargetCanister CanisterId `ic:"target_canister" json:"target_canister"`
StorageCanister *CanisterId `ic:"storage_canister,omitempty" json:"storage_canister,omitempty"`
ChunkHashesList []ChunkHash `ic:"chunk_hashes_list" json:"chunk_hashes_list"`
WasmModuleHash []byte `ic:"wasm_module_hash" json:"wasm_module_hash"`
Arg []byte `ic:"arg" json:"arg"`
SenderCanisterVersion *uint64 `ic:"sender_canister_version,omitempty" json:"sender_canister_version,omitempty"`
}

type InstallCodeArgs struct {
Mode CanisterInstallMode `ic:"mode" json:"mode"`
CanisterId CanisterId `ic:"canister_id" json:"canister_id"`
WasmModule WasmModule `ic:"wasm_module" json:"wasm_module"`
Arg []byte `ic:"arg" json:"arg"`
SenderCanisterVersion *uint64 `ic:"sender_canister_version,omitempty" json:"sender_canister_version,omitempty"`
}

type LogVisibility struct {
Controllers *idl.Null `ic:"controllers,variant"`
Public *idl.Null `ic:"public,variant"`
Mode struct {
Install *idl.Null `ic:"install,variant"`
Reinstall *idl.Null `ic:"reinstall,variant"`
Upgrade **struct {
SkipPreUpgrade *bool `ic:"skip_pre_upgrade,omitempty" json:"skip_pre_upgrade,omitempty"`
} `ic:"upgrade,variant"`
} `ic:"mode" json:"mode"`
CanisterId CanisterId `ic:"canister_id" json:"canister_id"`
WasmModule WasmModule `ic:"wasm_module" json:"wasm_module"`
Arg []byte `ic:"arg" json:"arg"`
SenderCanisterVersion *uint64 `ic:"sender_canister_version,omitempty" json:"sender_canister_version,omitempty"`
}

type MillisatoshiPerByte = uint64

type NodeMetrics struct {
NodeId principal.Principal `ic:"node_id" json:"node_id"`
NumBlocksProposedTotal uint64 `ic:"num_blocks_proposed_total" json:"num_blocks_proposed_total"`
NumBlockFailuresTotal uint64 `ic:"num_block_failures_total" json:"num_block_failures_total"`
NodeId principal.Principal `ic:"node_id" json:"node_id"`
NumBlocksTotal uint64 `ic:"num_blocks_total" json:"num_blocks_total"`
NumBlockFailuresTotal uint64 `ic:"num_block_failures_total" json:"num_block_failures_total"`
}

type NodeMetricsHistoryArgs struct {
Expand Down
8 changes: 4 additions & 4 deletions ic/icpledger/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,8 @@ type Icrc21ConsentMessage struct {
}

type Icrc21ConsentMessageMetadata struct {
Language string `ic:"language" json:"language"`
Language string `ic:"language" json:"language"`
UtcOffsetMinutes *int16 `ic:"utc_offset_minutes,omitempty" json:"utc_offset_minutes,omitempty"`
}

type Icrc21ConsentMessageRequest struct {
Expand Down Expand Up @@ -855,9 +856,8 @@ type TransferResult struct {
}

type UpgradeArgs struct {
MaximumNumberOfAccounts *uint64 `ic:"maximum_number_of_accounts,omitempty" json:"maximum_number_of_accounts,omitempty"`
Icrc1MintingAccount *Account `ic:"icrc1_minting_account,omitempty" json:"icrc1_minting_account,omitempty"`
FeatureFlags *FeatureFlags `ic:"feature_flags,omitempty" json:"feature_flags,omitempty"`
Icrc1MintingAccount *Account `ic:"icrc1_minting_account,omitempty" json:"icrc1_minting_account,omitempty"`
FeatureFlags *FeatureFlags `ic:"feature_flags,omitempty" json:"feature_flags,omitempty"`
}

type Value struct {
Expand Down
Loading

0 comments on commit 5624e71

Please sign in to comment.