Nachdem ich die Datei " instructions.gogeth
" geändert habe, kann ich die Ausführungszeit einzelner Opcodes sehen, sie sieht so aus:
Meine Interpretation dieser Ausgabe ist, dass sie die Ausführung aller Verträge darstellt, von denen mein laufender Knoten hört, also alle Transaktionen des gesamten Netzwerks (ropsten testnet).
Die Änderungen, die ich am geth
Client vorgenommen habe, sind hier:
func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// begin execution time tracking
var startTime = time.Now().UnixNano();
x, y := stack.pop(), stack.pop()
stack.push(math.U256(x.Add(x, y)))
evm.interpreter.intPool.put(y)
// log ellapsed execution time
fmt.Println("execute opAdd consume = ",(time.Now().UnixNano() - startTime))
return nil, nil
}
Ich möchte diese Ausgabe irgendwie einschränken, sodass sie nur für Verträge/Funktionen angezeigt wird, die ich von meinem lokalen Knoten aus bereitstelle, dh diejenigen, die ich selbst anrufe.
Was ich jetzt suche, sind einige Gedanken darüber, wie man das macht – nicht einmal unbedingt eine Lösung – obwohl das großartig wäre – aber sogar Orte, an denen man anfangen kann – z. all diese Sachen, all diese Ideen wären sehr cool und hilfreich!
Ich lese immer wieder, dass vm die Quelle aufruft, aber ich kann keinen gültigen Weg finden, um die Ausführungszeit einer einzelnen Funktion (manchmal ein Aufruf einer anderen) zu berechnen. Wenn wir einen Vertrag bereitstellen, wird dadurch eine Transaktion erstellt, input
das Attribut ist der Bytecode des Vertrags. Wenn wir eine Methode aufrufen, generieren Sie zuerst die Signatur der Methode (z. B.: 0xe079bdf1), finden Sie diese Methode dann anhand der Signatur und führen Sie sie aus. Die einzige Möglichkeit, eine Antwort zu erhalten, ist vm opcode, und ich hatte Solidity Assembly gelesen und viele Methodenaufrufe getestet, viele opcodes analysiert, aber ich kann keine Antwort finden, es ist so schwer für mich. Opcodes Anzeige folgt:
.data
0:
.code
PUSH 60 contract Wallet {\n
mappin...
PUSH 40 contract Wallet {\n
mappin...
MSTORE contract Wallet {\n
mappin...
PUSH 0 contract Wallet {\n
mappin...
CALLDATALOAD contract Wallet {\n
mappin...
PUSH 100000000000000000000000000000000000000000000000000000000 contract Wallet {\n
mappin...
SWAP1 contract Wallet {\n
mappin...
DIV contract Wallet {\n
mappin...
PUSH FFFFFFFF contract Wallet {\n
mappin...
AND
......
Vielleicht gibt es keine Antwort, vielleicht ist meine Analysemethode falsch. Wenn jemand die richtige Antwort weiß, sagen Sie es mir bitte. Hoffe es hilft~
Okay, na ja, es ist eine Art Hack, aber ... ich glaube, ich habe es verstanden. So geht's:
Mir wurde klar, dass wir jedes Mal, wenn wir einen Vertrag lokal aufrufen, was ich zu verfolgen versuche, in der Konsole in Form von davon hören "Submitted transaction"
:
Was ich getan habe, war ein boolesches Flag in die Funktion zu setzen, die diesen Text hervorruft "Submitted transaction"
, dieser boolsche Wert ist sozusagen der " Einstiegspunkt/Gateway " für einen Wrapper des Zeiterfassungscodes.
So sieht es in der aus go-ethereum/core/vm/instructions.go
, wo wir die Ausführungszeit verfolgen:
var (
bigZero = new(big.Int)
startTime = time.Now().UnixNano();
)
func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// wrap the logging in a check
if OpcodeTrigger {
// begin execution time tracking
startTime = time.Now().UnixNano();
}
x, y := stack.pop(), stack.pop()
stack.push(math.U256(x.Add(x, y)))
evm.interpreter.intPool.put(y)
// wrap the logging in a check
if OpcodeTrigger {
// now set the boolean flag back to false
OpcodeTrigger = false
// log ellapsed execution time
fmt.Println("execute opAdd consume = ",(time.Now().UnixNano() - startTime))
}
return nil, nil
}
Ist also niedriger als der Code, der den Text go-ethereum/core/vm/instructions.go
ausspuckt, das ist in , weshalb wir dort den bool definieren. Wenn Sie versuchen, den bool in zu definieren , funktioniert es nicht."Submitted transaction"
go-ethereum/internal/ethapi/api.go
go-ethereum/internal/ethapi/api.go
So setzen wir den bool in go-ethereum/internal/ethapi/api.go
:
// submitTransaction is a helper function that submits tx to txPool and logs a message.
func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) {
if err := b.SendTx(ctx, tx); err != nil {
return common.Hash{}, err
}
if tx.To() == nil {
signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number())
from, _ := types.Sender(signer, tx)
addr := crypto.CreateAddress(from, tx.Nonce())
log.Info("Submitted contract creation", "fullhash", tx.Hash().Hex(), "contract", addr.Hex())
} else {
// flag for opcode execution time tracking
vm.OpcodeTrigger = true
log.Info("Submitted transaction", "fullhash", tx.Hash().Hex(), "recipient", tx.To())
}
return tx.Hash(), nil
}
Endlich scheinen wir das zu haben, was im OP angegeben wurde, oder zumindest eine vernünftige Annäherung davon, dh:
INFO [08-09|20:16:38] Submitted transaction fullhash=0xa55357ec2488604d580cbdc56373f40ea16dc4cb6aec0ea41a3836c696cc3c17 recipient=0x8705C513da621a16fd1dEFc9dE8aE7CDEAD01Fb8
execute opAdd consume = 1063
Sie können den Code und meine Antwort darauf auf meinem GitHub auslesen !
Sehr interessant zu wissen, was ihr von dieser Lösung haltet.
opAdd
Anweisungen. und manchmal kann eine Methode viele andere Funktionen aufrufen usw.
smatthewenglisch
smatthewenglisch