diff --git a/chain/event.go b/chain/event.go index 0fc8162..6f87da0 100755 --- a/chain/event.go +++ b/chain/event.go @@ -8,6 +8,7 @@ package chain import ( + "bytes" "fmt" "reflect" "strconv" @@ -16,8 +17,10 @@ import ( "github.com/CESSProject/cess-go-sdk/core/event" "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/CESSProject/cess-go-sdk/utils" + "github.com/centrifuge/go-substrate-rpc-client/v4/registry/parser" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/pkg/errors" + "github.com/vedhavyas/go-subkey/scale" ) func (c *chainClient) DecodeEventNameFromBlock(block uint64) ([]string, error) { @@ -946,8 +949,8 @@ func (c *chainClient) RetrieveEvent_FileBank_CalculateReport(blockhash types.Has return result, errors.Errorf("failed: no %s event found", event.FileBankCalculateReport) } -func (c *chainClient) RetrieveEvent_Sminer_UpdataIp(blockhash types.Hash) (event.Event_UpdataIp, error) { - var result event.Event_UpdataIp +func (c *chainClient) RetrieveEvent_Sminer_UpdataIp(blockhash types.Hash) (event.Sminer_UpdatePeerId, error) { + var result event.Sminer_UpdatePeerId events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err @@ -1843,3 +1846,265 @@ func (c *chainClient) RetrieveAllEventFromBlock(blockhash types.Hash) ([]string, } return systemEvents, extrinsicsEvents, nil } + +func (c *chainClient) RetrieveBlock(blocknumber uint64) ([]string, []event.ExtrinsicsInfo, []event.TransferInfo, string, string, string, string, int64, error) { + var timeUnixMilli int64 + var systemEvents = make([]string, 0) + var extrinsicsInfo = make([]event.ExtrinsicsInfo, 0) + var transferInfo = make([]event.TransferInfo, 0) + blockhash, err := c.GetSubstrateAPI().RPC.Chain.GetBlockHash(blocknumber) + if err != nil { + return systemEvents, extrinsicsInfo, transferInfo, "", "", "", "", 0, err + } + block, err := c.GetSubstrateAPI().RPC.Chain.GetBlock(blockhash) + if err != nil { + return systemEvents, extrinsicsInfo, transferInfo, "", "", "", "", 0, err + } + events, err := c.eventRetriever.GetEvents(blockhash) + if err != nil { + return systemEvents, extrinsicsInfo, transferInfo, "", "", "", "", 0, err + } + var eventsBuf = make([]string, 0) + var signer string + var fee string + // var from string + // var to string + // var amount string + var ok bool + var name string + var preExtName string + var result bool + for _, e := range events { + if e.Phase.IsApplyExtrinsic { + if name, ok = ExtrinsicsName[block.Block.Extrinsics[e.Phase.AsApplyExtrinsic].Method.CallIndex]; ok { + if name == ExtName_Timestamp_set { + timeDecoder := scale.NewDecoder(bytes.NewReader(block.Block.Extrinsics[e.Phase.AsApplyExtrinsic].Method.Args)) + timestamp, err := timeDecoder.DecodeUintCompact() + if err != nil { + return systemEvents, extrinsicsInfo, transferInfo, "", "", "", "", 0, err + } + timeUnixMilli = timestamp.Int64() + extrinsicsInfo = append(extrinsicsInfo, event.ExtrinsicsInfo{ + Name: name, + Events: []string{e.Name}, + Result: true, + }) + preExtName = name + continue + } + if e.Name == event.BalancesWithdraw { + if len(eventsBuf) > 0 { + result = false + for i := 0; i < len(eventsBuf); i++ { + if eventsBuf[i] == event.SystemExtrinsicSuccess { + result = true + break + } + if eventsBuf[i] == event.SystemExtrinsicFailed { + result = false + break + } + } + extrinsicsInfo = append(extrinsicsInfo, event.ExtrinsicsInfo{ + Name: preExtName, + Signer: signer, + FeePaid: fee, + Result: result, + Events: append(make([]string, 0), eventsBuf...), + }) + preExtName = name + eventsBuf = make([]string, 0) + } + } + eventsBuf = append(eventsBuf, e.Name) + if e.Name == event.TransactionPaymentTransactionFeePaid { + signer, fee, _ = parseSignerAndFeePaidFromEvent(e) + } + if e.Name == event.BalancesTransfer { + // fmt.Println("find transfer event") + // from, to, amount, _ = parseTransferInfoFromEvent(e) + // transferInfo = append(transferInfo, event.TransferInfo{ + // From: from, + // To: to, + // Amount: amount, + // Result: true, + // }) + transfers, err := c.parseTransferInfoFromBlock(blockhash) + if err != nil { + return systemEvents, extrinsicsInfo, transferInfo, "", "", "", "", 0, err + } + if len(transfers) > 0 { + transferInfo = append(transferInfo, transfers...) + } + } + } + } else { + systemEvents = append(systemEvents, e.Name) + } + } + if len(eventsBuf) > 0 { + result = false + for i := 0; i < len(eventsBuf); i++ { + if eventsBuf[i] == event.SystemExtrinsicSuccess { + result = true + break + } + if eventsBuf[i] == event.SystemExtrinsicFailed { + result = false + break + } + } + extrinsicsInfo = append(extrinsicsInfo, event.ExtrinsicsInfo{ + Name: name, + Signer: signer, + FeePaid: fee, + Result: result, + Events: append(make([]string, 0), eventsBuf...), + }) + } + return systemEvents, extrinsicsInfo, transferInfo, blockhash.Hex(), block.Block.Header.ParentHash.Hex(), block.Block.Header.ExtrinsicsRoot.Hex(), block.Block.Header.StateRoot.Hex(), timeUnixMilli, nil +} + +func parseSignerAndFeePaidFromEvent(e *parser.Event) (string, string, error) { + if e == nil { + return "", "", errors.New("event is nil") + } + if e.Name != event.TransactionPaymentTransactionFeePaid { + return "", "", fmt.Errorf("event is not %s", event.TransactionPaymentTransactionFeePaid) + } + var signAcc string + var fee string + for _, v := range e.Fields { + val := reflect.ValueOf(v.Value) + if reflect.TypeOf(v.Value).Kind() == reflect.Slice { + signAcc = parseAccount(val) + } + if reflect.TypeOf(v.Value).Kind() == reflect.Struct { + if v.Name == "actual_fee" { + fee = Explicit(val, 0) + } + } + } + return signAcc, fee, nil +} + +func parseAccount(v reflect.Value) string { + var acc string + if v.Len() > 0 { + allValue := fmt.Sprintf("%v", v.Index(0)) + temp := strings.Split(allValue, "] ") + puk := make([]byte, types.AccountIDLen) + for _, v := range temp { + if strings.Count(v, " ") == (types.AccountIDLen - 1) { + subValue := strings.TrimPrefix(v, "[") + ids := strings.Split(subValue, " ") + if len(ids) != types.AccountIDLen { + continue + } + for kk, vv := range ids { + intv, _ := strconv.Atoi(vv) + puk[kk] = byte(intv) + } + } + } + acc, _ = utils.EncodePublicKeyAsCessAccount(puk) + } + return acc +} + +func Explicit(v reflect.Value, depth int) string { + var fee string + if v.CanInterface() { + t := v.Type() + switch v.Kind() { + case reflect.Ptr: + fee = Explicit(v.Elem(), depth) + case reflect.Struct: + //fmt.Printf(strings.Repeat("\t", depth)+"%v %v {\n", t.Name(), t.Kind()) + for i := 0; i < v.NumField(); i++ { + f := v.Field(i) + if f.Kind() == reflect.Struct || f.Kind() == reflect.Ptr { + //fmt.Printf(strings.Repeat("\t", depth+1)+"%s %s : \n", t.Field(i).Name, f.Type()) + fee = Explicit(f, depth+2) + } else { + if f.CanInterface() { + //fmt.Printf(strings.Repeat("\t", depth+1)+"%s %s : %v \n", t.Field(i).Name, f.Type(), f.Interface()) + } else { + if t.Field(i).Name == "abs" { + val := fmt.Sprintf("%v", f) + return val[1 : len(val)-1] + } + //fmt.Printf(strings.Repeat("\t", depth+1)+"%s %s : %v \n", t.Field(i).Name, f.Type(), f) + } + } + } + //fmt.Println(strings.Repeat("\t", depth) + "}") + } + } + // else { + // fmt.Printf(strings.Repeat("\t", depth)+"%+v\n", v) + // } + return fee +} + +func (c *chainClient) parseTransferInfoFromBlock(blockhash types.Hash) ([]event.TransferInfo, error) { + var transferEvents = make([]event.TransferInfo, 0) + var data types.StorageDataRaw + ok, err := c.GetSubstrateAPI().RPC.State.GetStorage(c.GetKeyEvents(), &data, blockhash) + if err != nil { + return transferEvents, err + } + var from string + var to string + if ok { + events := event.EventRecords{} + err = types.EventRecordsRaw(data).DecodeEventRecords(c.GetMetadata(), &events) + if err != nil { + return transferEvents, err + } + for _, e := range events.Balances_Transfer { + from, _ = utils.EncodePublicKeyAsCessAccount(e.From[:]) + to, _ = utils.EncodePublicKeyAsCessAccount(e.To[:]) + transferEvents = append(transferEvents, event.TransferInfo{ + From: from, + To: to, + Amount: e.Value.String(), + Result: true, + }) + } + } + return transferEvents, nil +} + +func parseTransferInfoFromEvent(e *parser.Event) (string, string, string, error) { + if e == nil { + return "", "", "", errors.New("event is nil") + } + if e.Name != event.BalancesTransfer { + return "", "", "", fmt.Errorf("event is not %s", event.BalancesTransfer) + } + var from string + var to string + var amount string + for _, v := range e.Fields { + k := reflect.TypeOf(v.Value).Kind() + val := reflect.ValueOf(v.Value) + fmt.Println("k: ", k) + fmt.Println("v.Name: ", v.Name) + if k == reflect.Slice { + if strings.Contains(v.Name, "from") { + from = parseAccount(val) + } + if strings.Contains(v.Name, "to") { + to = parseAccount(val) + } + } + if k == reflect.Struct { + if v.Name == "amount" { + amount = Explicit(val, 0) + } + } + } + fmt.Println("amount: ", amount) + return from, to, amount, nil +} diff --git a/core/event/events.go b/core/event/events.go index 4e74689..264060e 100755 --- a/core/event/events.go +++ b/core/event/events.go @@ -65,10 +65,9 @@ type Event_SubmitServiceVerifyResult struct { // ------------------------Sminer------------------------ type Event_Registered struct { - Phase types.Phase - Acc types.AccountID - StakingVal types.U128 - Topics []types.Hash + Phase types.Phase + Acc types.AccountID + Topics []types.Hash } type Event_RegisterPoisKey struct { @@ -132,7 +131,7 @@ type Event_UpdataBeneficiary struct { Topics []types.Hash } -type Event_UpdataIp struct { +type Sminer_UpdatePeerId struct { Phase types.Phase Acc types.AccountID Old pattern.PeerId @@ -332,7 +331,7 @@ type Event_MasterKeyLaunched struct { Topics []types.Hash } -type Event_KeyfairyAdded struct { +type Event_WorkerAdded struct { Phase types.Phase Pubkey pattern.WorkerPublicKey AttestationProvider types.Option[types.U8] @@ -340,6 +339,12 @@ type Event_KeyfairyAdded struct { Topics []types.Hash } +type Event_KeyfairyAdded struct { + Phase types.Phase + Pubkey pattern.WorkerPublicKey + Topics []types.Hash +} + type Event_WorkerUpdated struct { Phase types.Phase Pubkey pattern.WorkerPublicKey @@ -412,6 +417,44 @@ type Event_ElectionFinalized struct { Topics []types.Hash } +type Event_ServiceFeePaid struct { + Phase types.Phase + Who types.AccountID + ActualFee types.U128 + ExpectedFee types.U128 + Topics []types.Hash +} + +type Event_CallDone struct { + Phase types.Phase + Who types.AccountID + CallResult Result + Topics []types.Hash +} + +type Result struct { + Index types.U8 + ResultOk ResultOk +} + +type ResultOk struct { + ActualWeight types.Option[ActualWeightType] + PaysFee types.U8 +} + +type ActualWeightType struct { + RefTime types.U64 + ProofSize types.U64 +} + +type Event_TransactionFeePaid struct { + Phase types.Phase + Who types.AccountID + ActualFee types.U128 + Tip types.U128 + Topics []types.Hash +} + // ******************************************************* type ElectionScore struct { /// The minimal winner, in terms of total backing stake. @@ -490,7 +533,7 @@ type EventRecords struct { Sminer_IncreaseCollateral []Event_IncreaseCollateral Sminer_Deposit []Event_Deposit Sminer_UpdataBeneficiary []Event_UpdataBeneficiary - Sminer_UpdataIp []Event_UpdataIp + Sminer_UpdatePeerId []Sminer_UpdatePeerId Sminer_Receive []Event_Receive Sminer_MinerExitPrep []Event_MinerExitPrep Sminer_Withdraw []Event_Withdraw @@ -506,6 +549,7 @@ type EventRecords struct { // TeeWorker TeeWorker_Exit []Event_Exit TeeWorker_MasterKeyLaunched []Event_MasterKeyLaunched + TeeWorker_WorkerAdded []Event_WorkerAdded TeeWorker_KeyfairyAdded []Event_KeyfairyAdded TeeWorker_WorkerUpdated []Event_WorkerUpdated TeeWorker_MasterKeyRotated []Event_MasterKeyRotated @@ -514,7 +558,24 @@ type EventRecords struct { // system ElectionProviderMultiPhase_ElectionFinalized []Event_ElectionFinalized - + EvmAccountMapping_ServiceFeePaid []Event_ServiceFeePaid + EvmAccountMapping_CallDone []Event_CallDone + EvmAccountMapping_TransactionFeePaid []Event_TransactionFeePaid // system-gsrpc types.EventRecords } + +type ExtrinsicsInfo struct { + Name string + Signer string + FeePaid string + Result bool + Events []string +} + +type TransferInfo struct { + From string + To string + Amount string + Result bool +} diff --git a/core/event/eventsName.go b/core/event/eventsName.go index 9718743..4c3a5e4 100755 --- a/core/event/eventsName.go +++ b/core/event/eventsName.go @@ -72,4 +72,13 @@ const ( TeeWorkerMasterKeyRotated = "TeeWorker.MasterKeyRotated" TeeWorkerMasterKeyRotationFailed = "TeeWorker.MasterKeyRotationFailed" TeeWorkerMinimumCesealVersionChangedTo = "TeeWorker.MinimumCesealVersionChangedTo" + + // + TransactionPaymentTransactionFeePaid = "TransactionPayment.TransactionFeePaid" + // + BalancesWithdraw = "Balances.Withdraw" + BalancesTransfer = "Balances.Transfer" + // + SystemExtrinsicSuccess = "System.ExtrinsicSuccess" + SystemExtrinsicFailed = "System.ExtrinsicFailed" ) diff --git a/core/sdk/sdk.go b/core/sdk/sdk.go index 36dc4c8..0f9caa3 100755 --- a/core/sdk/sdk.go +++ b/core/sdk/sdk.go @@ -393,7 +393,7 @@ type SDK interface { // RetrieveEvent_Sminer_RegisterPoisKey(blockhash types.Hash) (event.Event_RegisterPoisKey, error) // - RetrieveEvent_Sminer_UpdataIp(blockhash types.Hash) (event.Event_UpdataIp, error) + RetrieveEvent_Sminer_UpdataIp(blockhash types.Hash) (event.Sminer_UpdatePeerId, error) // RetrieveEvent_Sminer_UpdataBeneficiary(blockhash types.Hash) (event.Event_UpdataBeneficiary, error) // @@ -426,7 +426,8 @@ type SDK interface { //RetrieveAllEvent(blockhash types.Hash) ([]string, []string, error) // RetrieveAllEventFromBlock(blockhash types.Hash) ([]string, map[string][]string, error) - + // + RetrieveBlock(blocknumber uint64) ([]string, []event.ExtrinsicsInfo, []event.TransferInfo, string, string, string, string, int64, error) // InitExtrinsicsName() error } diff --git a/example/parseEvent/parseevent.go b/example/parseEvent/parseevent.go index 11ed9d8..b1f03f7 100755 --- a/example/parseEvent/parseevent.go +++ b/example/parseEvent/parseevent.go @@ -6,6 +6,8 @@ import ( "time" cess "github.com/CESSProject/cess-go-sdk" + "github.com/CESSProject/cess-go-sdk/core/event" + "github.com/centrifuge/go-substrate-rpc-client/v4/types" ) // Substrate well-known mnemonic: @@ -15,28 +17,77 @@ var MY_MNEMONIC = "bottom drive obey lake curtain smoke basket hold race lonely var RPC_ADDRS = []string{ //devnet - "wss://devnet-rpc.cess.cloud/ws/", + //"wss://devnet-rpc.cess.cloud/ws/", //testnet "wss://testnet-rpc0.cess.cloud/ws/", "wss://testnet-rpc1.cess.cloud/ws/", "wss://testnet-rpc2.cess.cloud/ws/", } +type MyEvent struct { + Sminer_FaucetTopUpMoney []event.Event_FaucetTopUpMoney + types.EventRecords +} + func main() { sdk, err := cess.New( context.Background(), cess.ConnectRpcAddrs(RPC_ADDRS), - cess.Mnemonic(MY_MNEMONIC), + //cess.Mnemonic(MY_MNEMONIC), cess.TransactionTimeout(time.Second*10), ) if err != nil { panic(err) } + sdk.InitExtrinsicsName() + // RetrieveEvent_FileBank_CalculateReport - bhash, err := sdk.GetSubstrateAPI().RPC.Chain.GetBlockHash(72745) + // bhash, err := sdk.GetSubstrateAPI().RPC.Chain.GetBlockHash(713) + // if err != nil { + // panic(err) + // } + // var data types.StorageDataRaw + // key, err := types.CreateStorageKey(sdk.GetMetadata(), "System", "Events", nil, nil) + // if err != nil { + // panic(err) + // } + // ok, err := sdk.GetSubstrateAPI().RPC.State.GetStorage(key, &data, bhash) + // if err != nil { + // panic(err) + // } + + // if ok { + // events := MyEvent{} + // err = types.EventRecordsRaw(data).DecodeEventRecords(sdk.GetMetadata(), &events) + // if err != nil { + // panic(err) + // } + + // for _, e := range events.Balances_Transfer { + // fmt.Printf("Balances:Transfer:: (phase=%#v)\n", e.Phase) + // fmt.Printf("\t%v, %v, %v\n", e.From, e.To, e.Value) + // } + // } + + //fmt.Println(sdk.RetrieveAllEventFromBlock(bhash)) + fmt.Println(" --------- ") + sysEvents, extrinsics, transferInfo, blockhash, preHash, extHash, stHash, t, err := sdk.RetrieveBlock(11921) if err != nil { panic(err) } - - fmt.Println(sdk.RetrieveEvent_FileBank_CalculateReport(bhash)) + fmt.Println("system events: ", sysEvents) + fmt.Println("extrinsics:") + for k, v := range extrinsics { + fmt.Println(" ", k, ": ", v.Name) + fmt.Println(" Singer: ", v.Signer) + fmt.Println(" FeePaid: ", v.FeePaid) + fmt.Println(" Events: ", v.Events) + } + fmt.Println("transfer info: ", transferInfo) + fmt.Println("blockhash: ", blockhash) + fmt.Println("preHash: ", preHash) + fmt.Println("extHash: ", extHash) + fmt.Println("stHash: ", stHash) + fmt.Println("timpstamp: ", t) + //fmt.Println(sdk.RetrieveEvent_FileBank_CalculateReport(bhash)) }