diff --git a/build_package.sh b/build_package.sh index 7bcbd383..9471e717 100644 --- a/build_package.sh +++ b/build_package.sh @@ -52,7 +52,7 @@ for PLATFORM in $PLATFORMS; do BIN_FILENAME="${OUTPUT}-${GOOS}-${GOARCH}" echo mkdir -p $OUTPUT_DIR if [[ "${GOOS}" == "windows" ]]; then BIN_FILENAME="${BIN_FILENAME}.exe"; fi - CMD="GOOS=${GOOS} GOARCH=${GOARCH} go build -gcflags=${GCFLAGS} -o $OUTPUT_DIR/${BIN_FILENAME} $package" + CMD="GOOS=${GOOS} GOARCH=${GOARCH} go build -trimpath -ldflags=-buildid= -gcflags=${GCFLAGS} -o $OUTPUT_DIR/${BIN_FILENAME} $package" echo "${CMD}" eval $CMD || FAILURES="${FAILURES} ${PLATFORM}" @@ -75,7 +75,7 @@ for GOOS in $PLATFORMS_ARM; do for GOARM in 7; do OUTPUT_DIR="${ABSDIR}/build/dero_${GOOS}_${GOARCH}${GOARM}" BIN_FILENAME="${OUTPUT}-${GOOS}-${GOARCH}${GOARM}" - CMD="GOARM=${GOARM} GOOS=${GOOS} GOARCH=${GOARCH} go build -gcflags=${GCFLAGS} -o $OUTPUT_DIR/${BIN_FILENAME} $package" + CMD="GOARM=${GOARM} GOOS=${GOOS} GOARCH=${GOARCH} go build -trimpath -ldflags=-buildid= -gcflags=${GCFLAGS} -o $OUTPUT_DIR/${BIN_FILENAME} $package" echo "${CMD}" eval "${CMD}" || FAILURES="${FAILURES} ${GOOS}/${GOARCH}${GOARM}" done diff --git a/cmd/dero-wallet-cli/easymenu_pre_open.go b/cmd/dero-wallet-cli/easymenu_pre_open.go index 5fd6cb49..b56ef134 100644 --- a/cmd/dero-wallet-cli/easymenu_pre_open.go +++ b/cmd/dero-wallet-cli/easymenu_pre_open.go @@ -19,6 +19,7 @@ package main import "io" import "fmt" import "time" +import "strconv" import "strings" import "encoding/hex" @@ -222,6 +223,30 @@ func common_processing(wallet *walletapi.Wallet_Disk) { wallet.SetOnlineMode() } + if globals.Arguments["--scan-top-n-blocks"] != nil && globals.Arguments["--scan-top-n-blocks"].(string) != "" { + s, err := strconv.ParseInt(globals.Arguments["--scan-top-n-blocks"].(string), 10, 64) + if err != nil { + logger.Error(err, "Error parsing number(in numeric form)") + } else { + wallet.SetTrackRecentBlocks(s) + if wallet.SetTrackRecentBlocks(-1) == 0 { + logger.Info("Wallet will track entire history") + } else { + logger.Info("Wallet will track recent blocks", "blocks", wallet.SetTrackRecentBlocks(-1)) + } + } + } + + if globals.Arguments["--save-every-x-seconds"] != nil && globals.Arguments["--save-every-x-seconds"].(string) != "" { + s, err := strconv.ParseUint(globals.Arguments["--save-every-x-seconds"].(string), 10, 64) + if err != nil { + logger.Error(err, "Error parsing seconds(in numeric form)") + } else { + wallet.SetSaveDuration(time.Duration(s) * time.Second) + logger.Info("Wallet changes will be saved every", "duration (seconds)", wallet.SetSaveDuration(-1)) + } + } + wallet.SetNetwork(!globals.Arguments["--testnet"].(bool)) // start rpc server if requested diff --git a/cmd/dero-wallet-cli/main.go b/cmd/dero-wallet-cli/main.go index 92ba014e..c50b13a8 100644 --- a/cmd/dero-wallet-cli/main.go +++ b/cmd/dero-wallet-cli/main.go @@ -81,13 +81,15 @@ Usage: --rpc-bind=<127.0.0.1:20209> Wallet binds on this ip address and port --rpc-login= RPC server will grant access based on these credentials --allow-rpc-password-change RPC server will change password if you send "Pass" header with new password + --scan-top-n-blocks=<100000> Only scan top N blocks + --save-every-x-seconds=<300> Save wallet every x seconds ` var menu_mode bool = true // default display menu mode -//var account_valid bool = false // if an account has been opened, do not allow to create new account in this session +// var account_valid bool = false // if an account has been opened, do not allow to create new account in this session var offline_mode bool // whether we are in offline mode var sync_in_progress int // whether sync is in progress with daemon var wallet *walletapi.Wallet_Disk //= &walletapi.Account{} // all account data is available here -//var address string +// var address string var sync_time time.Time // used to suitable update prompt var default_offline_datafile string = "getoutputs.bin" diff --git a/cmd/dero-wallet-cli/prompt.go b/cmd/dero-wallet-cli/prompt.go index 86e6fbbe..98cf3476 100644 --- a/cmd/dero-wallet-cli/prompt.go +++ b/cmd/dero-wallet-cli/prompt.go @@ -146,6 +146,7 @@ func handle_prompt_command(l *readline.Instance, line string) { filename, err := ReadString(l, "Enter file to sign", "") if err != nil { logger.Error(err, "Cannot read input file name") + break } outputfile := filename + ".sign" @@ -162,6 +163,7 @@ func handle_prompt_command(l *readline.Instance, line string) { filename, err := ReadString(l, "Enter file to verify signature", "") if err != nil { logger.Error(err, "Cannot read input file name") + break } outputfile := strings.TrimSuffix(filename, ".sign") @@ -184,6 +186,40 @@ func handle_prompt_command(l *readline.Instance, line string) { } + case "filesign_huge": // sign a hugefile contents + if !ValidateCurrentPassword(l, wallet) { + logger.Error(err, "Invalid password") + PressAnyKey(l, wallet) + break + } + + filename, err := ReadString(l, "Enter file to sign", "") + if err != nil { + logger.Error(err, "Cannot read input file name") + break + } + + if err := wallet.SignFile(filename); err != nil { + logger.Error(err, "Cannot sign", "file", filename) + } else { + logger.Info("successfully signed file. please check", "file", filename, "signature", filename+".signed") + } + + case "fileverify_huge": // verify a file contents + filename, err := ReadString(l, "Enter file to verify signature", "") + if err != nil { + logger.Error(err, "Cannot read input file name") + break + } + + if signer, err := wallet.CheckFileSignature(filename); err != nil { + logger.Error(err, "Signature verify failed", "file", filename) + } else { + logger.Info("Signed by", "address", signer.String()) + + logger.Info("Signature verified successfully.", "file", filename) + } + case "password": // change wallet password if ConfirmYesNoDefaultNo(l, "Change wallet password (y/N)") && ValidateCurrentPassword(l, wallet) { @@ -435,6 +471,9 @@ func handle_set_command(l *readline.Instance, line string) { fmt.Fprintf(l.Stderr(), color_extra_white+"Current settings"+color_extra_white+"\n") fmt.Fprintf(l.Stderr(), color_normal+"Seed Language: "+color_extra_white+"%s\t"+color_normal+"eg. "+color_extra_white+"set seed language\n"+color_normal, wallet.GetSeedLanguage()) fmt.Fprintf(l.Stderr(), color_normal+"Ringsize: "+color_extra_white+"%d\t"+color_normal+"eg. "+color_extra_white+"set ringsize 16\n"+color_normal, wallet.GetRingSize()) + fmt.Fprintf(l.Stderr(), color_normal+"Save Every : "+color_extra_white+"%s \t"+color_normal+"eg. "+color_extra_white+"default value:0 (set using command line)\n"+color_normal, wallet.SetSaveDuration(-1)) + fmt.Fprintf(l.Stderr(), color_normal+"Track Recent Blocks : "+color_extra_white+"%d \t"+color_normal+"eg. "+color_extra_white+"default value:0 means track all blocks (set using command line)\n"+color_normal, wallet.SetTrackRecentBlocks(-1)) + fmt.Fprintf(l.Stderr(), color_normal+"Priority: "+color_extra_white+"%0.2f\t"+color_normal+"eg. "+color_extra_white+"set priority 4.0\t"+color_normal+"Transaction priority on DERO network \n", wallet.GetFeeMultiplier()) fmt.Fprintf(l.Stderr(), "\t\tMinimum priority is 1.00. High priority = high fees\n") @@ -867,6 +906,8 @@ var completer = readline.NewPrefixCompleter( readline.PcItem("get_tx_key"), readline.PcItem("filesign"), readline.PcItem("fileverify"), + readline.PcItem("filesign_huge"), + readline.PcItem("fileverify_huge"), readline.PcItem("menu"), readline.PcItem("rescan_bc"), readline.PcItem("payment_id"), diff --git a/cmd/derod/rpc/rpc_dero_gettxpool.go b/cmd/derod/rpc/rpc_dero_gettxpool.go index b025eebc..112c248d 100644 --- a/cmd/derod/rpc/rpc_dero_gettxpool.go +++ b/cmd/derod/rpc/rpc_dero_gettxpool.go @@ -27,5 +27,10 @@ func GetTxPool(ctx context.Context) (result rpc.GetTxPool_Result) { for i := range pool_list { result.Tx_list = append(result.Tx_list, fmt.Sprintf("%s", pool_list[i])) } + + reg_list := chain.Regpool.Regpool_List_TX() + for i := range reg_list { + result.Tx_list = append(result.Tx_list, fmt.Sprintf("%s", reg_list[i])) + } return result } diff --git a/cmd/derod/rpc/rpc_dero_sendrawtransaction.go b/cmd/derod/rpc/rpc_dero_sendrawtransaction.go index 5a4d0af8..694b3dba 100644 --- a/cmd/derod/rpc/rpc_dero_sendrawtransaction.go +++ b/cmd/derod/rpc/rpc_dero_sendrawtransaction.go @@ -24,7 +24,7 @@ import "github.com/deroproject/derohe/rpc" import "github.com/deroproject/derohe/p2p" import "github.com/deroproject/derohe/transaction" -//NOTE: finally we have shifted to json api +// NOTE: finally we have shifted to json api func SendRawTransaction(ctx context.Context, p rpc.SendRawTransaction_Params) (result rpc.SendRawTransaction_Result, err error) { defer func() { // safety so if anything wrong happens, we return error @@ -61,6 +61,7 @@ func SendRawTransaction(ctx context.Context, p rpc.SendRawTransaction_Params) (r if err = chain.Add_TX_To_Pool(&tx); err == nil { p2p.Broadcast_Tx(&tx, 0) // broadcast tx result.Status = "OK" + result.TXID = fmt.Sprintf("%s", tx.GetHash()) } else { err = fmt.Errorf("Transaction %s rejected by daemon err '%s'", tx.GetHash(), err) } diff --git a/cmd/rpc_examples/pong_server/pong_server.go b/cmd/rpc_examples/pong_server/pong_server.go index 09320cb7..cd300204 100644 --- a/cmd/rpc_examples/pong_server/pong_server.go +++ b/cmd/rpc_examples/pong_server/pong_server.go @@ -15,7 +15,7 @@ import "fmt" import "time" import "crypto/sha1" -import "etcd.io/bbolt" +import "go.etcd.io/bbolt" import "github.com/go-logr/logr" import "gopkg.in/natefinch/lumberjack.v2" @@ -36,8 +36,8 @@ var expected_arguments = rpc.Arguments{ // { Name:rpc.RPC_EXPIRY , DataType:rpc.DataTime, Value:time.Now().Add(time.Hour).UTC()}, {Name: rpc.RPC_COMMENT, DataType: rpc.DataString, Value: "Purchase PONG"}, //{"float64", rpc.DataFloat64, float64(0.12345)}, // in atomic units - // {Name:rpc.RPC_NEEDS_REPLYBACK_ADDRESS,DataType:rpc.DataUint64,Value:uint64(0)}, // this service will reply to incoming request,so needs the senders address - {Name: rpc.RPC_VALUE_TRANSFER, DataType: rpc.DataUint64, Value: uint64(12345)}, // in atomic units + {Name: rpc.RPC_NEEDS_REPLYBACK_ADDRESS, DataType: rpc.DataUint64, Value: uint64(0)}, // this service will reply to incoming request,so needs the senders address + {Name: rpc.RPC_VALUE_TRANSFER, DataType: rpc.DataUint64, Value: uint64(12345)}, // in atomic units } @@ -167,16 +167,23 @@ func processing_thread(db *bbolt.DB) { continue } - /* if !e.Payload_RPC.Has(rpc.RPC_REPLYBACK_ADDRESS, rpc.DataAddress){ - logger.Error(nil, fmt.Sprintf("user has not give his address so we cannot replyback")) // this is an unexpected situation - continue - } + if !e.Payload_RPC.Has(rpc.RPC_REPLYBACK_ADDRESS, rpc.DataAddress) { + logger.Error(nil, fmt.Sprintf("user has not give his address so we cannot replyback")) // this is an unexpected situation + continue + } + + destination_expected := e.Payload_RPC.Value(rpc.RPC_REPLYBACK_ADDRESS, rpc.DataAddress).(rpc.Address).String() + addr, err := rpc.NewAddress(destination_expected) + if err != nil { + logger.Error(err, "err while while parsing incoming addr") + continue + } + addr.Mainnet = false // convert addresses to testnet form, by default it's expected to be mainnnet + destination_expected = addr.String() - destination_expected := e.Payload_RPC.Value(rpc.RPC_REPLYBACK_ADDRESS, rpc.DataAddress).(rpc.Address).String() + logger.V(1).Info("tx should be replied", "txid", e.TXID, "replyback_address", destination_expected) - logger.V(1).Info("tx should be replied", "txid", e.TXID,"replyback_address",destination_expected) - */ - destination_expected := e.Sender + //destination_expected := e.Sender // value received is what we are expecting, so time for response response[0].Value = e.SourcePort // source port now becomes destination port, similar to TCP diff --git a/config/version.go b/config/version.go index 5cc3f7cb..1939a24d 100644 --- a/config/version.go +++ b/config/version.go @@ -20,4 +20,4 @@ import "github.com/blang/semver/v4" // right now it has to be manually changed // do we need to include git commitsha?? -var Version = semver.MustParse("3.5.1-110a.DEROHE.STARGATE+26022022") +var Version = semver.MustParse("3.5.2-113.DEROHE.STARGATE+01102022") diff --git a/p2p/connection_pool.go b/p2p/connection_pool.go index a844522e..ec4c4f4f 100644 --- a/p2p/connection_pool.go +++ b/p2p/connection_pool.go @@ -174,7 +174,7 @@ func IsAddressConnected(address string) bool { // add connection to map, only if we are not connected already // we also check for limits for incoming connections // same ip max 8 ip ( considering NAT) -//same Peer ID 4 +// same Peer ID 4 func Connection_Add(c *Connection) bool { if dup, ok := connection_map.LoadOrStore(Address(c), c); !ok { c.Created = time.Now() @@ -396,6 +396,7 @@ func broadcast_Block_Coded(cbl *block.Complete_Block, PeerID uint64, first_seen our_height := chain.Get_Height() // build the request once and dispatch it to all possible peers + tries := 0 count := 0 unique_map := UniqueConnections() @@ -425,6 +426,11 @@ func broadcast_Block_Coded(cbl *block.Complete_Block, PeerID uint64, first_seen return default: } + + if tries > 1024 { + return + } + tries++ if atomic.LoadUint32(&v.State) != HANDSHAKE_PENDING && PeerID != v.Peer_ID && v.Peer_ID != GetPeerID() { // skip pre-handshake connections // if the other end is > 2 blocks behind, do not broadcast block to him diff --git a/p2p/peer.go b/p2p/peer.go index 5697e570..d889ccaa 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -45,7 +45,7 @@ func GetPeerID() uint64 { if peerid == 0 { var buf [8]byte rand.Read(buf[:]) - peerid = binary.LittleEndian.Uint64(buf[:]) + peerid = binary.LittleEndian.Uint64(buf[:]) & 0x7FFFFFFFFFFFFFFF } return peerid } diff --git a/rpc/daemon_rpc.go b/rpc/daemon_rpc.go index a25263c0..d2fae098 100644 --- a/rpc/daemon_rpc.go +++ b/rpc/daemon_rpc.go @@ -145,7 +145,7 @@ type ( } ) -//get encrypted balance call +// get encrypted balance call type ( GetEncryptedBalance_Params struct { Address string `json:"address"` @@ -268,6 +268,7 @@ type ( } SendRawTransaction_Result struct { Status string `json:"status"` + TXID string `json:"txid"` Reason string `json:"string"` } ) diff --git "a/vendor/github.com/tjfoc/gmsm/API\344\275\277\347\224\250\350\257\264\346\230\216.md" b/vendor/github.com/tjfoc/gmsm/API????.md similarity index 100% rename from "vendor/github.com/tjfoc/gmsm/API\344\275\277\347\224\250\350\257\264\346\230\216.md" rename to vendor/github.com/tjfoc/gmsm/API????.md diff --git a/vendor/etcd.io/bbolt/.gitignore b/vendor/go.etcd.io/bbolt/.gitignore similarity index 100% rename from vendor/etcd.io/bbolt/.gitignore rename to vendor/go.etcd.io/bbolt/.gitignore diff --git a/vendor/etcd.io/bbolt/.travis.yml b/vendor/go.etcd.io/bbolt/.travis.yml similarity index 100% rename from vendor/etcd.io/bbolt/.travis.yml rename to vendor/go.etcd.io/bbolt/.travis.yml diff --git a/vendor/etcd.io/bbolt/LICENSE b/vendor/go.etcd.io/bbolt/LICENSE similarity index 100% rename from vendor/etcd.io/bbolt/LICENSE rename to vendor/go.etcd.io/bbolt/LICENSE diff --git a/vendor/etcd.io/bbolt/Makefile b/vendor/go.etcd.io/bbolt/Makefile similarity index 100% rename from vendor/etcd.io/bbolt/Makefile rename to vendor/go.etcd.io/bbolt/Makefile diff --git a/vendor/etcd.io/bbolt/README.md b/vendor/go.etcd.io/bbolt/README.md similarity index 100% rename from vendor/etcd.io/bbolt/README.md rename to vendor/go.etcd.io/bbolt/README.md diff --git a/vendor/etcd.io/bbolt/allocate_test.go b/vendor/go.etcd.io/bbolt/allocate_test.go similarity index 100% rename from vendor/etcd.io/bbolt/allocate_test.go rename to vendor/go.etcd.io/bbolt/allocate_test.go diff --git a/vendor/etcd.io/bbolt/bolt_386.go b/vendor/go.etcd.io/bbolt/bolt_386.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_386.go rename to vendor/go.etcd.io/bbolt/bolt_386.go diff --git a/vendor/etcd.io/bbolt/bolt_amd64.go b/vendor/go.etcd.io/bbolt/bolt_amd64.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_amd64.go rename to vendor/go.etcd.io/bbolt/bolt_amd64.go diff --git a/vendor/etcd.io/bbolt/bolt_arm.go b/vendor/go.etcd.io/bbolt/bolt_arm.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_arm.go rename to vendor/go.etcd.io/bbolt/bolt_arm.go diff --git a/vendor/etcd.io/bbolt/bolt_arm64.go b/vendor/go.etcd.io/bbolt/bolt_arm64.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_arm64.go rename to vendor/go.etcd.io/bbolt/bolt_arm64.go diff --git a/vendor/etcd.io/bbolt/bolt_linux.go b/vendor/go.etcd.io/bbolt/bolt_linux.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_linux.go rename to vendor/go.etcd.io/bbolt/bolt_linux.go diff --git a/vendor/etcd.io/bbolt/bolt_mips64x.go b/vendor/go.etcd.io/bbolt/bolt_mips64x.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_mips64x.go rename to vendor/go.etcd.io/bbolt/bolt_mips64x.go diff --git a/vendor/etcd.io/bbolt/bolt_mipsx.go b/vendor/go.etcd.io/bbolt/bolt_mipsx.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_mipsx.go rename to vendor/go.etcd.io/bbolt/bolt_mipsx.go diff --git a/vendor/etcd.io/bbolt/bolt_openbsd.go b/vendor/go.etcd.io/bbolt/bolt_openbsd.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_openbsd.go rename to vendor/go.etcd.io/bbolt/bolt_openbsd.go diff --git a/vendor/etcd.io/bbolt/bolt_ppc.go b/vendor/go.etcd.io/bbolt/bolt_ppc.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_ppc.go rename to vendor/go.etcd.io/bbolt/bolt_ppc.go diff --git a/vendor/etcd.io/bbolt/bolt_ppc64.go b/vendor/go.etcd.io/bbolt/bolt_ppc64.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_ppc64.go rename to vendor/go.etcd.io/bbolt/bolt_ppc64.go diff --git a/vendor/etcd.io/bbolt/bolt_ppc64le.go b/vendor/go.etcd.io/bbolt/bolt_ppc64le.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_ppc64le.go rename to vendor/go.etcd.io/bbolt/bolt_ppc64le.go diff --git a/vendor/etcd.io/bbolt/bolt_riscv64.go b/vendor/go.etcd.io/bbolt/bolt_riscv64.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_riscv64.go rename to vendor/go.etcd.io/bbolt/bolt_riscv64.go diff --git a/vendor/etcd.io/bbolt/bolt_s390x.go b/vendor/go.etcd.io/bbolt/bolt_s390x.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_s390x.go rename to vendor/go.etcd.io/bbolt/bolt_s390x.go diff --git a/vendor/etcd.io/bbolt/bolt_unix.go b/vendor/go.etcd.io/bbolt/bolt_unix.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_unix.go rename to vendor/go.etcd.io/bbolt/bolt_unix.go diff --git a/vendor/etcd.io/bbolt/bolt_unix_aix.go b/vendor/go.etcd.io/bbolt/bolt_unix_aix.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_unix_aix.go rename to vendor/go.etcd.io/bbolt/bolt_unix_aix.go diff --git a/vendor/etcd.io/bbolt/bolt_unix_solaris.go b/vendor/go.etcd.io/bbolt/bolt_unix_solaris.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_unix_solaris.go rename to vendor/go.etcd.io/bbolt/bolt_unix_solaris.go diff --git a/vendor/etcd.io/bbolt/bolt_windows.go b/vendor/go.etcd.io/bbolt/bolt_windows.go similarity index 100% rename from vendor/etcd.io/bbolt/bolt_windows.go rename to vendor/go.etcd.io/bbolt/bolt_windows.go diff --git a/vendor/etcd.io/bbolt/boltsync_unix.go b/vendor/go.etcd.io/bbolt/boltsync_unix.go similarity index 100% rename from vendor/etcd.io/bbolt/boltsync_unix.go rename to vendor/go.etcd.io/bbolt/boltsync_unix.go diff --git a/vendor/etcd.io/bbolt/bucket.go b/vendor/go.etcd.io/bbolt/bucket.go similarity index 100% rename from vendor/etcd.io/bbolt/bucket.go rename to vendor/go.etcd.io/bbolt/bucket.go diff --git a/vendor/etcd.io/bbolt/bucket_test.go b/vendor/go.etcd.io/bbolt/bucket_test.go similarity index 100% rename from vendor/etcd.io/bbolt/bucket_test.go rename to vendor/go.etcd.io/bbolt/bucket_test.go diff --git a/vendor/etcd.io/bbolt/cmd/bbolt/main.go b/vendor/go.etcd.io/bbolt/cmd/bbolt/main.go similarity index 100% rename from vendor/etcd.io/bbolt/cmd/bbolt/main.go rename to vendor/go.etcd.io/bbolt/cmd/bbolt/main.go diff --git a/vendor/etcd.io/bbolt/cmd/bbolt/main_test b/vendor/go.etcd.io/bbolt/cmd/bbolt/main_test similarity index 100% rename from vendor/etcd.io/bbolt/cmd/bbolt/main_test rename to vendor/go.etcd.io/bbolt/cmd/bbolt/main_test diff --git a/vendor/etcd.io/bbolt/cursor.go b/vendor/go.etcd.io/bbolt/cursor.go similarity index 100% rename from vendor/etcd.io/bbolt/cursor.go rename to vendor/go.etcd.io/bbolt/cursor.go diff --git a/vendor/etcd.io/bbolt/cursor_test.go b/vendor/go.etcd.io/bbolt/cursor_test.go similarity index 100% rename from vendor/etcd.io/bbolt/cursor_test.go rename to vendor/go.etcd.io/bbolt/cursor_test.go diff --git a/vendor/etcd.io/bbolt/db.go b/vendor/go.etcd.io/bbolt/db.go similarity index 100% rename from vendor/etcd.io/bbolt/db.go rename to vendor/go.etcd.io/bbolt/db.go diff --git a/vendor/etcd.io/bbolt/db_test.go b/vendor/go.etcd.io/bbolt/db_test.go similarity index 100% rename from vendor/etcd.io/bbolt/db_test.go rename to vendor/go.etcd.io/bbolt/db_test.go diff --git a/vendor/etcd.io/bbolt/doc.go b/vendor/go.etcd.io/bbolt/doc.go similarity index 100% rename from vendor/etcd.io/bbolt/doc.go rename to vendor/go.etcd.io/bbolt/doc.go diff --git a/vendor/etcd.io/bbolt/errors.go b/vendor/go.etcd.io/bbolt/errors.go similarity index 100% rename from vendor/etcd.io/bbolt/errors.go rename to vendor/go.etcd.io/bbolt/errors.go diff --git a/vendor/etcd.io/bbolt/freelist.go b/vendor/go.etcd.io/bbolt/freelist.go similarity index 100% rename from vendor/etcd.io/bbolt/freelist.go rename to vendor/go.etcd.io/bbolt/freelist.go diff --git a/vendor/etcd.io/bbolt/freelist_hmap.go b/vendor/go.etcd.io/bbolt/freelist_hmap.go similarity index 100% rename from vendor/etcd.io/bbolt/freelist_hmap.go rename to vendor/go.etcd.io/bbolt/freelist_hmap.go diff --git a/vendor/etcd.io/bbolt/freelist_test.go b/vendor/go.etcd.io/bbolt/freelist_test.go similarity index 100% rename from vendor/etcd.io/bbolt/freelist_test.go rename to vendor/go.etcd.io/bbolt/freelist_test.go diff --git a/vendor/etcd.io/bbolt/go.mod b/vendor/go.etcd.io/bbolt/go.mod similarity index 100% rename from vendor/etcd.io/bbolt/go.mod rename to vendor/go.etcd.io/bbolt/go.mod diff --git a/vendor/etcd.io/bbolt/go.sum b/vendor/go.etcd.io/bbolt/go.sum similarity index 100% rename from vendor/etcd.io/bbolt/go.sum rename to vendor/go.etcd.io/bbolt/go.sum diff --git a/vendor/etcd.io/bbolt/manydbs_test.go b/vendor/go.etcd.io/bbolt/manydbs_test.go similarity index 100% rename from vendor/etcd.io/bbolt/manydbs_test.go rename to vendor/go.etcd.io/bbolt/manydbs_test.go diff --git a/vendor/etcd.io/bbolt/node.go b/vendor/go.etcd.io/bbolt/node.go similarity index 100% rename from vendor/etcd.io/bbolt/node.go rename to vendor/go.etcd.io/bbolt/node.go diff --git a/vendor/etcd.io/bbolt/node_test.go b/vendor/go.etcd.io/bbolt/node_test.go similarity index 100% rename from vendor/etcd.io/bbolt/node_test.go rename to vendor/go.etcd.io/bbolt/node_test.go diff --git a/vendor/etcd.io/bbolt/page.go b/vendor/go.etcd.io/bbolt/page.go similarity index 100% rename from vendor/etcd.io/bbolt/page.go rename to vendor/go.etcd.io/bbolt/page.go diff --git a/vendor/etcd.io/bbolt/page_test.go b/vendor/go.etcd.io/bbolt/page_test.go similarity index 100% rename from vendor/etcd.io/bbolt/page_test.go rename to vendor/go.etcd.io/bbolt/page_test.go diff --git a/vendor/etcd.io/bbolt/quick_test.go b/vendor/go.etcd.io/bbolt/quick_test.go similarity index 100% rename from vendor/etcd.io/bbolt/quick_test.go rename to vendor/go.etcd.io/bbolt/quick_test.go diff --git a/vendor/etcd.io/bbolt/simulation_no_freelist_sync_test.go b/vendor/go.etcd.io/bbolt/simulation_no_freelist_sync_test.go similarity index 100% rename from vendor/etcd.io/bbolt/simulation_no_freelist_sync_test.go rename to vendor/go.etcd.io/bbolt/simulation_no_freelist_sync_test.go diff --git a/vendor/etcd.io/bbolt/simulation_test.go b/vendor/go.etcd.io/bbolt/simulation_test.go similarity index 100% rename from vendor/etcd.io/bbolt/simulation_test.go rename to vendor/go.etcd.io/bbolt/simulation_test.go diff --git a/vendor/etcd.io/bbolt/tx.go b/vendor/go.etcd.io/bbolt/tx.go similarity index 100% rename from vendor/etcd.io/bbolt/tx.go rename to vendor/go.etcd.io/bbolt/tx.go diff --git a/vendor/etcd.io/bbolt/tx_test.go b/vendor/go.etcd.io/bbolt/tx_test.go similarity index 100% rename from vendor/etcd.io/bbolt/tx_test.go rename to vendor/go.etcd.io/bbolt/tx_test.go diff --git a/vendor/etcd.io/bbolt/unsafe.go b/vendor/go.etcd.io/bbolt/unsafe.go similarity index 100% rename from vendor/etcd.io/bbolt/unsafe.go rename to vendor/go.etcd.io/bbolt/unsafe.go diff --git a/walletapi/daemon_communication.go b/walletapi/daemon_communication.go index d9051eb8..539cf089 100644 --- a/walletapi/daemon_communication.go +++ b/walletapi/daemon_communication.go @@ -165,7 +165,6 @@ func test_connectivity() (err error) { if info.Testnet != !globals.IsMainnet() { err = fmt.Errorf("Mainnet/TestNet is different between wallet/daemon.Please run daemon/wallet without --testnet") logger.Error(err, "Mainnet/Testnet mismatch") - fmt.Printf("Mainnet/Testnet mismatch\n") return } @@ -174,18 +173,24 @@ func test_connectivity() (err error) { } daemon_height = info.Height daemon_topoheight = info.TopoHeight - logger.Info("successfully connected to daemon") + // logger.Info("connection is maintained") return nil } // triggers syncing with wallet every 5 seconds func (w *Wallet_Memory) sync_loop() { + //logger = globals.Logger for { select { case <-w.Quit: break default: + } + if w.account.lastsaved.IsZero() || time.Since(w.account.lastsaved) > w.account.SaveChangesEvery { + w.save_if_disk() // save wallet() + w.account.lastsaved = time.Now() + // w.db.Sync() } if IsDaemonOnline() && test_connectivity() != nil { @@ -195,13 +200,14 @@ func (w *Wallet_Memory) sync_loop() { var zerohash crypto.Hash if len(w.account.EntriesNative) == 0 { - err := w.Sync_Wallet_Memory_With_Daemon() - logger.V(1).Error(err, "wallet syncing err", err) + if err := w.Sync_Wallet_Memory_With_Daemon(); err != nil { + logger.Error(err, "wallet syncing err") + } } else { for k := range w.account.EntriesNative { err := w.Sync_Wallet_Memory_With_Daemon_internal(k) if k == zerohash && err != nil { - logger.V(1).Error(err, "wallet syncing err", err) + logger.Error(err, "wallet syncing err") } } } @@ -358,7 +364,6 @@ func (w *Wallet_Memory) GetSelfEncryptedBalanceAtTopoHeight(scid crypto.Hash, to // this can leak informtion which keyimage belongs to us // TODO in order to stop privacy leaks we must guess this information somehow on client side itself // maybe the server can broadcast a bloomfilter or something else from the mempool keyimages -// func (w *Wallet_Memory) GetEncryptedBalanceAtTopoHeight(scid crypto.Hash, topoheight int64, accountaddr string) (bits int, lastused uint64, blid crypto.Hash, e *crypto.ElGamal, err error) { defer func() { @@ -472,12 +477,6 @@ func (w *Wallet_Memory) GetDecryptedBalanceAtTopoHeight(scid crypto.Hash, topohe return 0, 0, err } - if w.account.EntriesNative != nil { - if _, ok := w.account.EntriesNative[scid]; !ok { //if we could obtain something, try tracking - w.account.EntriesNative[scid] = []rpc.Entry{} - } - } - return w.DecodeEncryptedBalance_Memory(encrypted_balance, 0), noncetopo, nil } @@ -521,6 +520,10 @@ func (w *Wallet_Memory) SyncHistory(scid crypto.Hash) (balance uint64) { entries := w.account.EntriesNative[scid] + logger.Info("syncing loop ", "total_entries", len(entries)) + + defer func() { logger.Info("syncing loop completed", "total_entries", len(w.account.EntriesNative[scid])) }() + // we need to find a sync point, to minimize traffic for i := len(entries) - 1; i >= 0; { @@ -528,46 +531,60 @@ func (w *Wallet_Memory) SyncHistory(scid crypto.Hash) (balance uint64) { if w.getEncryptedBalanceresult(scid).Registration >= entries[i].TopoHeight { // keep old history if chain got pruned break } - if last_topo_height == entries[i].TopoHeight { - i-- - } else { - last_topo_height = entries[i].TopoHeight + last_topo_height = entries[i].TopoHeight - var result rpc.GetBlockHeaderByHeight_Result + var result rpc.GetBlockHeaderByHeight_Result - // Issue a call with a response. - if err := rpc_client.Call("DERO.GetBlockHeaderByTopoHeight", rpc.GetBlockHeaderByTopoHeight_Params{TopoHeight: uint64(entries[i].TopoHeight)}, &result); err != nil { - logger.V(1).Error(err, "DERO.GetBlockHeaderByTopoHeight Call failed:") - return 0 - } + // Issue a call with a response. + if err := rpc_client.Call("DERO.GetBlockHeaderByTopoHeight", rpc.GetBlockHeaderByTopoHeight_Params{TopoHeight: uint64(entries[i].TopoHeight)}, &result); err != nil { + logger.V(1).Error(err, "DERO.GetBlockHeaderByTopoHeight Call failed:") + return 0 + } - if entries[i].BlockHash != result.Block_Header.Hash { - if i >= 1 && last_topo_height == entries[i-1].TopoHeight { // skipping any entries withing same block - for ; i >= 1; i-- { - if last_topo_height == entries[i-1].TopoHeight { - entries = entries[:i] - w.account.EntriesNative[scid] = entries - } + if result.Status != "OK" { + logger.Error(nil, "syncing loop status failed", "Status", result.Status, "topo", entries[i].TopoHeight) + return + } + + // wallet previous synced onto a side block chain / revert + if entries[i].BlockHash != result.Block_Header.Hash { + logger.Info("syncing loop header mismatch ", "i", i, "block_hash", entries[i].BlockHash) + skip := 1 + if i >= 1 && last_topo_height == entries[i-1].TopoHeight { // skipping any entries withing same block + for ; i >= 1; i-- { + if last_topo_height == entries[i-1].TopoHeight { + skip++ + } else { + break } } } + entries = entries[:i-skip] + w.account.EntriesNative[scid] = entries + logger.Info("syncing loop skipped ", "i", i, "skip", skip) + continue + } - if i == 0 { - w.account.EntriesNative[scid] = entries[:0] // discard all entries - break - } + if i <= 0 { + w.account.EntriesNative[scid] = entries[:0] // discard all entries + logger.Info("syncing loop discarding all entries", "i", i) + break + } - // we have found a matching block hash, start syncing from here - if result.Status == "OK" && result.Block_Header.Hash == entries[i].BlockHash { - w.synchistory_internal(scid, entries[i].TopoHeight+1, w.getEncryptedBalanceresult(scid).Topoheight) - return - } + // we have found a matching block hash, start syncing from here + if result.Block_Header.Hash == entries[i].BlockHash { + logger.Info("syncing loop from pos", "i", i, "start_topo", entries[i].TopoHeight+1, "end_topo", w.getEncryptedBalanceresult(scid).Topoheight) + + w.synchistory_internal(scid, entries[i].TopoHeight+1, w.getEncryptedBalanceresult(scid).Topoheight) + return } + return + } - //fmt.Printf("syncing loop using Registration %+v\n",w.getEncryptedBalanceresult(scid).Registration) + logger.Info("syncing loop using Registration", "registraion", w.getEncryptedBalanceresult(scid).Registration) // if we reached here, means we should sync from scratch w.synchistory_internal(scid, w.getEncryptedBalanceresult(scid).Registration, w.getEncryptedBalanceresult(scid).Topoheight) @@ -587,17 +604,25 @@ func (w *Wallet_Memory) SyncHistory(scid crypto.Hash) (balance uint64) { func (w *Wallet_Memory) synchistory_internal(scid crypto.Hash, start_topo, end_topo int64) error { var err error var start_balance_e *crypto.ElGamal + + logger.Info("syncing loop starting internal ", "start_topo", start_topo, "end_topo", end_topo) + + if w.account.TrackRecentBlocks > 0 && daemon_topoheight >= w.account.TrackRecentBlocks { + start_topo = daemon_topoheight - w.account.TrackRecentBlocks + } if start_topo == w.getEncryptedBalanceresult(scid).Registration { start_balance_e = crypto.ConstructElGamal(w.account.Keys.Public.G1(), crypto.ElGamal_BASE_G) } else { _, _, _, start_balance_e, err = w.GetEncryptedBalanceAtTopoHeight(scid, start_topo, w.GetAddress().String()) if err != nil { + logger.Error(err, "syncing info failed", "start_topo", start_topo) return err } } _, _, _, end_balance_e, err := w.GetEncryptedBalanceAtTopoHeight(scid, end_topo, w.GetAddress().String()) if err != nil { + logger.Error(err, "syncing info failed", "end_topo", end_topo) return err } @@ -615,31 +640,35 @@ func (w *Wallet_Memory) synchistory_internal_binary_search(level int, scid crypt return fmt.Errorf("done") } - /* if bytes.Compare(start_balance_e.Serialize(), end_balance_e.Serialize()) == 0 { - return nil - } - */ + //if bytes.Compare(start_balance_e.Serialize(), end_balance_e.Serialize()) == 0 { + // logger.Info("syncing loop same encrypted data so skipping ","start_topo",start_topo, "end_topo",end_topo) + // return nil + //} defer globals.Recover(0) //for start_topo <= end_topo{ { median := (start_topo + end_topo) / 2 - //fmt.Printf("%slevel %d low %d high %d median %d\n", strings.Repeat("\t", level), level, start_topo, end_topo, median) + // fmt.Printf("%slevel %d low %d high %d median %d\n", strings.Repeat("\t", level), level, start_topo, end_topo, median) if start_topo == median { if err = w.synchistory_block(scid, start_topo); err != nil { + logger.Error(err, "syncing block failed", "start_topo", start_topo) return err } } if end_topo-start_topo <= 1 { - err = w.synchistory_block(scid, end_topo) - return err + if err = w.synchistory_block(scid, end_topo); err != nil { + logger.Error(err, "syncing block failed", "end_topo", end_topo) + return err + } + return nil } _, _, _, median_balance_e, err := w.GetEncryptedBalanceAtTopoHeight(scid, median, w.GetAddress().String()) if err != nil { - fmt.Printf("getting block err %s\n", err) + logger.Error(err, "syncing block getting balance failed", "median", median) return err } @@ -648,6 +677,7 @@ func (w *Wallet_Memory) synchistory_internal_binary_search(level int, scid crypt if start_topo == w.getEncryptedBalanceresult(scid).Registration || bytes.Compare(start_balance_e.Serialize(), median_balance_e.Serialize()) != 0 { err = w.synchistory_internal_binary_search(level+1, scid, start_topo, start_balance_e, median, median_balance_e) if err != nil { + logger.Error(err, "syncing block synchistory_internal_binary_search failed", "level+1", level+1, "start_topo", start_topo, "median", median) return err } } @@ -657,6 +687,7 @@ func (w *Wallet_Memory) synchistory_internal_binary_search(level int, scid crypt if bytes.Compare(median_balance_e.Serialize(), end_balance_e.Serialize()) != 0 { err = w.synchistory_internal_binary_search(level+1, scid, median, median_balance_e, end_topo, end_balance_e) if err != nil { + logger.Error(err, "syncing block synchistory_internal_binary_search failed", "level+1", level+1, "median", median, "end_topo", end_topo) return err } } @@ -688,6 +719,7 @@ func (w *Wallet_Memory) synchistory_block(scid crypto.Hash, topo int64) (err err } } + //logger.Info("syncing block", "topo", topo) _, _, _, current_balance_e, err = w.GetEncryptedBalanceAtTopoHeight(scid, topo, w.GetAddress().String()) if err != nil { return err @@ -961,13 +993,16 @@ func (w *Wallet_Memory) synchistory_block(scid crypto.Hash, topo int64) (err err //fmt.Printf("decoding encrypted payload %x\n",tx.Payloads[t].RPCPayload) crypto.EncryptDecryptUserData(crypto.Keccak256(shared_key[:], w.GetAddress().PublicKey.EncodeCompressed()), tx.Payloads[t].RPCPayload) //fmt.Printf("decoded plaintext payload %x\n",tx.Payloads[t].RPCPayload) - + sender_idx := uint(tx.Payloads[t].RPCPayload[0]) // if ring size is 2, the other party is the sender so mark it so if uint(tx.Payloads[t].Statement.RingSize) == 2 { - sender_idx := 0 + sender_idx = 0 if j == 0 { sender_idx = 1 } + } + + if sender_idx <= uint(tx.Payloads[t].Statement.RingSize) { addr := rpc.NewAddressFromKeys((*crypto.Point)(tx.Payloads[t].Statement.Publickeylist[sender_idx])) addr.Mainnet = w.GetNetwork() entry.Sender = addr.String() diff --git a/walletapi/wallet.go b/walletapi/wallet.go index 9b2954d9..d0a52cf5 100644 --- a/walletapi/wallet.go +++ b/walletapi/wallet.go @@ -16,9 +16,11 @@ package walletapi +import "os" import "fmt" import "sort" import "sync" +import "time" import "strings" import "math/big" import "crypto/rand" @@ -69,6 +71,12 @@ type Account struct { RingMembers map[string]int64 `json:"ring_members"` // ring members + SaveChangesEvery time.Duration `json:"-"` // default is zero + lastsaved time.Time + + // do not build entire history from 0, only maintain top history + TrackRecentBlocks int64 `json:"-"` // only scan top blocks, default is zero, means everything + sync.Mutex // syncronise modifications to this structure } @@ -219,7 +227,7 @@ func (w *Wallet_Memory) Get_Balance() (mature_balance uint64, locked_balance uin // TODO this code can be easily parallelised and need to be parallelised // if only the availble is requested, then the wallet is very fast // the spent tracking may make it slow ( in case of large probably million txs ) -//TODO currently we do not track POOL at all any where ( except while building tx) +// TODO currently we do not track POOL at all any where ( except while building tx) // if payment_id is true, only entries with payment ids are returned // min_height/max height represent topoheight func (w *Wallet_Memory) Show_Transfers(scid crypto.Hash, coinbase bool, in bool, out bool, min_height, max_height uint64, sender, receiver string, dstport, srcport uint64) []rpc.Entry { @@ -269,7 +277,8 @@ func (w *Wallet_Memory) Get_Payments_Payment_ID(scid crypto.Hash, dst_port uint6 // gets all the payments done to specific payment ID and filtered by specific block height // we do need better rpc func (w *Wallet_Memory) Get_Payments_DestinationPort(scid crypto.Hash, port uint64, min_height uint64) (entries []rpc.Entry) { - + w.Lock() + defer w.Unlock() all_entries := w.account.EntriesNative[scid] if all_entries == nil || len(all_entries) < 1 { return @@ -288,6 +297,9 @@ func (w *Wallet_Memory) Get_Payments_DestinationPort(scid crypto.Hash, port uint // return all payments within a tx there can be only 1 entry // NOTE: what about multiple payments func (w *Wallet_Memory) Get_Payments_TXID(txid string) (entry rpc.Entry) { + w.Lock() + defer w.Unlock() + var zerohash crypto.Hash all_entries := w.account.EntriesNative[zerohash] if all_entries == nil || len(all_entries) < 1 { @@ -306,6 +318,8 @@ func (w *Wallet_Memory) Get_Payments_TXID(txid string) (entry rpc.Entry) { // delete most of the data and prepare for rescan // TODO we must save tokens list and reuse, them, but will be created on-demand when using shows transfers/or rpc apis func (w *Wallet_Memory) Clean() { + w.Lock() + defer w.Unlock() //w.account.Entries = w.account.Entries[:0] for k := range w.account.EntriesNative { @@ -466,6 +480,35 @@ func (w *Wallet_Memory) GetSeedLanguage() string { return w.account.SeedLanguage } +// Ability to set save frequency to lower disc write frequency +// a negative set value, will return existing value, +// 0 is a valid value and is set to default +// this is supposed to be used in very specific/special conditions and generally need not be changed +func (w *Wallet_Memory) SetSaveDuration(saveevery time.Duration) (old time.Duration) { + old = w.account.SaveChangesEvery + if saveevery >= 0 { + if saveevery.Seconds() > 3600 { + saveevery = 3600 * time.Second + } + w.account.SaveChangesEvery = saveevery + defer w.save_if_disk() // save wallet now so as settting become permanent + } + return +} + +// Ability to set wallet scanning +// a negative set value, will return existing value, +// 0 is a valid value and is set to default and will scan entire history +// this is supposed to be used in very specific/special conditions and generally need not be changed +func (w *Wallet_Memory) SetTrackRecentBlocks(recency int64) (old int64) { + old = w.account.TrackRecentBlocks + if recency >= 0 { + w.account.TrackRecentBlocks = recency + defer w.save_if_disk() // save wallet now so as settting become permanent + } + return +} + // retrieve secret key for any tx we may have created func (w *Wallet_Memory) GetRegistrationTX() *transaction.Transaction { var tx transaction.Transaction @@ -515,7 +558,6 @@ func (w *Wallet_Memory) GetTXKey(txhash string) string { // never do any division operation on money due to floating point issues // newbies, see type the next in python interpretor "3.33-3.13" -// func FormatMoney(amount uint64) string { return FormatMoneyPrecision(amount, 5) // default is 5 precision after floating point } @@ -595,3 +637,87 @@ func (w *Wallet_Memory) CheckSignature(input []byte) (signer *rpc.Address, messa message = p.Bytes return } + +// this basically does a Schnorr Signature on random information for registration +// NOTE: this function brings entire file to RAM 2 times, this could be removed by refactoring this function +// NOTE: a similar function which wraps data already exists in wallet.go just above this function +func (w *Wallet_Memory) SignFile(filename string) error { + var tmppoint bn256.G1 + + tmpsecret := crypto.RandomScalar() + tmppoint.ScalarMult(crypto.G, tmpsecret) + + input, err := os.ReadFile(filename) + if err != nil { + return err + } + + serialize := []byte(fmt.Sprintf("%s%s%x", w.account.Keys.Public.G1().String(), tmppoint.String(), input)) + + c := crypto.ReducedHash(serialize) + s := new(big.Int).Mul(c, w.account.Keys.Secret.BigInt()) // basicaly scalar mul add + s = s.Mod(s, bn256.Order) + s = s.Add(s, tmpsecret) + s = s.Mod(s, bn256.Order) + + p := &pem.Block{Type: "DERO SIGNED MESSAGE"} + p.Headers = map[string]string{} + p.Headers["Address"] = w.GetAddress().String() + p.Headers["C"] = fmt.Sprintf("%x", c) + p.Headers["S"] = fmt.Sprintf("%x", s) + + return os.WriteFile(filename+".signed", pem.EncodeToMemory(p), 0600) +} + +func (w *Wallet_Memory) CheckFileSignature(filename string) (signer *rpc.Address, err error) { + + input, err := os.ReadFile(filename + ".signed") + if err != nil { + return + } + + p, _ := pem.Decode(input) + if p == nil { + err = fmt.Errorf("Unknown format") + return + } + + astr := p.Headers["Address"] + cstr := p.Headers["C"] + sstr := p.Headers["S"] + + addr, err := rpc.NewAddress(astr) + if err != nil { + return + } + + c, ok := new(big.Int).SetString(cstr, 16) + if !ok { + err = fmt.Errorf("Unknown C format") + return + } + + s, ok := new(big.Int).SetString(sstr, 16) + if !ok { + err = fmt.Errorf("Unknown S format") + return + } + + tmppoint := new(bn256.G1).Add(new(bn256.G1).ScalarMult(crypto.G, s), new(bn256.G1).ScalarMult(addr.PublicKey.G1(), new(big.Int).Neg(c))) + + input_data, err := os.ReadFile(filename) + if err != nil { + return + } + + serialize := []byte(fmt.Sprintf("%s%s%x", addr.PublicKey.G1().String(), tmppoint.String(), input_data)) + + c_calculated := crypto.ReducedHash(serialize) + if c.String() != c_calculated.String() { + err = fmt.Errorf("signature mismatch") + return + } + + signer = addr + return +} diff --git a/walletapi/wallet_memory.go b/walletapi/wallet_memory.go index c1a299e0..37e5a147 100644 --- a/walletapi/wallet_memory.go +++ b/walletapi/wallet_memory.go @@ -83,6 +83,8 @@ type Wallet_Memory struct { transfer_mutex sync.Mutex // to avoid races within the transfer //sync.Mutex // used to syncronise access sync.RWMutex + + sync_in_progress sync.Mutex // whether sync is in progress } // when smart contracts are implemented, each will have it's own universe to track and maintain transactions