mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-02-24 04:13:16 +00:00
Compare commits
10 Commits
with-deriv
...
testsLoctT
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51b6534a78 | ||
|
|
9e2b3844c2 | ||
|
|
777e5d539a | ||
|
|
26ae0c8bd8 | ||
|
|
4d36f2c561 | ||
|
|
9161ea39b2 | ||
|
|
87a2e4d002 | ||
|
|
4f4a8934e7 | ||
|
|
16ba2bd312 | ||
|
|
4125188686 |
@@ -4,6 +4,7 @@ package appmessage
|
||||
// its respective RPC message
|
||||
type EstimateNetworkHashesPerSecondRequestMessage struct {
|
||||
baseMessage
|
||||
StartHash string
|
||||
WindowSize uint32
|
||||
}
|
||||
|
||||
@@ -13,8 +14,9 @@ func (msg *EstimateNetworkHashesPerSecondRequestMessage) Command() MessageComman
|
||||
}
|
||||
|
||||
// NewEstimateNetworkHashesPerSecondRequestMessage returns a instance of the message
|
||||
func NewEstimateNetworkHashesPerSecondRequestMessage(windowSize uint32) *EstimateNetworkHashesPerSecondRequestMessage {
|
||||
func NewEstimateNetworkHashesPerSecondRequestMessage(startHash string, windowSize uint32) *EstimateNetworkHashesPerSecondRequestMessage {
|
||||
return &EstimateNetworkHashesPerSecondRequestMessage{
|
||||
StartHash: startHash,
|
||||
WindowSize: windowSize,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ type fakeRelayInvsContext struct {
|
||||
rwLock sync.RWMutex
|
||||
}
|
||||
|
||||
func (f *fakeRelayInvsContext) EstimateNetworkHashesPerSecond(windowSize int) (uint64, error) {
|
||||
func (f *fakeRelayInvsContext) EstimateNetworkHashesPerSecond(startHash *externalapi.DomainHash, windowSize int) (uint64, error) {
|
||||
panic(errors.Errorf("called unimplemented function from test '%s'", f.testName))
|
||||
}
|
||||
|
||||
|
||||
@@ -3,19 +3,35 @@ package rpchandlers
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||
)
|
||||
|
||||
// HandleEstimateNetworkHashesPerSecond handles the respectively named RPC command
|
||||
func HandleEstimateNetworkHashesPerSecond(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
||||
func HandleEstimateNetworkHashesPerSecond(
|
||||
context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
||||
|
||||
estimateNetworkHashesPerSecondRequest := request.(*appmessage.EstimateNetworkHashesPerSecondRequestMessage)
|
||||
|
||||
windowSize := int(estimateNetworkHashesPerSecondRequest.WindowSize)
|
||||
networkHashesPerSecond, err := context.Domain.Consensus().EstimateNetworkHashesPerSecond(windowSize)
|
||||
startHash := model.VirtualBlockHash
|
||||
if estimateNetworkHashesPerSecondRequest.StartHash != "" {
|
||||
var err error
|
||||
startHash, err = externalapi.NewDomainHashFromString(estimateNetworkHashesPerSecondRequest.StartHash)
|
||||
if err != nil {
|
||||
response := &appmessage.EstimateNetworkHashesPerSecondResponseMessage{}
|
||||
response.Error = appmessage.RPCErrorf("StartHash '%s' is not a valid block hash",
|
||||
estimateNetworkHashesPerSecondRequest.StartHash)
|
||||
return response, nil
|
||||
}
|
||||
}
|
||||
|
||||
networkHashesPerSecond, err := context.Domain.Consensus().EstimateNetworkHashesPerSecond(startHash, windowSize)
|
||||
if err != nil {
|
||||
response := &appmessage.EstimateNetworkHashesPerSecondResponseMessage{}
|
||||
response.Error = appmessage.RPCErrorf("could not resolve network hashes per "+
|
||||
"second for window size %d: %s", windowSize, err)
|
||||
"second for startHash %s and window size %d: %s", startHash, windowSize, err)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,10 @@ func setField(commandValue reflect.Value, parameterValue reflect.Value, paramete
|
||||
}
|
||||
|
||||
func stringToValue(parameterDesc *parameterDescription, valueStr string) (reflect.Value, error) {
|
||||
if valueStr == "-" {
|
||||
return reflect.Zero(parameterDesc.typeof), nil
|
||||
}
|
||||
|
||||
var value interface{}
|
||||
var err error
|
||||
switch parameterDesc.typeof.Kind() {
|
||||
|
||||
@@ -27,7 +27,8 @@ func parseConfig() (*configFlags, error) {
|
||||
}
|
||||
parser := flags.NewParser(cfg, flags.HelpFlag)
|
||||
parser.Usage = "kaspactl [OPTIONS] [COMMAND] [COMMAND PARAMETERS].\n\nCommand can be supplied only if --json is not used." +
|
||||
"\n\nUse `kaspactl --list-commands` to get a list of all commands and their parameters"
|
||||
"\n\nUse `kaspactl --list-commands` to get a list of all commands and their parameters." +
|
||||
"\nFor optional parameters- use '-' without quotes to not pass the parameter.\n"
|
||||
remainingArgs, err := parser.Parse()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/kaspanet/kaspad/infrastructure/config"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
|
||||
"github.com/jessevdk/go-flags"
|
||||
)
|
||||
@@ -73,8 +72,7 @@ type broadcastConfig struct {
|
||||
}
|
||||
|
||||
type showAddressConfig struct {
|
||||
DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to (default: localhost:8082)"`
|
||||
WithDerivationPath bool `long:"with-derivation-path" description:"Print the derivation path of the returned address"`
|
||||
DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to (default: localhost:8082)"`
|
||||
config.NetworkFlags
|
||||
}
|
||||
|
||||
|
||||
@@ -263,8 +263,7 @@ type GetReceiveAddressResponse struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||
DerivationPath string `protobuf:"bytes,2,opt,name=derivationPath,proto3" json:"derivationPath,omitempty"`
|
||||
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||
}
|
||||
|
||||
func (x *GetReceiveAddressResponse) Reset() {
|
||||
@@ -306,13 +305,6 @@ func (x *GetReceiveAddressResponse) GetAddress() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetReceiveAddressResponse) GetDerivationPath() string {
|
||||
if x != nil {
|
||||
return x.DerivationPath
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type BroadcastRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -506,47 +498,45 @@ var file_kaspawalletd_proto_rawDesc = []byte{
|
||||
0x13, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69,
|
||||
0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x22, 0x5d, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x64,
|
||||
0x22, 0x35, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x64,
|
||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a,
|
||||
0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x64, 0x65, 0x72, 0x69, 0x76,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0e, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x22,
|
||||
0x34, 0x0a, 0x10, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x27, 0x0a, 0x11, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61,
|
||||
0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78,
|
||||
0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x49, 0x44, 0x22, 0x11,
|
||||
0x0a, 0x0f, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x22, 0x12, 0x0a, 0x10, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe4, 0x02, 0x0a, 0x0c, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x77,
|
||||
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x12, 0x37, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c,
|
||||
0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61,
|
||||
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
|
||||
0x64, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65,
|
||||
0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x43,
|
||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61,
|
||||
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x22, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64,
|
||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65,
|
||||
0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x19, 0x2e, 0x47, 0x65, 0x74,
|
||||
0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69,
|
||||
0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12,
|
||||
0x10, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x11, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x09, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63,
|
||||
0x61, 0x73, 0x74, 0x12, 0x11, 0x2e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61,
|
||||
0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x36, 0x5a, 0x34,
|
||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61,
|
||||
0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x6b,
|
||||
0x61, 0x73, 0x70, 0x61, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f,
|
||||
0x6e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x34, 0x0a, 0x10, 0x42, 0x72, 0x6f, 0x61, 0x64,
|
||||
0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x74,
|
||||
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x27, 0x0a,
|
||||
0x11, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x04, 0x74, 0x78, 0x49, 0x44, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f,
|
||||
0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x12, 0x0a, 0x10, 0x53, 0x68, 0x75,
|
||||
0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe4, 0x02,
|
||||
0x0a, 0x0c, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x12, 0x37,
|
||||
0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x2e, 0x47,
|
||||
0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x13, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x64, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||
0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73,
|
||||
0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||
0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a,
|
||||
0x11, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65,
|
||||
0x73, 0x73, 0x12, 0x19, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41,
|
||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e,
|
||||
0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
|
||||
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x08, 0x53,
|
||||
0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x10, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f,
|
||||
0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x53, 0x68, 0x75, 0x74,
|
||||
0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x34,
|
||||
0x0a, 0x09, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x11, 0x2e, 0x42, 0x72,
|
||||
0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12,
|
||||
0x2e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x00, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70,
|
||||
0x61, 0x64, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x77, 0x61, 0x6c, 0x6c,
|
||||
0x65, 0x74, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -32,7 +32,6 @@ message GetReceiveAddressRequest {
|
||||
|
||||
message GetReceiveAddressResponse {
|
||||
string address = 1;
|
||||
string derivationPath = 2;
|
||||
}
|
||||
|
||||
message BroadcastRequest {
|
||||
|
||||
@@ -3,7 +3,6 @@ package server
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
@@ -59,11 +58,7 @@ func (s *server) GetReceiveAddress(_ context.Context, request *pb.GetReceiveAddr
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.GetReceiveAddressResponse{
|
||||
Address: address.String(),
|
||||
DerivationPath: path,
|
||||
}, nil
|
||||
|
||||
return &pb.GetReceiveAddressResponse{Address: address.String()}, nil
|
||||
}
|
||||
|
||||
func (s *server) walletAddressString(wAddr *walletAddress) (string, error) {
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
"github.com/kaspanet/kaspad/util/panics"
|
||||
)
|
||||
@@ -9,4 +15,33 @@ var (
|
||||
backendLog = logger.NewBackend()
|
||||
log = backendLog.Logger("KSWD")
|
||||
spawn = panics.GoroutineWrapperFunc(log)
|
||||
|
||||
defaultAppDir = util.AppDir("kaspawallet", false)
|
||||
defaultLogFile = filepath.Join(defaultAppDir, "daemon.log")
|
||||
defaultErrLogFile = filepath.Join(defaultAppDir, "daemon_err.log")
|
||||
)
|
||||
|
||||
func initLog(logFile, errLogFile string) {
|
||||
log.SetLevel(logger.LevelDebug)
|
||||
err := backendLog.AddLogFile(logFile, logger.LevelTrace)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error adding log file %s as log rotator for level %s: %s", logFile, logger.LevelTrace, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = backendLog.AddLogFile(errLogFile, logger.LevelWarn)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error adding log file %s as log rotator for level %s: %s", errLogFile, logger.LevelWarn, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = backendLog.AddLogWriter(os.Stdout, logger.LevelInfo)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error adding stdout to the loggerfor level %s: %s", logger.LevelWarn, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = backendLog.Run()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error starting the logger: %s ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,11 @@ package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
@@ -10,10 +15,6 @@ import (
|
||||
"github.com/kaspanet/kaspad/infrastructure/os/signal"
|
||||
"github.com/kaspanet/kaspad/util/panics"
|
||||
"github.com/pkg/errors"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
@@ -33,6 +34,8 @@ type server struct {
|
||||
|
||||
// Start starts the kaspawalletd server
|
||||
func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath string) error {
|
||||
initLog(defaultLogFile, defaultErrLogFile)
|
||||
|
||||
defer panics.HandlePanic(log, "MAIN", nil)
|
||||
interrupt := signal.InterruptListener()
|
||||
|
||||
@@ -40,6 +43,7 @@ func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath stri
|
||||
if err != nil {
|
||||
return (errors.Wrapf(err, "Error listening to tcp at %s", listen))
|
||||
}
|
||||
log.Infof("Listening on %s", listen)
|
||||
|
||||
rpcClient, err := connectToRPC(params, rpcServer)
|
||||
if err != nil {
|
||||
|
||||
@@ -16,23 +16,23 @@ func CreateMnemonic() (string, error) {
|
||||
return bip39.NewMnemonic(entropy)
|
||||
}
|
||||
|
||||
// Purpose and CoinType constants
|
||||
const (
|
||||
SingleSignerPurpose = 44
|
||||
// Note: this is not entirely compatible to BIP 45 since
|
||||
// BIP 45 doesn't have a coin type in its derivation path.
|
||||
MultiSigPurpose = 45
|
||||
// TODO: Register the coin type in https://github.com/satoshilabs/slips/blob/master/slip-0044.md
|
||||
CoinType = 111111
|
||||
)
|
||||
|
||||
func defaultPath(isMultisig bool) string {
|
||||
const (
|
||||
singleSignerPurpose = 44
|
||||
|
||||
// Note: this is not entirely compatible to BIP 45 since
|
||||
// BIP 45 doesn't have a coin type in its derivation path.
|
||||
multiSigPurpose = 45
|
||||
)
|
||||
|
||||
purpose := singleSignerPurpose
|
||||
purpose := SingleSignerPurpose
|
||||
if isMultisig {
|
||||
purpose = multiSigPurpose
|
||||
purpose = MultiSigPurpose
|
||||
}
|
||||
|
||||
// TODO: Register the coin type in https://github.com/satoshilabs/slips/blob/master/slip-0044.md
|
||||
const coinType = 111111
|
||||
return fmt.Sprintf("m/%d'/%d'/0'", purpose, coinType)
|
||||
return fmt.Sprintf("m/%d'/%d'/0'", purpose, CoinType)
|
||||
}
|
||||
|
||||
// MasterPublicKeyFromMnemonic returns the master public key with the correct derivation for the given mnemonic.
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package libkaspawallet
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet/bip32"
|
||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
"github.com/pkg/errors"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// CreateKeyPair generates a private-public key pair
|
||||
|
||||
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/client"
|
||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
||||
)
|
||||
@@ -24,9 +23,5 @@ func showAddress(conf *showAddressConfig) error {
|
||||
}
|
||||
|
||||
fmt.Printf("Address:\n%s\n", response.Address)
|
||||
if conf.WithDerivationPath {
|
||||
fmt.Printf("Derivation path:\n%s\n", response.DerivationPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,13 +3,15 @@ package utils
|
||||
import (
|
||||
"bufio"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ReadLine reads one line from the given reader with trimmed white space.
|
||||
func ReadLine(reader *bufio.Reader) (string, error) {
|
||||
line, err := reader.ReadBytes('\n')
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(string(line)), nil
|
||||
|
||||
@@ -536,9 +536,9 @@ func (s *consensus) Anticone(blockHash *externalapi.DomainHash) ([]*externalapi.
|
||||
return s.dagTraversalManager.Anticone(stagingArea, blockHash)
|
||||
}
|
||||
|
||||
func (s *consensus) EstimateNetworkHashesPerSecond(windowSize int) (uint64, error) {
|
||||
func (s *consensus) EstimateNetworkHashesPerSecond(startHash *externalapi.DomainHash, windowSize int) (uint64, error) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
return s.difficultyManager.EstimateNetworkHashesPerSecond(windowSize)
|
||||
return s.difficultyManager.EstimateNetworkHashesPerSecond(startHash, windowSize)
|
||||
}
|
||||
|
||||
@@ -33,5 +33,5 @@ type Consensus interface {
|
||||
IsInSelectedParentChainOf(blockHashA *DomainHash, blockHashB *DomainHash) (bool, error)
|
||||
GetHeadersSelectedTip() (*DomainHash, error)
|
||||
Anticone(blockHash *DomainHash) ([]*DomainHash, error)
|
||||
EstimateNetworkHashesPerSecond(windowSize int) (uint64, error)
|
||||
EstimateNetworkHashesPerSecond(startHash *DomainHash, windowSize int) (uint64, error)
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ import (
|
||||
type DifficultyManager interface {
|
||||
StageDAADataAndReturnRequiredDifficulty(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (uint32, error)
|
||||
RequiredDifficulty(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (uint32, error)
|
||||
EstimateNetworkHashesPerSecond(windowSize int) (uint64, error)
|
||||
EstimateNetworkHashesPerSecond(startHash *externalapi.DomainHash, windowSize int) (uint64, error)
|
||||
}
|
||||
|
||||
@@ -313,6 +313,6 @@ func (dm *mocDifficultyManager) StageDAADataAndReturnRequiredDifficulty(stagingA
|
||||
return dm.testDifficulty, nil
|
||||
}
|
||||
|
||||
func (dm *mocDifficultyManager) EstimateNetworkHashesPerSecond(windowSize int) (uint64, error) {
|
||||
func (dm *mocDifficultyManager) EstimateNetworkHashesPerSecond(startHash *externalapi.DomainHash, windowSize int) (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -1,26 +1,31 @@
|
||||
package difficultymanager
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
"github.com/pkg/errors"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func (dm *difficultyManager) EstimateNetworkHashesPerSecond(windowSize int) (uint64, error) {
|
||||
func (dm *difficultyManager) EstimateNetworkHashesPerSecond(startHash *externalapi.DomainHash, windowSize int) (uint64, error) {
|
||||
onEnd := logger.LogAndMeasureExecutionTime(log, "EstimateNetworkHashesPerSecond")
|
||||
defer onEnd()
|
||||
|
||||
stagingArea := model.NewStagingArea()
|
||||
return dm.estimateNetworkHashesPerSecond(stagingArea, windowSize)
|
||||
return dm.estimateNetworkHashesPerSecond(stagingArea, startHash, windowSize)
|
||||
}
|
||||
|
||||
func (dm *difficultyManager) estimateNetworkHashesPerSecond(stagingArea *model.StagingArea, windowSize int) (uint64, error) {
|
||||
if windowSize < 2 {
|
||||
return 0, errors.Errorf("windowSize must be equal to or greater than 2")
|
||||
func (dm *difficultyManager) estimateNetworkHashesPerSecond(stagingArea *model.StagingArea,
|
||||
startHash *externalapi.DomainHash, windowSize int) (uint64, error) {
|
||||
|
||||
const minWindowSize = 1000
|
||||
if windowSize < minWindowSize {
|
||||
return 0, errors.Errorf("windowSize must be equal to or greater than %d", minWindowSize)
|
||||
}
|
||||
|
||||
blockWindow, windowHashes, err := dm.blockWindow(stagingArea, model.VirtualBlockHash, windowSize)
|
||||
blockWindow, windowHashes, err := dm.blockWindow(stagingArea, startHash, windowSize)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -57,8 +62,13 @@ func (dm *difficultyManager) estimateNetworkHashesPerSecond(stagingArea *model.S
|
||||
}
|
||||
}
|
||||
|
||||
windowsDiff := (maxWindowTimestamp - minWindowTimestamp) / 1000 // Divided by 1000 to convert milliseconds to seconds
|
||||
if windowsDiff == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
nominator := new(big.Int).Sub(maxWindowBlueWork, minWindowBlueWork)
|
||||
denominator := big.NewInt((maxWindowTimestamp - minWindowTimestamp) / 1000) // Divided by 1000 to convert milliseconds to seconds
|
||||
denominator := big.NewInt(windowsDiff)
|
||||
networkHashesPerSecondBigInt := new(big.Int).Div(nominator, denominator)
|
||||
return networkHashesPerSecondBigInt.Uint64(), nil
|
||||
}
|
||||
|
||||
308
domain/consensus/timelock_CLTV_test.go
Normal file
308
domain/consensus/timelock_CLTV_test.go
Normal file
@@ -0,0 +1,308 @@
|
||||
package consensus_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/kaspanet/kaspad/domain/consensus"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestCheckLockTimeVerifyConditionedByBlockHeight verifies that an output locked by the CLTV script is spendable only after
|
||||
// the block height reached the set target.
|
||||
func TestCheckLockTimeVerifyConditionedByBlockHeight(t *testing.T) {
|
||||
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
|
||||
consensusConfig.BlockCoinbaseMaturity = 0
|
||||
factory := consensus.NewFactory()
|
||||
testConsensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckLockTimeVerifyConditionedByBlockHeight")
|
||||
if err != nil {
|
||||
t.Fatalf("Error setting up consensus: %+v", err)
|
||||
}
|
||||
defer teardown(false)
|
||||
|
||||
currentBlockHeight := int64(0)
|
||||
blockAHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{testConsensus.DAGParams().GenesisHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating blockA: %v", err)
|
||||
}
|
||||
currentBlockHeight++
|
||||
blockBHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockAHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating blockB: %v", err)
|
||||
}
|
||||
currentBlockHeight++
|
||||
blockCHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockBHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating blockC: %v", err)
|
||||
}
|
||||
currentBlockHeight++
|
||||
blockC, err := testConsensus.GetBlock(blockCHash)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed getting blockC: %v", err)
|
||||
}
|
||||
fees := uint64(1)
|
||||
fundingTransaction, err := testutils.CreateTransaction(blockC.Transactions[transactionhelper.CoinbaseTransactionIndex], fees)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating fundingTransaction: %v", err)
|
||||
}
|
||||
blockDHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockCHash}, nil,
|
||||
[]*externalapi.DomainTransaction{fundingTransaction})
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating blockD: %v", err)
|
||||
}
|
||||
currentBlockHeight++
|
||||
//Create a CLTV script:
|
||||
targetBlockHeight := int64(30)
|
||||
redeemScriptCLTV, err := createScriptCLTV(targetBlockHeight)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a script using createScriptCLTV: %v", err)
|
||||
}
|
||||
p2shScriptCLTV, err := txscript.PayToScriptHashScript(redeemScriptCLTV)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a pay-to-script-hash script : %v", err)
|
||||
}
|
||||
scriptPublicKeyCLTV := externalapi.ScriptPublicKey{
|
||||
Version: constants.MaxScriptPublicKeyVersion,
|
||||
Script: p2shScriptCLTV,
|
||||
}
|
||||
transactionWithLockedOutput, err := createTransactionWithLockedOutput(fundingTransaction, fees, &scriptPublicKeyCLTV)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in createTransactionWithLockedOutput: %v", err)
|
||||
}
|
||||
// BlockE contains the locked output (locked by CLTV).
|
||||
// This block should be valid since CLTV script locked only the output.
|
||||
blockEHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockDHash}, nil,
|
||||
[]*externalapi.DomainTransaction{transactionWithLockedOutput})
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating blockE: %v", err)
|
||||
}
|
||||
currentBlockHeight++
|
||||
// Create a transaction that tries to spend the locked output.
|
||||
transactionThatSpentTheLockedOutput, err := createTransactionThatSpentTheLockedOutput(transactionWithLockedOutput,
|
||||
fees, redeemScriptCLTV, targetBlockHeight)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating transactionThatSpentTheLockedOutput: %v", err)
|
||||
}
|
||||
// Add a block that contains a transaction that spends the locked output before the time, and therefore should be failed.
|
||||
// (The block height should be x, before the output will be spendable, where x = 'targetBlockHeight' ).
|
||||
_, _, err = testConsensus.AddBlock([]*externalapi.DomainHash{blockEHash}, nil,
|
||||
[]*externalapi.DomainTransaction{transactionThatSpentTheLockedOutput})
|
||||
if err == nil || !errors.Is(err, ruleerrors.ErrUnfinalizedTx) {
|
||||
t.Fatalf("Expected block to be invalid with err: %v, instead found: %v", ruleerrors.ErrUnfinalizedTx, err)
|
||||
}
|
||||
|
||||
// Add blocks to release the locked output, the block height should be 'numOfBlocksToWait'.
|
||||
tipHash := blockEHash
|
||||
numOfBlocksToAdd := targetBlockHeight - currentBlockHeight
|
||||
for i := int64(0); i < numOfBlocksToAdd; i++ {
|
||||
tipHash, _, err = testConsensus.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating tip: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
// Tries to spend the output that should be no longer locked
|
||||
_, _, err = testConsensus.AddBlock([]*externalapi.DomainHash{tipHash}, nil,
|
||||
[]*externalapi.DomainTransaction{transactionThatSpentTheLockedOutput})
|
||||
if err != nil {
|
||||
t.Fatalf("The block should be valid since the output is not locked anymore. but got an error: %v", err)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// TestCheckLockTimeVerifyConditionedByAbsoluteTime verifies that an output locked by the CLTV script is spendable only after
|
||||
// the time is reached to the set target (compared to the past median time)).
|
||||
func TestCheckLockTimeVerifyConditionedByAbsoluteTime(t *testing.T) {
|
||||
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
|
||||
consensusConfig.BlockCoinbaseMaturity = 0
|
||||
factory := consensus.NewFactory()
|
||||
testConsensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckLockTimeVerifyConditionedByAbsoluteTime")
|
||||
if err != nil {
|
||||
t.Fatalf("Error setting up consensus: %+v", err)
|
||||
}
|
||||
defer teardown(false)
|
||||
|
||||
blockAHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{testConsensus.DAGParams().GenesisHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating blockA: %v", err)
|
||||
}
|
||||
blockBHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockAHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating blockB: %v", err)
|
||||
}
|
||||
blockCHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockBHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating blockC: %v", err)
|
||||
}
|
||||
blockC, err := testConsensus.GetBlock(blockCHash)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed getting blockC: %v", err)
|
||||
}
|
||||
fees := uint64(1)
|
||||
fundingTransaction, err := testutils.CreateTransaction(blockC.Transactions[transactionhelper.CoinbaseTransactionIndex], fees)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating fundingTransaction: %v", err)
|
||||
}
|
||||
blockDHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockCHash}, nil,
|
||||
[]*externalapi.DomainTransaction{fundingTransaction})
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating blockD: %v", err)
|
||||
}
|
||||
blockD, err := testConsensus.GetBlock(blockDHash)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed getting blockD: %v", err)
|
||||
}
|
||||
//Create a CLTV script:
|
||||
timeToWait := int64(12 * 1000)
|
||||
lockTimeTarget := blockD.Header.TimeInMilliseconds() + timeToWait
|
||||
redeemScriptCLTV, err := createScriptCLTV(lockTimeTarget)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a script using createScriptCLTV: %v", err)
|
||||
}
|
||||
p2shScriptCLTV, err := txscript.PayToScriptHashScript(redeemScriptCLTV)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a pay-to-script-hash script : %v", err)
|
||||
}
|
||||
scriptPublicKeyCLTV := externalapi.ScriptPublicKey{
|
||||
Version: constants.MaxScriptPublicKeyVersion,
|
||||
Script: p2shScriptCLTV,
|
||||
}
|
||||
transactionWithLockedOutput, err := createTransactionWithLockedOutput(fundingTransaction, fees, &scriptPublicKeyCLTV)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in createTransactionWithLockedOutput: %v", err)
|
||||
}
|
||||
// BlockE contains the locked output (locked by CLTV).
|
||||
// This block should be valid since CLTV script locked only the output.
|
||||
blockEHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockDHash}, nil,
|
||||
[]*externalapi.DomainTransaction{transactionWithLockedOutput})
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating blockE: %v", err)
|
||||
}
|
||||
blockE, err := testConsensus.GetBlock(blockEHash)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed getting blockE: %v", err)
|
||||
}
|
||||
// Create a transaction that tries to spend the locked output.
|
||||
transactionThatSpentTheLockedOutput, err := createTransactionThatSpentTheLockedOutput(transactionWithLockedOutput,
|
||||
fees, redeemScriptCLTV, lockTimeTarget)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating transactionThatSpentTheLockedOutput: %v", err)
|
||||
}
|
||||
// Add a block that contains a transaction that tries to spend the locked output before the time, and therefore should be failed.
|
||||
_, _, err = testConsensus.AddBlock([]*externalapi.DomainHash{blockEHash}, nil,
|
||||
[]*externalapi.DomainTransaction{transactionThatSpentTheLockedOutput})
|
||||
if err == nil || !errors.Is(err, ruleerrors.ErrUnfinalizedTx) {
|
||||
t.Fatalf("Expected block to be invalid with err: %v, instead found: %v", ruleerrors.ErrUnfinalizedTx, err)
|
||||
}
|
||||
|
||||
emptyCoinbase := externalapi.DomainCoinbaseData{
|
||||
ScriptPublicKey: &externalapi.ScriptPublicKey{
|
||||
Script: nil,
|
||||
Version: 0,
|
||||
},
|
||||
}
|
||||
var tipHash *externalapi.DomainHash
|
||||
timeStampBlockE := blockE.Header.TimeInMilliseconds()
|
||||
stagingArea := model.NewStagingArea()
|
||||
// Make sure the time limitation has passed.
|
||||
for i := int64(0); ; i++ {
|
||||
tipBlock, err := testConsensus.BuildBlock(&emptyCoinbase, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating tip using BuildBlock: %v", err)
|
||||
}
|
||||
blockHeader := tipBlock.Header.ToMutable()
|
||||
blockHeader.SetTimeInMilliseconds(timeStampBlockE + i*1000)
|
||||
tipBlock.Header = blockHeader.ToImmutable()
|
||||
_, err = testConsensus.ValidateAndInsertBlock(tipBlock)
|
||||
if err != nil {
|
||||
t.Fatalf("Error validating and inserting tip block: %v", err)
|
||||
}
|
||||
tipHash = consensushashing.BlockHash(tipBlock)
|
||||
pastMedianTime, err := testConsensus.PastMedianTimeManager().PastMedianTime(stagingArea, tipHash)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed getting pastMedianTime: %v", err)
|
||||
}
|
||||
if pastMedianTime > lockTimeTarget {
|
||||
break
|
||||
}
|
||||
}
|
||||
// Tries to spend the output that should be no longer locked
|
||||
_, _, err = testConsensus.AddBlock([]*externalapi.DomainHash{tipHash}, nil,
|
||||
[]*externalapi.DomainTransaction{transactionThatSpentTheLockedOutput})
|
||||
if err != nil {
|
||||
t.Fatalf("The block should be valid since the output is not locked anymore. but got an error: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func createScriptCLTV(blockHeightOrAbsoluteTimeTarget int64) ([]byte, error) {
|
||||
scriptBuilder := txscript.NewScriptBuilder()
|
||||
scriptBuilder.AddInt64(blockHeightOrAbsoluteTimeTarget)
|
||||
scriptBuilder.AddOp(txscript.OpCheckLockTimeVerify)
|
||||
scriptBuilder.AddOp(txscript.OpTrue)
|
||||
return scriptBuilder.Script()
|
||||
}
|
||||
|
||||
func createTransactionWithLockedOutput(txToSpend *externalapi.DomainTransaction, fee uint64,
|
||||
scriptPublicKeyCLTV *externalapi.ScriptPublicKey) (*externalapi.DomainTransaction, error) {
|
||||
|
||||
_, redeemScript := testutils.OpTrueScript()
|
||||
signatureScript, err := txscript.PayToScriptHashSignatureScript(redeemScript, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
input := &externalapi.DomainTransactionInput{
|
||||
PreviousOutpoint: externalapi.DomainOutpoint{
|
||||
TransactionID: *consensushashing.TransactionID(txToSpend),
|
||||
Index: 0,
|
||||
},
|
||||
SignatureScript: signatureScript,
|
||||
Sequence: constants.MaxTxInSequenceNum,
|
||||
}
|
||||
output := &externalapi.DomainTransactionOutput{
|
||||
ScriptPublicKey: scriptPublicKeyCLTV,
|
||||
Value: txToSpend.Outputs[0].Value - fee,
|
||||
}
|
||||
return &externalapi.DomainTransaction{
|
||||
Version: constants.MaxTransactionVersion,
|
||||
Inputs: []*externalapi.DomainTransactionInput{input},
|
||||
Outputs: []*externalapi.DomainTransactionOutput{output},
|
||||
Payload: []byte{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func createTransactionThatSpentTheLockedOutput(txToSpend *externalapi.DomainTransaction, fee uint64,
|
||||
redeemScript []byte, lockTime int64) (*externalapi.DomainTransaction, error) {
|
||||
|
||||
signatureScript, err := txscript.PayToScriptHashSignatureScript(redeemScript, []byte{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scriptPublicKeyOutput, _ := testutils.OpTrueScript()
|
||||
input := &externalapi.DomainTransactionInput{
|
||||
PreviousOutpoint: externalapi.DomainOutpoint{
|
||||
TransactionID: *consensushashing.TransactionID(txToSpend),
|
||||
Index: 0,
|
||||
},
|
||||
SignatureScript: signatureScript,
|
||||
Sequence: 0xffffffff - 1,
|
||||
}
|
||||
output := &externalapi.DomainTransactionOutput{
|
||||
ScriptPublicKey: scriptPublicKeyOutput,
|
||||
Value: txToSpend.Outputs[0].Value - fee,
|
||||
}
|
||||
return &externalapi.DomainTransaction{
|
||||
Version: constants.MaxTransactionVersion,
|
||||
Inputs: []*externalapi.DomainTransactionInput{input},
|
||||
Outputs: []*externalapi.DomainTransactionOutput{output},
|
||||
Payload: []byte{},
|
||||
LockTime: uint64(lockTime), // less than 500 million interpreted as a block height, and above as an UNIX timestamp.
|
||||
}, nil
|
||||
}
|
||||
@@ -17,11 +17,12 @@
|
||||
package protowire
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -5008,6 +5009,7 @@ type EstimateNetworkHashesPerSecondRequestMessage struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
WindowSize uint32 `protobuf:"varint,1,opt,name=windowSize,proto3" json:"windowSize,omitempty"`
|
||||
StartHash string `protobuf:"bytes,2,opt,name=blockHash,proto3" json:"blockHash,omitempty"`
|
||||
}
|
||||
|
||||
func (x *EstimateNetworkHashesPerSecondRequestMessage) Reset() {
|
||||
@@ -5049,6 +5051,13 @@ func (x *EstimateNetworkHashesPerSecondRequestMessage) GetWindowSize() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *EstimateNetworkHashesPerSecondRequestMessage) GetBlockHash() string {
|
||||
if x != nil {
|
||||
return x.StartHash
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type EstimateNetworkHashesPerSecondResponseMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -5727,25 +5736,26 @@ var file_rpc_proto_rawDesc = []byte{
|
||||
0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x69, 0x7a, 0x65,
|
||||
0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43,
|
||||
0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x4e, 0x0a, 0x2c,
|
||||
0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x6c, 0x0a, 0x2c,
|
||||
0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48,
|
||||
0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a,
|
||||
0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x0a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x93, 0x01, 0x0a,
|
||||
0x2d, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
|
||||
0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x36,
|
||||
0x0a, 0x16, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50,
|
||||
0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16,
|
||||
0x52, 0x0a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1c, 0x0a, 0x09,
|
||||
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0x93, 0x01, 0x0a, 0x2d, 0x45,
|
||||
0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61,
|
||||
0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x16,
|
||||
0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72,
|
||||
0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18,
|
||||
0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69,
|
||||
0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72,
|
||||
0x6f, 0x72, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x6e, 0x65,
|
||||
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65,
|
||||
0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65,
|
||||
0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72,
|
||||
0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b,
|
||||
0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -592,6 +592,7 @@ message GetInfoResponseMessage{
|
||||
|
||||
message EstimateNetworkHashesPerSecondRequestMessage{
|
||||
uint32 windowSize = 1;
|
||||
string blockHash = 2;
|
||||
}
|
||||
|
||||
message EstimateNetworkHashesPerSecondResponseMessage{
|
||||
|
||||
@@ -15,6 +15,7 @@ func (x *KaspadMessage_EstimateNetworkHashesPerSecondRequest) toAppMessage() (ap
|
||||
func (x *KaspadMessage_EstimateNetworkHashesPerSecondRequest) fromAppMessage(message *appmessage.EstimateNetworkHashesPerSecondRequestMessage) error {
|
||||
x.EstimateNetworkHashesPerSecondRequest = &EstimateNetworkHashesPerSecondRequestMessage{
|
||||
WindowSize: message.WindowSize,
|
||||
StartHash: message.StartHash,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -25,6 +26,7 @@ func (x *EstimateNetworkHashesPerSecondRequestMessage) toAppMessage() (appmessag
|
||||
}
|
||||
return &appmessage.EstimateNetworkHashesPerSecondRequestMessage{
|
||||
WindowSize: x.WindowSize,
|
||||
StartHash: x.StartHash,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ package rpcclient
|
||||
import "github.com/kaspanet/kaspad/app/appmessage"
|
||||
|
||||
// EstimateNetworkHashesPerSecond sends an RPC request respective to the function's name and returns the RPC server's response
|
||||
func (c *RPCClient) EstimateNetworkHashesPerSecond(windowSize uint32) (*appmessage.EstimateNetworkHashesPerSecondResponseMessage, error) {
|
||||
err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewEstimateNetworkHashesPerSecondRequestMessage(windowSize))
|
||||
func (c *RPCClient) EstimateNetworkHashesPerSecond(startHash string, windowSize uint32) (*appmessage.EstimateNetworkHashesPerSecondResponseMessage, error) {
|
||||
err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewEstimateNetworkHashesPerSecondRequestMessage(startHash, windowSize))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user