diff --git a/app/abi/manager.go b/app/abi/manager.go index 7eb0602..2d2447a 100644 --- a/app/abi/manager.go +++ b/app/abi/manager.go @@ -31,6 +31,10 @@ func NewAbiManager(rdb *redis.Client, api *eos.API, id string) *AbiManager { } } +func (mgr *AbiManager) SetAbi(account eos.AccountName, abi *eos.ABI) error { + return mgr.cache.Set(string(account), abi, time.Hour) +} + func (mgr *AbiManager) GetAbi(account eos.AccountName) (*eos.ABI, error) { key := string(account) @@ -42,7 +46,7 @@ func (mgr *AbiManager) GetAbi(account eos.AccountName) (*eos.ABI, error) { } abi = &resp.ABI - err = mgr.cache.Set(key, abi, time.Hour) + err = mgr.SetAbi(account, abi) if err != nil { return nil, fmt.Errorf("cache: %s", err) } diff --git a/app/ship_processor.go b/app/ship_processor.go index 09cd146..13443a9 100644 --- a/app/ship_processor.go +++ b/app/ship_processor.go @@ -1,6 +1,7 @@ package app import ( + "encoding/hex" "encoding/json" "github.com/eosswedenorg/thalos/api" @@ -32,14 +33,18 @@ type ShipProcessor struct { writer api.Writer shipStream *shipclient.Stream encode message.Encoder + + // System contract ("eosio" per default) + syscontract eos.AccountName } func SpawnProccessor(shipStream *shipclient.Stream, writer api.Writer, abi *abi.AbiManager, codec message.Codec) *ShipProcessor { processor := &ShipProcessor{ - abi: abi, - writer: writer, - shipStream: shipStream, - encode: logDecoratedEncoder(codec.Encoder), + abi: abi, + writer: writer, + shipStream: shipStream, + encode: logDecoratedEncoder(codec.Encoder), + syscontract: eos.AccountName("eosio"), } // Attach handlers @@ -75,6 +80,33 @@ func decode(abi *eos.ABI, act *ship.Action, v any) error { return json.Unmarshal(jsondata, v) } +func (processor *ShipProcessor) updateAbiFromAction(act *ship.Action) error { + ABI, err := processor.abi.GetAbi(processor.syscontract) + if err != nil { + return err + } + + set_abi := struct { + Abi string + Account eos.AccountName + }{} + if err := decode(ABI, act, &set_abi); err != nil { + return err + } + + binary_abi, err := hex.DecodeString(set_abi.Abi) + if err != nil { + return err + } + + contract_abi := eos.ABI{} + if err = eos.UnmarshalBinary(binary_abi, &contract_abi); err != nil { + return err + } + + return processor.abi.SetAbi(set_abi.Account, &contract_abi) +} + func (processor *ShipProcessor) processBlock(block *ship.GetBlocksResultV0) { if block.ThisBlock.BlockNum%100 == 0 { log.Infof("Current: %d, Head: %d", block.ThisBlock.BlockNum, block.Head.BlockNum) @@ -120,6 +152,14 @@ func (processor *ShipProcessor) processBlock(block *ship.GetBlocksResultV0) { act_trace = actionTraceVar.Impl.(*ship.ActionTraceV1) } + // Check if actions updates an abi. + if act_trace.Act.Account == processor.syscontract && act_trace.Act.Name == eos.ActionName("setabi") { + err := processor.updateAbiFromAction(act_trace.Act) + if err != nil { + log.WithError(err).Warn("Failed to update abi") + } + } + act := message.ActionTrace{ TxID: trace.ID.String(), BlockNum: block.Block.BlockNumber(),